1*fd9871f7SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 26a7eba24SJean-Francois Moine /* 3cd8955b8SJean-François Moine * T613 subdriver 4cd8955b8SJean-François Moine * 5cd8955b8SJean-François Moine * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr) 66a7eba24SJean-Francois Moine * 710b0e96eSJean-Francois Moine *Notes: * t613 + tas5130A 810b0e96eSJean-Francois Moine * * Focus to light do not balance well as in win. 910b0e96eSJean-Francois Moine * Quality in win is not good, but its kinda better. 1010b0e96eSJean-Francois Moine * * Fix some "extraneous bytes", most of apps will show the image anyway 1110b0e96eSJean-Francois Moine * * Gamma table, is there, but its really doing something? 1210b0e96eSJean-Francois Moine * * 7~8 Fps, its ok, max on win its 10. 1310b0e96eSJean-Francois Moine * Costantino Leandro 146a7eba24SJean-Francois Moine */ 156a7eba24SJean-Francois Moine 161b19e429SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 171b19e429SJoe Perches 186a7eba24SJean-Francois Moine #define MODULE_NAME "t613" 1910b0e96eSJean-Francois Moine 20ee186fd9SHans de Goede #include <linux/input.h> 21be2a9faeSJean-François Moine #include <linux/slab.h> 226a7eba24SJean-Francois Moine #include "gspca.h" 236a7eba24SJean-Francois Moine 246a7eba24SJean-Francois Moine MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>"); 256a7eba24SJean-Francois Moine MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver"); 266a7eba24SJean-Francois Moine MODULE_LICENSE("GPL"); 276a7eba24SJean-Francois Moine 286a7eba24SJean-Francois Moine struct sd { 296a7eba24SJean-Francois Moine struct gspca_dev gspca_dev; /* !! must be the first item */ 309bf81642SHans Verkuil struct v4l2_ctrl *freq; 319bf81642SHans Verkuil struct { /* awb / color gains control cluster */ 329bf81642SHans Verkuil struct v4l2_ctrl *awb; 339bf81642SHans Verkuil struct v4l2_ctrl *gain; 349bf81642SHans Verkuil struct v4l2_ctrl *red_balance; 359bf81642SHans Verkuil struct v4l2_ctrl *blue_balance; 369bf81642SHans Verkuil }; 37fadc7993SJean-Francois Moine 3882e25491SJean-Francois Moine u8 sensor; 39ee186fd9SHans de Goede u8 button_pressed; 4011ce884aSJean-François Moine }; 4111ce884aSJean-François Moine enum sensors { 42cd8955b8SJean-François Moine SENSOR_OM6802, 43cd8955b8SJean-François Moine SENSOR_OTHER, 44cd8955b8SJean-François Moine SENSOR_TAS5130A, 45cd8955b8SJean-François Moine SENSOR_LT168G, /* must verify if this is the actual model */ 466a7eba24SJean-Francois Moine }; 476a7eba24SJean-Francois Moine 48cc611b8aSJean-Francois Moine static const struct v4l2_pix_format vga_mode_t16[] = { 49c2446b3eSJean-Francois Moine {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 50c2446b3eSJean-Francois Moine .bytesperline = 160, 515d05294aSJean-Francois Moine .sizeimage = 160 * 120 * 4 / 8 + 590, 52c2446b3eSJean-Francois Moine .colorspace = V4L2_COLORSPACE_JPEG, 53c2446b3eSJean-Francois Moine .priv = 4}, 541ea172d2SHans de Goede #if 0 /* HDG: broken with my test cam, so lets disable it */ 55c2446b3eSJean-Francois Moine {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 56c2446b3eSJean-Francois Moine .bytesperline = 176, 57c2446b3eSJean-Francois Moine .sizeimage = 176 * 144 * 3 / 8 + 590, 58c2446b3eSJean-Francois Moine .colorspace = V4L2_COLORSPACE_JPEG, 59c2446b3eSJean-Francois Moine .priv = 3}, 601ea172d2SHans de Goede #endif 61c2446b3eSJean-Francois Moine {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 62c2446b3eSJean-Francois Moine .bytesperline = 320, 63c2446b3eSJean-Francois Moine .sizeimage = 320 * 240 * 3 / 8 + 590, 64c2446b3eSJean-Francois Moine .colorspace = V4L2_COLORSPACE_JPEG, 65c2446b3eSJean-Francois Moine .priv = 2}, 661ea172d2SHans de Goede #if 0 /* HDG: broken with my test cam, so lets disable it */ 67c2446b3eSJean-Francois Moine {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 68c2446b3eSJean-Francois Moine .bytesperline = 352, 69c2446b3eSJean-Francois Moine .sizeimage = 352 * 288 * 3 / 8 + 590, 70c2446b3eSJean-Francois Moine .colorspace = V4L2_COLORSPACE_JPEG, 71c2446b3eSJean-Francois Moine .priv = 1}, 721ea172d2SHans de Goede #endif 73c2446b3eSJean-Francois Moine {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 74c2446b3eSJean-Francois Moine .bytesperline = 640, 75c2446b3eSJean-Francois Moine .sizeimage = 640 * 480 * 3 / 8 + 590, 76c2446b3eSJean-Francois Moine .colorspace = V4L2_COLORSPACE_JPEG, 77c2446b3eSJean-Francois Moine .priv = 0}, 786a7eba24SJean-Francois Moine }; 796a7eba24SJean-Francois Moine 80ad62fb08SLeandro Costantino /* sensor specific data */ 81ad62fb08SLeandro Costantino struct additional_sensor_data { 8278a6d74eSJean-Francois Moine const u8 n3[6]; 8378a6d74eSJean-Francois Moine const u8 *n4, n4sz; 8478a6d74eSJean-Francois Moine const u8 reg80, reg8e; 8578a6d74eSJean-Francois Moine const u8 nset8[6]; 8682e25491SJean-Francois Moine const u8 data1[10]; 8782e25491SJean-Francois Moine const u8 data2[9]; 8882e25491SJean-Francois Moine const u8 data3[9]; 8982e25491SJean-Francois Moine const u8 data5[6]; 9082e25491SJean-Francois Moine const u8 stream[4]; 91ad62fb08SLeandro Costantino }; 92ad62fb08SLeandro Costantino 9378a6d74eSJean-Francois Moine static const u8 n4_om6802[] = { 9478a6d74eSJean-Francois Moine 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, 9578a6d74eSJean-Francois Moine 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, 9678a6d74eSJean-Francois Moine 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1, 9778a6d74eSJean-Francois Moine 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8, 9878a6d74eSJean-Francois Moine 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48, 9978a6d74eSJean-Francois Moine 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0, 10078a6d74eSJean-Francois Moine 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, 10178a6d74eSJean-Francois Moine 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, 10278a6d74eSJean-Francois Moine 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46 10378a6d74eSJean-Francois Moine }; 10478a6d74eSJean-Francois Moine static const u8 n4_other[] = { 10578a6d74eSJean-Francois Moine 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69, 10678a6d74eSJean-Francois Moine 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68, 10778a6d74eSJean-Francois Moine 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8, 10878a6d74eSJean-Francois Moine 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8, 10978a6d74eSJean-Francois Moine 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56, 11078a6d74eSJean-Francois Moine 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5, 11178a6d74eSJean-Francois Moine 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0, 11278a6d74eSJean-Francois Moine 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00 11378a6d74eSJean-Francois Moine }; 11478a6d74eSJean-Francois Moine static const u8 n4_tas5130a[] = { 11578a6d74eSJean-Francois Moine 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20, 11678a6d74eSJean-Francois Moine 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4, 11778a6d74eSJean-Francois Moine 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10, 11878a6d74eSJean-Francois Moine 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08, 11978a6d74eSJean-Francois Moine 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a, 12078a6d74eSJean-Francois Moine 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8, 12178a6d74eSJean-Francois Moine 0xc6, 0xda 12278a6d74eSJean-Francois Moine }; 12300e8006dSNicolau Werneck static const u8 n4_lt168g[] = { 12400e8006dSNicolau Werneck 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28, 12500e8006dSNicolau Werneck 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70, 12600e8006dSNicolau Werneck 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3, 12700e8006dSNicolau Werneck 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20, 12800e8006dSNicolau Werneck 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68, 12900e8006dSNicolau Werneck 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40, 13000e8006dSNicolau Werneck 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0, 13100e8006dSNicolau Werneck 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c, 13200e8006dSNicolau Werneck 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80 13300e8006dSNicolau Werneck }; 13478a6d74eSJean-Francois Moine 135e23b2907STobias Klauser static const struct additional_sensor_data sensor_data[] = { 136cd8955b8SJean-François Moine [SENSOR_OM6802] = { 13778a6d74eSJean-Francois Moine .n3 = 13878a6d74eSJean-Francois Moine {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}, 13978a6d74eSJean-Francois Moine .n4 = n4_om6802, 14078a6d74eSJean-Francois Moine .n4sz = sizeof n4_om6802, 14178a6d74eSJean-Francois Moine .reg80 = 0x3c, 14278a6d74eSJean-Francois Moine .reg8e = 0x33, 14378a6d74eSJean-Francois Moine .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00}, 1442d56f3bbSJean-Francois Moine .data1 = 1452d56f3bbSJean-Francois Moine {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06, 1462d56f3bbSJean-Francois Moine 0xb3, 0xfc}, 1472d56f3bbSJean-Francois Moine .data2 = 1482d56f3bbSJean-Francois Moine {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 1492d56f3bbSJean-Francois Moine 0xff}, 15078a6d74eSJean-Francois Moine .data3 = 15178a6d74eSJean-Francois Moine {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 15278a6d74eSJean-Francois Moine 0xff}, 1532d56f3bbSJean-Francois Moine .data5 = /* this could be removed later */ 1542d56f3bbSJean-Francois Moine {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23}, 1552d56f3bbSJean-Francois Moine .stream = 1562d56f3bbSJean-Francois Moine {0x0b, 0x04, 0x0a, 0x78}, 1572d56f3bbSJean-Francois Moine }, 158cd8955b8SJean-François Moine [SENSOR_OTHER] = { 15978a6d74eSJean-Francois Moine .n3 = 16078a6d74eSJean-Francois Moine {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00}, 16178a6d74eSJean-Francois Moine .n4 = n4_other, 16278a6d74eSJean-Francois Moine .n4sz = sizeof n4_other, 16378a6d74eSJean-Francois Moine .reg80 = 0xac, 16478a6d74eSJean-Francois Moine .reg8e = 0xb8, 16578a6d74eSJean-Francois Moine .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00}, 1662d56f3bbSJean-Francois Moine .data1 = 1672d56f3bbSJean-Francois Moine {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a, 1682d56f3bbSJean-Francois Moine 0xe8, 0xfc}, 1692d56f3bbSJean-Francois Moine .data2 = 1702d56f3bbSJean-Francois Moine {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96, 1712d56f3bbSJean-Francois Moine 0xd9}, 17278a6d74eSJean-Francois Moine .data3 = 17378a6d74eSJean-Francois Moine {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96, 17478a6d74eSJean-Francois Moine 0xd9}, 1752d56f3bbSJean-Francois Moine .data5 = 1762d56f3bbSJean-Francois Moine {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69}, 1772d56f3bbSJean-Francois Moine .stream = 1782d56f3bbSJean-Francois Moine {0x0b, 0x04, 0x0a, 0x00}, 1792d56f3bbSJean-Francois Moine }, 180cd8955b8SJean-François Moine [SENSOR_TAS5130A] = { 18178a6d74eSJean-Francois Moine .n3 = 18278a6d74eSJean-Francois Moine {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08}, 18378a6d74eSJean-Francois Moine .n4 = n4_tas5130a, 18478a6d74eSJean-Francois Moine .n4sz = sizeof n4_tas5130a, 18578a6d74eSJean-Francois Moine .reg80 = 0x3c, 18678a6d74eSJean-Francois Moine .reg8e = 0xb4, 18778a6d74eSJean-Francois Moine .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00}, 188ad62fb08SLeandro Costantino .data1 = 18982e25491SJean-Francois Moine {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27, 19082e25491SJean-Francois Moine 0xc8, 0xfc}, 191ad62fb08SLeandro Costantino .data2 = 19282e25491SJean-Francois Moine {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, 19382e25491SJean-Francois Moine 0xe0}, 19478a6d74eSJean-Francois Moine .data3 = 19578a6d74eSJean-Francois Moine {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, 19678a6d74eSJean-Francois Moine 0xe0}, 197ad62fb08SLeandro Costantino .data5 = 198ad62fb08SLeandro Costantino {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20}, 199ad62fb08SLeandro Costantino .stream = 200ad62fb08SLeandro Costantino {0x0b, 0x04, 0x0a, 0x40}, 201ad62fb08SLeandro Costantino }, 202cd8955b8SJean-François Moine [SENSOR_LT168G] = { 20300e8006dSNicolau Werneck .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00}, 20400e8006dSNicolau Werneck .n4 = n4_lt168g, 20500e8006dSNicolau Werneck .n4sz = sizeof n4_lt168g, 20600e8006dSNicolau Werneck .reg80 = 0x7c, 20700e8006dSNicolau Werneck .reg8e = 0xb3, 20800e8006dSNicolau Werneck .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00}, 20900e8006dSNicolau Werneck .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40, 21000e8006dSNicolau Werneck 0xb0, 0xf4}, 21100e8006dSNicolau Werneck .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, 21200e8006dSNicolau Werneck 0xff}, 21300e8006dSNicolau Werneck .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, 21400e8006dSNicolau Werneck 0xff}, 21500e8006dSNicolau Werneck .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b}, 21600e8006dSNicolau Werneck .stream = {0x0b, 0x04, 0x0a, 0x28}, 21700e8006dSNicolau Werneck }, 218ad62fb08SLeandro Costantino }; 219ad62fb08SLeandro Costantino 2206a7eba24SJean-Francois Moine #define MAX_EFFECTS 7 22182e25491SJean-Francois Moine static const u8 effects_table[MAX_EFFECTS][6] = { 2226a7eba24SJean-Francois Moine {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */ 2236a7eba24SJean-Francois Moine {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */ 2246a7eba24SJean-Francois Moine {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */ 2256a7eba24SJean-Francois Moine {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */ 2266a7eba24SJean-Francois Moine {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */ 2276a7eba24SJean-Francois Moine {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */ 2286a7eba24SJean-Francois Moine {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */ 2296a7eba24SJean-Francois Moine }; 2306a7eba24SJean-Francois Moine 2319bf81642SHans Verkuil #define GAMMA_MAX (15) 2329bf81642SHans Verkuil static const u8 gamma_table[GAMMA_MAX+1][17] = { 23379960d39SJean-François Moine /* gamma table from cam1690.ini */ 23479960d39SJean-François Moine {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */ 23579960d39SJean-François Moine 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb, 23682e25491SJean-Francois Moine 0xff}, 23779960d39SJean-François Moine {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */ 23879960d39SJean-François Moine 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1, 23982e25491SJean-Francois Moine 0xff}, 24079960d39SJean-François Moine {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */ 24179960d39SJean-François Moine 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3, 24282e25491SJean-Francois Moine 0xff}, 24379960d39SJean-François Moine {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */ 24479960d39SJean-François Moine 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6, 24582e25491SJean-Francois Moine 0xff}, 2461d00d6c1SJean-François Moine {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */ 24779960d39SJean-François Moine 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9, 24882e25491SJean-Francois Moine 0xff}, 24979960d39SJean-François Moine {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */ 25079960d39SJean-François Moine 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec, 25182e25491SJean-Francois Moine 0xff}, 25279960d39SJean-François Moine {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */ 25382e25491SJean-Francois Moine 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 25482e25491SJean-Francois Moine 0xff}, 25579960d39SJean-François Moine {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */ 25682e25491SJean-Francois Moine 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 25782e25491SJean-Francois Moine 0xff}, 25879960d39SJean-François Moine {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */ 25979960d39SJean-François Moine 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0, 26082e25491SJean-Francois Moine 0xff}, 26179960d39SJean-François Moine {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */ 26279960d39SJean-François Moine 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2, 26382e25491SJean-Francois Moine 0xff}, 26479960d39SJean-François Moine {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */ 26579960d39SJean-François Moine 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3, 26682e25491SJean-Francois Moine 0xff}, 26779960d39SJean-François Moine {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */ 26882e25491SJean-Francois Moine 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5, 26982e25491SJean-Francois Moine 0xff}, 27082e25491SJean-Francois Moine {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */ 27182e25491SJean-Francois Moine 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6, 27282e25491SJean-Francois Moine 0xff}, 27382e25491SJean-Francois Moine {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */ 27482e25491SJean-Francois Moine 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9, 27582e25491SJean-Francois Moine 0xff}, 27682e25491SJean-Francois Moine {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */ 27782e25491SJean-Francois Moine 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa, 27882e25491SJean-Francois Moine 0xff}, 27982e25491SJean-Francois Moine {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */ 28082e25491SJean-Francois Moine 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc, 28182e25491SJean-Francois Moine 0xff} 2826a7eba24SJean-Francois Moine }; 2836a7eba24SJean-Francois Moine 28482e25491SJean-Francois Moine static const u8 tas5130a_sensor_init[][8] = { 2856a7eba24SJean-Francois Moine {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09}, 2866a7eba24SJean-Francois Moine {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09}, 2876a7eba24SJean-Francois Moine {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}, 2886a7eba24SJean-Francois Moine }; 2896a7eba24SJean-Francois Moine 29082e25491SJean-Francois Moine static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07}; 291392ee5a5SJean-Francois Moine 292739570bbSJean-Francois Moine /* read 1 byte */ 29382e25491SJean-Francois Moine static u8 reg_r(struct gspca_dev *gspca_dev, 29482e25491SJean-Francois Moine u16 index) 2956a7eba24SJean-Francois Moine { 296739570bbSJean-Francois Moine usb_control_msg(gspca_dev->dev, 297739570bbSJean-Francois Moine usb_rcvctrlpipe(gspca_dev->dev, 0), 2986a7eba24SJean-Francois Moine 0, /* request */ 2996a7eba24SJean-Francois Moine USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 3006a7eba24SJean-Francois Moine 0, /* value */ 301739570bbSJean-Francois Moine index, 302739570bbSJean-Francois Moine gspca_dev->usb_buf, 1, 500); 303739570bbSJean-Francois Moine return gspca_dev->usb_buf[0]; 3046a7eba24SJean-Francois Moine } 3056a7eba24SJean-Francois Moine 306739570bbSJean-Francois Moine static void reg_w(struct gspca_dev *gspca_dev, 30782e25491SJean-Francois Moine u16 index) 3086a7eba24SJean-Francois Moine { 309739570bbSJean-Francois Moine usb_control_msg(gspca_dev->dev, 310739570bbSJean-Francois Moine usb_sndctrlpipe(gspca_dev->dev, 0), 311a5ae2062SJean-Francois Moine 0, 3120bc99b5cSJean-Francois Moine USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 313fadc7993SJean-Francois Moine 0, index, 314a5ae2062SJean-Francois Moine NULL, 0, 500); 315bf7f0b98SJean-Francois Moine } 316fadc7993SJean-Francois Moine 317f89be036SJean-Francois Moine static void reg_w_buf(struct gspca_dev *gspca_dev, 31882e25491SJean-Francois Moine const u8 *buffer, u16 len) 319fadc7993SJean-Francois Moine { 3208295d99eSJean-Francois Moine if (len <= USB_BUF_SZ) { 321739570bbSJean-Francois Moine memcpy(gspca_dev->usb_buf, buffer, len); 322739570bbSJean-Francois Moine usb_control_msg(gspca_dev->dev, 323739570bbSJean-Francois Moine usb_sndctrlpipe(gspca_dev->dev, 0), 324a5ae2062SJean-Francois Moine 0, 3250bc99b5cSJean-Francois Moine USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 326fadc7993SJean-Francois Moine 0x01, 0, 327739570bbSJean-Francois Moine gspca_dev->usb_buf, len, 500); 328a5ae2062SJean-Francois Moine } else { 32982e25491SJean-Francois Moine u8 *tmpbuf; 330a5ae2062SJean-Francois Moine 331feda79bfSJulia Lawall tmpbuf = kmemdup(buffer, len, GFP_KERNEL); 33224f222e7SJean-François Moine if (!tmpbuf) { 3331b19e429SJoe Perches pr_err("Out of memory\n"); 33424f222e7SJean-François Moine return; 33524f222e7SJean-François Moine } 336739570bbSJean-Francois Moine usb_control_msg(gspca_dev->dev, 337739570bbSJean-Francois Moine usb_sndctrlpipe(gspca_dev->dev, 0), 338a5ae2062SJean-Francois Moine 0, 3390bc99b5cSJean-Francois Moine USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 340fadc7993SJean-Francois Moine 0x01, 0, 341a5ae2062SJean-Francois Moine tmpbuf, len, 500); 342a5ae2062SJean-Francois Moine kfree(tmpbuf); 343a5ae2062SJean-Francois Moine } 3446a7eba24SJean-Francois Moine } 3456a7eba24SJean-Francois Moine 34682e25491SJean-Francois Moine /* write values to consecutive registers */ 34782e25491SJean-Francois Moine static void reg_w_ixbuf(struct gspca_dev *gspca_dev, 34882e25491SJean-Francois Moine u8 reg, 34982e25491SJean-Francois Moine const u8 *buffer, u16 len) 35082e25491SJean-Francois Moine { 35182e25491SJean-Francois Moine int i; 35282e25491SJean-Francois Moine u8 *p, *tmpbuf; 35382e25491SJean-Francois Moine 35424f222e7SJean-François Moine if (len * 2 <= USB_BUF_SZ) { 35582e25491SJean-Francois Moine p = tmpbuf = gspca_dev->usb_buf; 35624f222e7SJean-François Moine } else { 3576da2ec56SKees Cook p = tmpbuf = kmalloc_array(len, 2, GFP_KERNEL); 35824f222e7SJean-François Moine if (!tmpbuf) { 3591b19e429SJoe Perches pr_err("Out of memory\n"); 36024f222e7SJean-François Moine return; 36124f222e7SJean-François Moine } 36224f222e7SJean-François Moine } 36382e25491SJean-Francois Moine i = len; 36482e25491SJean-Francois Moine while (--i >= 0) { 36582e25491SJean-Francois Moine *p++ = reg++; 36682e25491SJean-Francois Moine *p++ = *buffer++; 36782e25491SJean-Francois Moine } 36882e25491SJean-Francois Moine usb_control_msg(gspca_dev->dev, 36982e25491SJean-Francois Moine usb_sndctrlpipe(gspca_dev->dev, 0), 37082e25491SJean-Francois Moine 0, 37182e25491SJean-Francois Moine USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 37282e25491SJean-Francois Moine 0x01, 0, 37382e25491SJean-Francois Moine tmpbuf, len * 2, 500); 37482e25491SJean-Francois Moine if (len * 2 > USB_BUF_SZ) 37582e25491SJean-Francois Moine kfree(tmpbuf); 37682e25491SJean-Francois Moine } 37782e25491SJean-Francois Moine 378236088d2SJean-Francois Moine static void om6802_sensor_init(struct gspca_dev *gspca_dev) 379fadc7993SJean-Francois Moine { 380fadc7993SJean-Francois Moine int i; 38182e25491SJean-Francois Moine const u8 *p; 38282e25491SJean-Francois Moine u8 byte; 38382e25491SJean-Francois Moine u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05}; 38482e25491SJean-Francois Moine static const u8 sensor_init[] = { 385fadc7993SJean-Francois Moine 0xdf, 0x6d, 386fadc7993SJean-Francois Moine 0xdd, 0x18, 387fadc7993SJean-Francois Moine 0x5a, 0xe0, 388fadc7993SJean-Francois Moine 0x5c, 0x07, 389fadc7993SJean-Francois Moine 0x5d, 0xb0, 390fadc7993SJean-Francois Moine 0x5e, 0x1e, 391fadc7993SJean-Francois Moine 0x60, 0x71, 392fadc7993SJean-Francois Moine 0xef, 0x00, 393fadc7993SJean-Francois Moine 0xe9, 0x00, 394fadc7993SJean-Francois Moine 0xea, 0x00, 395fadc7993SJean-Francois Moine 0x90, 0x24, 396fadc7993SJean-Francois Moine 0x91, 0xb2, 397fadc7993SJean-Francois Moine 0x82, 0x32, 398fadc7993SJean-Francois Moine 0xfd, 0x41, 399fadc7993SJean-Francois Moine 0x00 /* table end */ 400fadc7993SJean-Francois Moine }; 401fadc7993SJean-Francois Moine 402392ee5a5SJean-Francois Moine reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset); 403e30bdc66SJean-Francois Moine msleep(100); 404392ee5a5SJean-Francois Moine i = 4; 40597a53a0fSRoel Kluin while (--i > 0) { 406392ee5a5SJean-Francois Moine byte = reg_r(gspca_dev, 0x0060); 407392ee5a5SJean-Francois Moine if (!(byte & 0x01)) 408392ee5a5SJean-Francois Moine break; 409392ee5a5SJean-Francois Moine msleep(100); 410392ee5a5SJean-Francois Moine } 411392ee5a5SJean-Francois Moine byte = reg_r(gspca_dev, 0x0063); 412392ee5a5SJean-Francois Moine if (byte != 0x17) { 4131b19e429SJoe Perches pr_err("Bad sensor reset %02x\n", byte); 414392ee5a5SJean-Francois Moine /* continue? */ 415392ee5a5SJean-Francois Moine } 416392ee5a5SJean-Francois Moine 417fadc7993SJean-Francois Moine p = sensor_init; 418fadc7993SJean-Francois Moine while (*p != 0) { 419fadc7993SJean-Francois Moine val[1] = *p++; 420fadc7993SJean-Francois Moine val[3] = *p++; 421fadc7993SJean-Francois Moine if (*p == 0) 422fadc7993SJean-Francois Moine reg_w(gspca_dev, 0x3c80); 423f89be036SJean-Francois Moine reg_w_buf(gspca_dev, val, sizeof val); 424fadc7993SJean-Francois Moine i = 4; 425fadc7993SJean-Francois Moine while (--i >= 0) { 426fadc7993SJean-Francois Moine msleep(15); 427fadc7993SJean-Francois Moine byte = reg_r(gspca_dev, 0x60); 428fadc7993SJean-Francois Moine if (!(byte & 0x01)) 429fadc7993SJean-Francois Moine break; 430fadc7993SJean-Francois Moine } 431fadc7993SJean-Francois Moine } 432392ee5a5SJean-Francois Moine msleep(15); 433fadc7993SJean-Francois Moine reg_w(gspca_dev, 0x3c80); 434fadc7993SJean-Francois Moine } 435fadc7993SJean-Francois Moine 4366a7eba24SJean-Francois Moine /* this function is called at probe time */ 4376a7eba24SJean-Francois Moine static int sd_config(struct gspca_dev *gspca_dev, 4386a7eba24SJean-Francois Moine const struct usb_device_id *id) 4396a7eba24SJean-Francois Moine { 4409bf81642SHans Verkuil struct cam *cam = &gspca_dev->cam; 4416a7eba24SJean-Francois Moine 4426a7eba24SJean-Francois Moine cam->cam_mode = vga_mode_t16; 4436a7eba24SJean-Francois Moine cam->nmodes = ARRAY_SIZE(vga_mode_t16); 4446a7eba24SJean-Francois Moine 4456a7eba24SJean-Francois Moine return 0; 4466a7eba24SJean-Francois Moine } 4476a7eba24SJean-Francois Moine 4489bf81642SHans Verkuil static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness) 44935480b6bSJean-Francois Moine { 45082e25491SJean-Francois Moine u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 }; 45135480b6bSJean-Francois Moine 45235480b6bSJean-Francois Moine if (brightness < 7) { 45335480b6bSJean-Francois Moine set6[1] = 0x26; 45435480b6bSJean-Francois Moine set6[3] = 0x70 - brightness * 0x10; 45535480b6bSJean-Francois Moine } else { 45635480b6bSJean-Francois Moine set6[3] = 0x00 + ((brightness - 7) * 0x10); 45735480b6bSJean-Francois Moine } 45835480b6bSJean-Francois Moine 45935480b6bSJean-Francois Moine reg_w_buf(gspca_dev, set6, sizeof set6); 46035480b6bSJean-Francois Moine } 46135480b6bSJean-Francois Moine 4629bf81642SHans Verkuil static void setcontrast(struct gspca_dev *gspca_dev, s32 contrast) 46335480b6bSJean-Francois Moine { 46482e25491SJean-Francois Moine u16 reg_to_write; 46535480b6bSJean-Francois Moine 46635480b6bSJean-Francois Moine if (contrast < 7) 46735480b6bSJean-Francois Moine reg_to_write = 0x8ea9 - contrast * 0x200; 46835480b6bSJean-Francois Moine else 46935480b6bSJean-Francois Moine reg_to_write = 0x00a9 + (contrast - 7) * 0x200; 47035480b6bSJean-Francois Moine 47135480b6bSJean-Francois Moine reg_w(gspca_dev, reg_to_write); 47235480b6bSJean-Francois Moine } 47335480b6bSJean-Francois Moine 4749bf81642SHans Verkuil static void setcolors(struct gspca_dev *gspca_dev, s32 val) 47535480b6bSJean-Francois Moine { 47682e25491SJean-Francois Moine u16 reg_to_write; 47735480b6bSJean-Francois Moine 4789bf81642SHans Verkuil reg_to_write = 0x80bb + val * 0x100; /* was 0xc0 */ 47935480b6bSJean-Francois Moine reg_w(gspca_dev, reg_to_write); 48035480b6bSJean-Francois Moine } 48135480b6bSJean-Francois Moine 4829bf81642SHans Verkuil static void setgamma(struct gspca_dev *gspca_dev, s32 val) 483fadc7993SJean-Francois Moine { 48437d5efb0SJoe Perches gspca_dbg(gspca_dev, D_CONF, "Gamma: %d\n", val); 48582e25491SJean-Francois Moine reg_w_ixbuf(gspca_dev, 0x90, 4869bf81642SHans Verkuil gamma_table[val], sizeof gamma_table[0]); 487fadc7993SJean-Francois Moine } 488fadc7993SJean-Francois Moine 4899bf81642SHans Verkuil static void setawb_n_RGB(struct gspca_dev *gspca_dev) 490e9b15653SJean-François Moine { 491be1da9eeSCostantino Leandro struct sd *sd = (struct sd *) gspca_dev; 4929bf81642SHans Verkuil u8 all_gain_reg[8] = { 4939bf81642SHans Verkuil 0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00 }; 4949bf81642SHans Verkuil s32 red_gain, blue_gain, green_gain; 495e9b15653SJean-François Moine 4969bf81642SHans Verkuil green_gain = sd->gain->val; 4979bf81642SHans Verkuil 4989bf81642SHans Verkuil red_gain = green_gain + sd->red_balance->val; 4999bf81642SHans Verkuil if (red_gain > 0x40) 5009bf81642SHans Verkuil red_gain = 0x40; 5019bf81642SHans Verkuil else if (red_gain < 0x10) 5029bf81642SHans Verkuil red_gain = 0x10; 5039bf81642SHans Verkuil 5049bf81642SHans Verkuil blue_gain = green_gain + sd->blue_balance->val; 5059bf81642SHans Verkuil if (blue_gain > 0x40) 5069bf81642SHans Verkuil blue_gain = 0x40; 5079bf81642SHans Verkuil else if (blue_gain < 0x10) 5089bf81642SHans Verkuil blue_gain = 0x10; 5099bf81642SHans Verkuil 5109bf81642SHans Verkuil all_gain_reg[1] = red_gain; 5119bf81642SHans Verkuil all_gain_reg[3] = blue_gain; 5129bf81642SHans Verkuil all_gain_reg[5] = green_gain; 5139bf81642SHans Verkuil all_gain_reg[7] = sensor_data[sd->sensor].reg80; 5149bf81642SHans Verkuil if (!sd->awb->val) 5159bf81642SHans Verkuil all_gain_reg[7] &= ~0x04; /* AWB off */ 5169bf81642SHans Verkuil 517e9b15653SJean-François Moine reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg); 518be1da9eeSCostantino Leandro } 519be1da9eeSCostantino Leandro 5209bf81642SHans Verkuil static void setsharpness(struct gspca_dev *gspca_dev, s32 val) 52135480b6bSJean-Francois Moine { 52282e25491SJean-Francois Moine u16 reg_to_write; 52335480b6bSJean-Francois Moine 5249bf81642SHans Verkuil reg_to_write = 0x0aa6 + 0x1000 * val; 52535480b6bSJean-Francois Moine 52635480b6bSJean-Francois Moine reg_w(gspca_dev, reg_to_write); 52735480b6bSJean-Francois Moine } 52835480b6bSJean-Francois Moine 5299bf81642SHans Verkuil static void setfreq(struct gspca_dev *gspca_dev, s32 val) 53078b98cb9SJean-François Moine { 53178b98cb9SJean-François Moine struct sd *sd = (struct sd *) gspca_dev; 53278b98cb9SJean-François Moine u8 reg66; 53378b98cb9SJean-François Moine u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 }; 53478b98cb9SJean-François Moine 53578b98cb9SJean-François Moine switch (sd->sensor) { 53678b98cb9SJean-François Moine case SENSOR_LT168G: 5379bf81642SHans Verkuil if (val != 0) 53878b98cb9SJean-François Moine freq[3] = 0xa8; 53978b98cb9SJean-François Moine reg66 = 0x41; 54078b98cb9SJean-François Moine break; 54178b98cb9SJean-François Moine case SENSOR_OM6802: 54278b98cb9SJean-François Moine reg66 = 0xca; 54378b98cb9SJean-François Moine break; 54478b98cb9SJean-François Moine default: 54578b98cb9SJean-François Moine reg66 = 0x40; 54678b98cb9SJean-François Moine break; 54778b98cb9SJean-François Moine } 5489bf81642SHans Verkuil switch (val) { 54978b98cb9SJean-François Moine case 0: /* no flicker */ 55078b98cb9SJean-François Moine freq[3] = 0xf0; 55178b98cb9SJean-François Moine break; 55278b98cb9SJean-François Moine case 2: /* 60Hz */ 55378b98cb9SJean-François Moine reg66 &= ~0x40; 55478b98cb9SJean-François Moine break; 55578b98cb9SJean-François Moine } 55678b98cb9SJean-François Moine freq[1] = reg66; 55778b98cb9SJean-François Moine 55878b98cb9SJean-François Moine reg_w_buf(gspca_dev, freq, sizeof freq); 55978b98cb9SJean-François Moine } 56078b98cb9SJean-François Moine 561fadc7993SJean-Francois Moine /* this function is called at probe and resume time */ 562fadc7993SJean-Francois Moine static int sd_init(struct gspca_dev *gspca_dev) 5636a7eba24SJean-Francois Moine { 564176180c2SMasahiro Yamada /* some of this registers are not really needed, because 565176180c2SMasahiro Yamada * they are overridden by setbrigthness, setcontrast, etc., 566176180c2SMasahiro Yamada * but won't hurt anyway, and can help someone with similar webcam 5676a7eba24SJean-Francois Moine * to see the initial parameters.*/ 568fadc7993SJean-Francois Moine struct sd *sd = (struct sd *) gspca_dev; 56978a6d74eSJean-Francois Moine const struct additional_sensor_data *sensor; 570fadc7993SJean-Francois Moine int i; 5712d56f3bbSJean-Francois Moine u16 sensor_id; 572d9ddd3b0SHans Verkuil u8 test_byte = 0; 5736a7eba24SJean-Francois Moine 57482e25491SJean-Francois Moine static const u8 read_indexs[] = 575249fe889SJean-Francois Moine { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, 57682e25491SJean-Francois Moine 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 }; 57782e25491SJean-Francois Moine static const u8 n1[] = 5786a7eba24SJean-Francois Moine {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; 57982e25491SJean-Francois Moine static const u8 n2[] = 5806a7eba24SJean-Francois Moine {0x08, 0x00}; 5816a7eba24SJean-Francois Moine 5822d56f3bbSJean-Francois Moine sensor_id = (reg_r(gspca_dev, 0x06) << 8) 5832d56f3bbSJean-Francois Moine | reg_r(gspca_dev, 0x07); 5843da37e42SJean-Francois Moine switch (sensor_id & 0xff0f) { 5852d56f3bbSJean-Francois Moine case 0x0801: 58637d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "sensor tas5130a\n"); 587236088d2SJean-Francois Moine sd->sensor = SENSOR_TAS5130A; 5882d56f3bbSJean-Francois Moine break; 58900e8006dSNicolau Werneck case 0x0802: 59037d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "sensor lt168g\n"); 59100e8006dSNicolau Werneck sd->sensor = SENSOR_LT168G; 59200e8006dSNicolau Werneck break; 5932d56f3bbSJean-Francois Moine case 0x0803: 59437d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "sensor 'other'\n"); 5952d56f3bbSJean-Francois Moine sd->sensor = SENSOR_OTHER; 5962d56f3bbSJean-Francois Moine break; 5972d56f3bbSJean-Francois Moine case 0x0807: 59837d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "sensor om6802\n"); 5992d56f3bbSJean-Francois Moine sd->sensor = SENSOR_OM6802; 6002d56f3bbSJean-Francois Moine break; 6012d56f3bbSJean-Francois Moine default: 6021b19e429SJoe Perches pr_err("unknown sensor %04x\n", sensor_id); 603409b11ddSJean-Francois Moine return -EINVAL; 604fadc7993SJean-Francois Moine } 6056a7eba24SJean-Francois Moine 606dd72cb3eSJean-Francois Moine if (sd->sensor == SENSOR_OM6802) { 607f89be036SJean-Francois Moine reg_w_buf(gspca_dev, n1, sizeof n1); 608fadc7993SJean-Francois Moine i = 5; 609fadc7993SJean-Francois Moine while (--i >= 0) { 610392ee5a5SJean-Francois Moine reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset); 611fadc7993SJean-Francois Moine test_byte = reg_r(gspca_dev, 0x0063); 612fadc7993SJean-Francois Moine msleep(100); 613fadc7993SJean-Francois Moine if (test_byte == 0x17) 614fadc7993SJean-Francois Moine break; /* OK */ 615fadc7993SJean-Francois Moine } 616fadc7993SJean-Francois Moine if (i < 0) { 6171b19e429SJoe Perches pr_err("Bad sensor reset %02x\n", test_byte); 61878a6d74eSJean-Francois Moine return -EIO; 619fadc7993SJean-Francois Moine } 620f89be036SJean-Francois Moine reg_w_buf(gspca_dev, n2, sizeof n2); 6212d56f3bbSJean-Francois Moine } 622fadc7993SJean-Francois Moine 623fadc7993SJean-Francois Moine i = 0; 6246a7eba24SJean-Francois Moine while (read_indexs[i] != 0x00) { 625fadc7993SJean-Francois Moine test_byte = reg_r(gspca_dev, read_indexs[i]); 62637d5efb0SJoe Perches gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n", 62737d5efb0SJoe Perches read_indexs[i], test_byte); 6286a7eba24SJean-Francois Moine i++; 6296a7eba24SJean-Francois Moine } 6306a7eba24SJean-Francois Moine 63178a6d74eSJean-Francois Moine sensor = &sensor_data[sd->sensor]; 63278a6d74eSJean-Francois Moine reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3); 63378a6d74eSJean-Francois Moine reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz); 634ad62fb08SLeandro Costantino 63500e8006dSNicolau Werneck if (sd->sensor == SENSOR_LT168G) { 63600e8006dSNicolau Werneck test_byte = reg_r(gspca_dev, 0x80); 63737d5efb0SJoe Perches gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n", 0x80, 63800e8006dSNicolau Werneck test_byte); 63900e8006dSNicolau Werneck reg_w(gspca_dev, 0x6c80); 64000e8006dSNicolau Werneck } 64100e8006dSNicolau Werneck 64278a6d74eSJean-Francois Moine reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); 64378a6d74eSJean-Francois Moine reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); 64478a6d74eSJean-Francois Moine reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); 645ad62fb08SLeandro Costantino 64678a6d74eSJean-Francois Moine reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80); 64778a6d74eSJean-Francois Moine reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80); 64878a6d74eSJean-Francois Moine reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e); 6499bf81642SHans Verkuil reg_w(gspca_dev, (0x20 << 8) + 0x87); 6509bf81642SHans Verkuil reg_w(gspca_dev, (0x20 << 8) + 0x88); 6519bf81642SHans Verkuil reg_w(gspca_dev, (0x20 << 8) + 0x89); 6526a7eba24SJean-Francois Moine 65378a6d74eSJean-Francois Moine reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5); 65478a6d74eSJean-Francois Moine reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8); 65578a6d74eSJean-Francois Moine reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); 656ad62fb08SLeandro Costantino 65700e8006dSNicolau Werneck if (sd->sensor == SENSOR_LT168G) { 65800e8006dSNicolau Werneck test_byte = reg_r(gspca_dev, 0x80); 65937d5efb0SJoe Perches gspca_dbg(gspca_dev, D_STREAM, "Reg 0x%02x = 0x%02x\n", 0x80, 66000e8006dSNicolau Werneck test_byte); 66100e8006dSNicolau Werneck reg_w(gspca_dev, 0x6c80); 66200e8006dSNicolau Werneck } 66300e8006dSNicolau Werneck 66478a6d74eSJean-Francois Moine reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); 66578a6d74eSJean-Francois Moine reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); 66678a6d74eSJean-Francois Moine reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); 6676a7eba24SJean-Francois Moine 6686a7eba24SJean-Francois Moine return 0; 6696a7eba24SJean-Francois Moine } 6706a7eba24SJean-Francois Moine 6719bf81642SHans Verkuil static void setmirror(struct gspca_dev *gspca_dev, s32 val) 6726a7eba24SJean-Francois Moine { 673cd8955b8SJean-François Moine u8 hflipcmd[8] = 6746a7eba24SJean-Francois Moine {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}; 6756a7eba24SJean-Francois Moine 6769bf81642SHans Verkuil if (val) 677cd8955b8SJean-François Moine hflipcmd[3] = 0x01; 6786a7eba24SJean-Francois Moine 679cd8955b8SJean-François Moine reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd); 6806a7eba24SJean-Francois Moine } 6816a7eba24SJean-Francois Moine 6829bf81642SHans Verkuil static void seteffect(struct gspca_dev *gspca_dev, s32 val) 6836a7eba24SJean-Francois Moine { 6849bf81642SHans Verkuil int idx = 0; 6856a7eba24SJean-Francois Moine 6869bf81642SHans Verkuil switch (val) { 6879bf81642SHans Verkuil case V4L2_COLORFX_NONE: 6889bf81642SHans Verkuil break; 6899bf81642SHans Verkuil case V4L2_COLORFX_BW: 6909bf81642SHans Verkuil idx = 2; 6919bf81642SHans Verkuil break; 6929bf81642SHans Verkuil case V4L2_COLORFX_SEPIA: 6939bf81642SHans Verkuil idx = 3; 6949bf81642SHans Verkuil break; 6959bf81642SHans Verkuil case V4L2_COLORFX_SKETCH: 6969bf81642SHans Verkuil idx = 4; 6979bf81642SHans Verkuil break; 6989bf81642SHans Verkuil case V4L2_COLORFX_NEGATIVE: 6999bf81642SHans Verkuil idx = 6; 7009bf81642SHans Verkuil break; 7019bf81642SHans Verkuil default: 7029bf81642SHans Verkuil break; 7036a7eba24SJean-Francois Moine } 7046a7eba24SJean-Francois Moine 7059bf81642SHans Verkuil reg_w_buf(gspca_dev, effects_table[idx], 7069bf81642SHans Verkuil sizeof effects_table[0]); 7079bf81642SHans Verkuil 7089bf81642SHans Verkuil if (val == V4L2_COLORFX_SKETCH) 709fadc7993SJean-Francois Moine reg_w(gspca_dev, 0x4aa6); 7106a7eba24SJean-Francois Moine else 711fadc7993SJean-Francois Moine reg_w(gspca_dev, 0xfaa6); 7126a7eba24SJean-Francois Moine } 7136a7eba24SJean-Francois Moine 714ad62fb08SLeandro Costantino /* Is this really needed? 715ad62fb08SLeandro Costantino * i added some module parameters for test with some users */ 716ad62fb08SLeandro Costantino static void poll_sensor(struct gspca_dev *gspca_dev) 717ad62fb08SLeandro Costantino { 71882e25491SJean-Francois Moine static const u8 poll1[] = 719ad62fb08SLeandro Costantino {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82, 720ad62fb08SLeandro Costantino 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34, 721ad62fb08SLeandro Costantino 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01, 722ad62fb08SLeandro Costantino 0x60, 0x14}; 72382e25491SJean-Francois Moine static const u8 poll2[] = 724ad62fb08SLeandro Costantino {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9, 725ad62fb08SLeandro Costantino 0x73, 0x02, 0x73, 0x02, 0x60, 0x14}; 72698388241SJean-François Moine static const u8 noise03[] = /* (some differences / ms-drv) */ 727ad62fb08SLeandro Costantino {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f, 728ad62fb08SLeandro Costantino 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c, 729ad62fb08SLeandro Costantino 0xc2, 0x80, 0xc3, 0x10}; 730ad62fb08SLeandro Costantino 73137d5efb0SJoe Perches gspca_dbg(gspca_dev, D_STREAM, "[Sensor requires polling]\n"); 732ad62fb08SLeandro Costantino reg_w_buf(gspca_dev, poll1, sizeof poll1); 733ad62fb08SLeandro Costantino reg_w_buf(gspca_dev, poll2, sizeof poll2); 73498388241SJean-François Moine reg_w_buf(gspca_dev, noise03, sizeof noise03); 735ad62fb08SLeandro Costantino } 736ad62fb08SLeandro Costantino 737fadc7993SJean-Francois Moine static int sd_start(struct gspca_dev *gspca_dev) 738fadc7993SJean-Francois Moine { 739fadc7993SJean-Francois Moine struct sd *sd = (struct sd *) gspca_dev; 74078a6d74eSJean-Francois Moine const struct additional_sensor_data *sensor; 741fadc7993SJean-Francois Moine int i, mode; 74282e25491SJean-Francois Moine u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; 74382e25491SJean-Francois Moine static const u8 t3[] = 74482e25491SJean-Francois Moine { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 }; 745fadc7993SJean-Francois Moine 74678a6d74eSJean-Francois Moine mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; 747fadc7993SJean-Francois Moine switch (mode) { 74882e25491SJean-Francois Moine case 0: /* 640x480 (0x00) */ 74982e25491SJean-Francois Moine break; 750fadc7993SJean-Francois Moine case 1: /* 352x288 */ 751fadc7993SJean-Francois Moine t2[1] = 0x40; 752fadc7993SJean-Francois Moine break; 753fadc7993SJean-Francois Moine case 2: /* 320x240 */ 754fadc7993SJean-Francois Moine t2[1] = 0x10; 755fadc7993SJean-Francois Moine break; 756fadc7993SJean-Francois Moine case 3: /* 176x144 */ 757fadc7993SJean-Francois Moine t2[1] = 0x50; 758fadc7993SJean-Francois Moine break; 75982e25491SJean-Francois Moine default: 76082e25491SJean-Francois Moine /* case 4: * 160x120 */ 761fadc7993SJean-Francois Moine t2[1] = 0x20; 762fadc7993SJean-Francois Moine break; 763fadc7993SJean-Francois Moine } 764fadc7993SJean-Francois Moine 7652d56f3bbSJean-Francois Moine switch (sd->sensor) { 7662d56f3bbSJean-Francois Moine case SENSOR_OM6802: 7672d56f3bbSJean-Francois Moine om6802_sensor_init(gspca_dev); 7682d56f3bbSJean-Francois Moine break; 769cd8955b8SJean-François Moine case SENSOR_TAS5130A: 770fadc7993SJean-Francois Moine i = 0; 77178a6d74eSJean-Francois Moine for (;;) { 772f89be036SJean-Francois Moine reg_w_buf(gspca_dev, tas5130a_sensor_init[i], 773fadc7993SJean-Francois Moine sizeof tas5130a_sensor_init[0]); 77478a6d74eSJean-Francois Moine if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1) 77578a6d74eSJean-Francois Moine break; 776fadc7993SJean-Francois Moine i++; 777fadc7993SJean-Francois Moine } 778fadc7993SJean-Francois Moine reg_w(gspca_dev, 0x3c80); 779fadc7993SJean-Francois Moine /* just in case and to keep sync with logs (for mine) */ 78078a6d74eSJean-Francois Moine reg_w_buf(gspca_dev, tas5130a_sensor_init[i], 781fadc7993SJean-Francois Moine sizeof tas5130a_sensor_init[0]); 782fadc7993SJean-Francois Moine reg_w(gspca_dev, 0x3c80); 7832d56f3bbSJean-Francois Moine break; 784fadc7993SJean-Francois Moine } 78578a6d74eSJean-Francois Moine sensor = &sensor_data[sd->sensor]; 7869bf81642SHans Verkuil setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq)); 787fadc7993SJean-Francois Moine reg_r(gspca_dev, 0x0012); 788ad62fb08SLeandro Costantino reg_w_buf(gspca_dev, t2, sizeof t2); 78982e25491SJean-Francois Moine reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3); 790fadc7993SJean-Francois Moine reg_w(gspca_dev, 0x0013); 791ad62fb08SLeandro Costantino msleep(15); 79278a6d74eSJean-Francois Moine reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); 79378a6d74eSJean-Francois Moine reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); 79478a6d74eSJean-Francois Moine 79578a6d74eSJean-Francois Moine if (sd->sensor == SENSOR_OM6802) 796ad62fb08SLeandro Costantino poll_sensor(gspca_dev); 797ad62fb08SLeandro Costantino 798fadc7993SJean-Francois Moine return 0; 799fadc7993SJean-Francois Moine } 800fadc7993SJean-Francois Moine 801eb229b22SJean-Francois Moine static void sd_stopN(struct gspca_dev *gspca_dev) 802eb229b22SJean-Francois Moine { 803eb229b22SJean-Francois Moine struct sd *sd = (struct sd *) gspca_dev; 804eb229b22SJean-Francois Moine 805eb229b22SJean-Francois Moine reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream, 806eb229b22SJean-Francois Moine sizeof sensor_data[sd->sensor].stream); 807eb229b22SJean-Francois Moine reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream, 808eb229b22SJean-Francois Moine sizeof sensor_data[sd->sensor].stream); 80978a6d74eSJean-Francois Moine if (sd->sensor == SENSOR_OM6802) { 810eb229b22SJean-Francois Moine msleep(20); 811eb229b22SJean-Francois Moine reg_w(gspca_dev, 0x0309); 812eb229b22SJean-Francois Moine } 813f8d26879SPeter Senna Tschudin #if IS_ENABLED(CONFIG_INPUT) 814ee186fd9SHans de Goede /* If the last button state is pressed, release it now! */ 815ee186fd9SHans de Goede if (sd->button_pressed) { 816ee186fd9SHans de Goede input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); 817ee186fd9SHans de Goede input_sync(gspca_dev->input_dev); 818ee186fd9SHans de Goede sd->button_pressed = 0; 819ee186fd9SHans de Goede } 820ee186fd9SHans de Goede #endif 8212d56f3bbSJean-Francois Moine } 822eb229b22SJean-Francois Moine 823fadc7993SJean-Francois Moine static void sd_pkt_scan(struct gspca_dev *gspca_dev, 82482e25491SJean-Francois Moine u8 *data, /* isoc packet */ 825fadc7993SJean-Francois Moine int len) /* iso packet length */ 826fadc7993SJean-Francois Moine { 827d7e92e15SArnd Bergmann struct sd *sd __maybe_unused = (struct sd *) gspca_dev; 828ebb78c5aSJean-François Moine int pkt_type; 829fadc7993SJean-Francois Moine 830fadc7993SJean-Francois Moine if (data[0] == 0x5a) { 831f8d26879SPeter Senna Tschudin #if IS_ENABLED(CONFIG_INPUT) 832ee186fd9SHans de Goede if (len > 20) { 833ee186fd9SHans de Goede u8 state = (data[20] & 0x80) ? 1 : 0; 834ee186fd9SHans de Goede if (sd->button_pressed != state) { 835ee186fd9SHans de Goede input_report_key(gspca_dev->input_dev, 836ee186fd9SHans de Goede KEY_CAMERA, state); 837ee186fd9SHans de Goede input_sync(gspca_dev->input_dev); 838ee186fd9SHans de Goede sd->button_pressed = state; 839ee186fd9SHans de Goede } 840ee186fd9SHans de Goede } 841ee186fd9SHans de Goede #endif 842fadc7993SJean-Francois Moine /* Control Packet, after this came the header again, 843fadc7993SJean-Francois Moine * but extra bytes came in the packet before this, 844fadc7993SJean-Francois Moine * sometimes an EOF arrives, sometimes not... */ 845fadc7993SJean-Francois Moine return; 846fadc7993SJean-Francois Moine } 847fadc7993SJean-Francois Moine data += 2; 848fadc7993SJean-Francois Moine len -= 2; 849ebb78c5aSJean-François Moine if (data[0] == 0xff && data[1] == 0xd8) 850ebb78c5aSJean-François Moine pkt_type = FIRST_PACKET; 851ebb78c5aSJean-François Moine else if (data[len - 2] == 0xff && data[len - 1] == 0xd9) 852ebb78c5aSJean-François Moine pkt_type = LAST_PACKET; 853ebb78c5aSJean-François Moine else 854ebb78c5aSJean-François Moine pkt_type = INTER_PACKET; 855ebb78c5aSJean-François Moine gspca_frame_add(gspca_dev, pkt_type, data, len); 8566a7eba24SJean-Francois Moine } 8576a7eba24SJean-Francois Moine 8589bf81642SHans Verkuil static int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 859be1da9eeSCostantino Leandro { 8609bf81642SHans Verkuil struct gspca_dev *gspca_dev = 8619bf81642SHans Verkuil container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 862be1da9eeSCostantino Leandro struct sd *sd = (struct sd *)gspca_dev; 8639bf81642SHans Verkuil s32 red_gain, blue_gain, green_gain; 864be1da9eeSCostantino Leandro 8659bf81642SHans Verkuil gspca_dev->usb_err = 0; 8669bf81642SHans Verkuil 8679bf81642SHans Verkuil switch (ctrl->id) { 8689bf81642SHans Verkuil case V4L2_CID_AUTO_WHITE_BALANCE: 8699bf81642SHans Verkuil red_gain = reg_r(gspca_dev, 0x0087); 8709bf81642SHans Verkuil if (red_gain > 0x40) 8719bf81642SHans Verkuil red_gain = 0x40; 8729bf81642SHans Verkuil else if (red_gain < 0x10) 8739bf81642SHans Verkuil red_gain = 0x10; 8749bf81642SHans Verkuil 8759bf81642SHans Verkuil blue_gain = reg_r(gspca_dev, 0x0088); 8769bf81642SHans Verkuil if (blue_gain > 0x40) 8779bf81642SHans Verkuil blue_gain = 0x40; 8789bf81642SHans Verkuil else if (blue_gain < 0x10) 8799bf81642SHans Verkuil blue_gain = 0x10; 8809bf81642SHans Verkuil 8819bf81642SHans Verkuil green_gain = reg_r(gspca_dev, 0x0089); 8829bf81642SHans Verkuil if (green_gain > 0x40) 8839bf81642SHans Verkuil green_gain = 0x40; 8849bf81642SHans Verkuil else if (green_gain < 0x10) 8859bf81642SHans Verkuil green_gain = 0x10; 8869bf81642SHans Verkuil 8879bf81642SHans Verkuil sd->gain->val = green_gain; 8889bf81642SHans Verkuil sd->red_balance->val = red_gain - green_gain; 8899bf81642SHans Verkuil sd->blue_balance->val = blue_gain - green_gain; 8909bf81642SHans Verkuil break; 8919bf81642SHans Verkuil } 892be1da9eeSCostantino Leandro return 0; 893be1da9eeSCostantino Leandro } 894be1da9eeSCostantino Leandro 8959bf81642SHans Verkuil static int sd_s_ctrl(struct v4l2_ctrl *ctrl) 896be1da9eeSCostantino Leandro { 8979bf81642SHans Verkuil struct gspca_dev *gspca_dev = 8989bf81642SHans Verkuil container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 899be1da9eeSCostantino Leandro 9009bf81642SHans Verkuil gspca_dev->usb_err = 0; 9019bf81642SHans Verkuil 9029bf81642SHans Verkuil if (!gspca_dev->streaming) 903be1da9eeSCostantino Leandro return 0; 904be1da9eeSCostantino Leandro 9059bf81642SHans Verkuil switch (ctrl->id) { 9069bf81642SHans Verkuil case V4L2_CID_BRIGHTNESS: 9079bf81642SHans Verkuil setbrightness(gspca_dev, ctrl->val); 9089bf81642SHans Verkuil break; 9099bf81642SHans Verkuil case V4L2_CID_CONTRAST: 9109bf81642SHans Verkuil setcontrast(gspca_dev, ctrl->val); 9119bf81642SHans Verkuil break; 9129bf81642SHans Verkuil case V4L2_CID_SATURATION: 9139bf81642SHans Verkuil setcolors(gspca_dev, ctrl->val); 9149bf81642SHans Verkuil break; 9159bf81642SHans Verkuil case V4L2_CID_GAMMA: 9169bf81642SHans Verkuil setgamma(gspca_dev, ctrl->val); 9179bf81642SHans Verkuil break; 9189bf81642SHans Verkuil case V4L2_CID_HFLIP: 9199bf81642SHans Verkuil setmirror(gspca_dev, ctrl->val); 9209bf81642SHans Verkuil break; 9219bf81642SHans Verkuil case V4L2_CID_SHARPNESS: 9229bf81642SHans Verkuil setsharpness(gspca_dev, ctrl->val); 9239bf81642SHans Verkuil break; 9246a7eba24SJean-Francois Moine case V4L2_CID_POWER_LINE_FREQUENCY: 9259bf81642SHans Verkuil setfreq(gspca_dev, ctrl->val); 9266a7eba24SJean-Francois Moine break; 9279bf81642SHans Verkuil case V4L2_CID_BACKLIGHT_COMPENSATION: 9289bf81642SHans Verkuil reg_w(gspca_dev, ctrl->val ? 0xf48e : 0xb48e); 9299bf81642SHans Verkuil break; 9309bf81642SHans Verkuil case V4L2_CID_AUTO_WHITE_BALANCE: 9319bf81642SHans Verkuil setawb_n_RGB(gspca_dev); 9329bf81642SHans Verkuil break; 9339bf81642SHans Verkuil case V4L2_CID_COLORFX: 9349bf81642SHans Verkuil seteffect(gspca_dev, ctrl->val); 9356a7eba24SJean-Francois Moine break; 9366a7eba24SJean-Francois Moine } 9379bf81642SHans Verkuil return gspca_dev->usb_err; 9389bf81642SHans Verkuil } 9399bf81642SHans Verkuil 9409bf81642SHans Verkuil static const struct v4l2_ctrl_ops sd_ctrl_ops = { 9419bf81642SHans Verkuil .g_volatile_ctrl = sd_g_volatile_ctrl, 9429bf81642SHans Verkuil .s_ctrl = sd_s_ctrl, 9439bf81642SHans Verkuil }; 9449bf81642SHans Verkuil 9459bf81642SHans Verkuil static int sd_init_controls(struct gspca_dev *gspca_dev) 9469bf81642SHans Verkuil { 9479bf81642SHans Verkuil struct sd *sd = (struct sd *)gspca_dev; 9489bf81642SHans Verkuil struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 9499bf81642SHans Verkuil 9509bf81642SHans Verkuil gspca_dev->vdev.ctrl_handler = hdl; 9519bf81642SHans Verkuil v4l2_ctrl_handler_init(hdl, 12); 9529bf81642SHans Verkuil v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9539bf81642SHans Verkuil V4L2_CID_BRIGHTNESS, 0, 14, 1, 8); 9549bf81642SHans Verkuil v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9559bf81642SHans Verkuil V4L2_CID_CONTRAST, 0, 0x0d, 1, 7); 9569bf81642SHans Verkuil v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9579bf81642SHans Verkuil V4L2_CID_SATURATION, 0, 0xf, 1, 5); 9589bf81642SHans Verkuil v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9599bf81642SHans Verkuil V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 10); 9603e4d8f48SMauro Carvalho Chehab /* Activate lowlight, some apps don't bring up the 9619bf81642SHans Verkuil backlight_compensation control) */ 9629bf81642SHans Verkuil v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9639bf81642SHans Verkuil V4L2_CID_BACKLIGHT_COMPENSATION, 0, 1, 1, 1); 9649bf81642SHans Verkuil if (sd->sensor == SENSOR_TAS5130A) 9659bf81642SHans Verkuil v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9669bf81642SHans Verkuil V4L2_CID_HFLIP, 0, 1, 1, 0); 9679bf81642SHans Verkuil sd->awb = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9689bf81642SHans Verkuil V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1); 9699bf81642SHans Verkuil sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9709bf81642SHans Verkuil V4L2_CID_GAIN, 0x10, 0x40, 1, 0x20); 9719bf81642SHans Verkuil sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9729bf81642SHans Verkuil V4L2_CID_BLUE_BALANCE, -0x30, 0x30, 1, 0); 9739bf81642SHans Verkuil sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9749bf81642SHans Verkuil V4L2_CID_RED_BALANCE, -0x30, 0x30, 1, 0); 9759bf81642SHans Verkuil v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 9769bf81642SHans Verkuil V4L2_CID_SHARPNESS, 0, 15, 1, 6); 9779bf81642SHans Verkuil v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, 9789bf81642SHans Verkuil V4L2_CID_COLORFX, V4L2_COLORFX_SKETCH, 9799bf81642SHans Verkuil ~((1 << V4L2_COLORFX_NONE) | 9809bf81642SHans Verkuil (1 << V4L2_COLORFX_BW) | 9819bf81642SHans Verkuil (1 << V4L2_COLORFX_SEPIA) | 9829bf81642SHans Verkuil (1 << V4L2_COLORFX_SKETCH) | 9839bf81642SHans Verkuil (1 << V4L2_COLORFX_NEGATIVE)), 9849bf81642SHans Verkuil V4L2_COLORFX_NONE); 9859bf81642SHans Verkuil sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, 9869bf81642SHans Verkuil V4L2_CID_POWER_LINE_FREQUENCY, 9879bf81642SHans Verkuil V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1, 9889bf81642SHans Verkuil V4L2_CID_POWER_LINE_FREQUENCY_50HZ); 9899bf81642SHans Verkuil 9909bf81642SHans Verkuil if (hdl->error) { 9919bf81642SHans Verkuil pr_err("Could not initialize controls\n"); 9929bf81642SHans Verkuil return hdl->error; 9939bf81642SHans Verkuil } 9949bf81642SHans Verkuil 9959bf81642SHans Verkuil v4l2_ctrl_auto_cluster(4, &sd->awb, 0, true); 9969bf81642SHans Verkuil 9979bf81642SHans Verkuil return 0; 9986a7eba24SJean-Francois Moine } 9996a7eba24SJean-Francois Moine 10006a7eba24SJean-Francois Moine /* sub-driver description */ 1001a5ae2062SJean-Francois Moine static const struct sd_desc sd_desc = { 10026a7eba24SJean-Francois Moine .name = MODULE_NAME, 10036a7eba24SJean-Francois Moine .config = sd_config, 1004012d6b02SJean-Francois Moine .init = sd_init, 10059bf81642SHans Verkuil .init_controls = sd_init_controls, 10066a7eba24SJean-Francois Moine .start = sd_start, 1007eb229b22SJean-Francois Moine .stopN = sd_stopN, 10086a7eba24SJean-Francois Moine .pkt_scan = sd_pkt_scan, 1009f8d26879SPeter Senna Tschudin #if IS_ENABLED(CONFIG_INPUT) 1010ee186fd9SHans de Goede .other_input = 1, 1011ee186fd9SHans de Goede #endif 10126a7eba24SJean-Francois Moine }; 10136a7eba24SJean-Francois Moine 10146a7eba24SJean-Francois Moine /* -- module initialisation -- */ 101595c967c1SJean-François Moine static const struct usb_device_id device_table[] = { 10169d64fdb1SJean-Francois Moine {USB_DEVICE(0x17a1, 0x0128)}, 10176a7eba24SJean-Francois Moine {} 10186a7eba24SJean-Francois Moine }; 10196a7eba24SJean-Francois Moine MODULE_DEVICE_TABLE(usb, device_table); 10206a7eba24SJean-Francois Moine 10216a7eba24SJean-Francois Moine /* -- device connect -- */ 10226a7eba24SJean-Francois Moine static int sd_probe(struct usb_interface *intf, 10236a7eba24SJean-Francois Moine const struct usb_device_id *id) 10246a7eba24SJean-Francois Moine { 10256a7eba24SJean-Francois Moine return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 10266a7eba24SJean-Francois Moine THIS_MODULE); 10276a7eba24SJean-Francois Moine } 10286a7eba24SJean-Francois Moine 10296a7eba24SJean-Francois Moine static struct usb_driver sd_driver = { 10306a7eba24SJean-Francois Moine .name = MODULE_NAME, 10316a7eba24SJean-Francois Moine .id_table = device_table, 10326a7eba24SJean-Francois Moine .probe = sd_probe, 10336a7eba24SJean-Francois Moine .disconnect = gspca_disconnect, 10346a709749SJean-Francois Moine #ifdef CONFIG_PM 10356a709749SJean-Francois Moine .suspend = gspca_suspend, 10366a709749SJean-Francois Moine .resume = gspca_resume, 10378bb58964SHans de Goede .reset_resume = gspca_resume, 10386a709749SJean-Francois Moine #endif 10396a7eba24SJean-Francois Moine }; 10406a7eba24SJean-Francois Moine 1041ecb3b2b3SGreg Kroah-Hartman module_usb_driver(sd_driver); 1042