1/* 2 * T613 subdriver 3 * 4 * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr) 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 *Notes: * t613 + tas5130A 21 * * Focus to light do not balance well as in win. 22 * Quality in win is not good, but its kinda better. 23 * * Fix some "extraneous bytes", most of apps will show the image anyway 24 * * Gamma table, is there, but its really doing something? 25 * * 7~8 Fps, its ok, max on win its 10. 26 * Costantino Leandro 27 */ 28 29#define MODULE_NAME "t613" 30 31#include <linux/slab.h> 32#include "gspca.h" 33 34#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0) 35 36MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>"); 37MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver"); 38MODULE_LICENSE("GPL"); 39 40struct sd { 41 struct gspca_dev gspca_dev; /* !! must be the first item */ 42 43 u8 brightness; 44 u8 contrast; 45 u8 colors; 46 u8 autogain; 47 u8 gamma; 48 u8 sharpness; 49 u8 freq; 50 u8 red_gain; 51 u8 blue_gain; 52 u8 green_gain; 53 u8 awb; /* set default r/g/b and activate */ 54 u8 mirror; 55 u8 effect; 56 57 u8 sensor; 58}; 59enum sensors { 60 SENSOR_OM6802, 61 SENSOR_OTHER, 62 SENSOR_TAS5130A, 63 SENSOR_LT168G, /* must verify if this is the actual model */ 64}; 65 66/* V4L2 controls supported by the driver */ 67static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); 68static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); 69static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); 70static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); 71static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); 72static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); 73static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val); 74static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val); 75static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val); 76static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val); 77static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); 78static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); 79static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); 80static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); 81 82static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val); 83static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val); 84static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val); 85static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val); 86static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val); 87static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val); 88static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); 89static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); 90 91static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val); 92static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val); 93static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val); 94static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val); 95static int sd_querymenu(struct gspca_dev *gspca_dev, 96 struct v4l2_querymenu *menu); 97 98static const struct ctrl sd_ctrls[] = { 99 { 100 { 101 .id = V4L2_CID_BRIGHTNESS, 102 .type = V4L2_CTRL_TYPE_INTEGER, 103 .name = "Brightness", 104 .minimum = 0, 105 .maximum = 14, 106 .step = 1, 107#define BRIGHTNESS_DEF 8 108 .default_value = BRIGHTNESS_DEF, 109 }, 110 .set = sd_setbrightness, 111 .get = sd_getbrightness, 112 }, 113 { 114 { 115 .id = V4L2_CID_CONTRAST, 116 .type = V4L2_CTRL_TYPE_INTEGER, 117 .name = "Contrast", 118 .minimum = 0, 119 .maximum = 0x0d, 120 .step = 1, 121#define CONTRAST_DEF 0x07 122 .default_value = CONTRAST_DEF, 123 }, 124 .set = sd_setcontrast, 125 .get = sd_getcontrast, 126 }, 127 { 128 { 129 .id = V4L2_CID_SATURATION, 130 .type = V4L2_CTRL_TYPE_INTEGER, 131 .name = "Color", 132 .minimum = 0, 133 .maximum = 0x0f, 134 .step = 1, 135#define COLORS_DEF 0x05 136 .default_value = COLORS_DEF, 137 }, 138 .set = sd_setcolors, 139 .get = sd_getcolors, 140 }, 141#define GAMMA_MAX 16 142#define GAMMA_DEF 10 143 { 144 { 145 .id = V4L2_CID_GAMMA, /* (gamma on win) */ 146 .type = V4L2_CTRL_TYPE_INTEGER, 147 .name = "Gamma", 148 .minimum = 0, 149 .maximum = GAMMA_MAX - 1, 150 .step = 1, 151 .default_value = GAMMA_DEF, 152 }, 153 .set = sd_setgamma, 154 .get = sd_getgamma, 155 }, 156 { 157 { 158 .id = V4L2_CID_BACKLIGHT_COMPENSATION, /* Activa lowlight, 159 * some apps dont bring up the 160 * backligth_compensation control) */ 161 .type = V4L2_CTRL_TYPE_INTEGER, 162 .name = "Low Light", 163 .minimum = 0, 164 .maximum = 1, 165 .step = 1, 166#define AUTOGAIN_DEF 0x01 167 .default_value = AUTOGAIN_DEF, 168 }, 169 .set = sd_setlowlight, 170 .get = sd_getlowlight, 171 }, 172 { 173 { 174 .id = V4L2_CID_HFLIP, 175 .type = V4L2_CTRL_TYPE_BOOLEAN, 176 .name = "Mirror Image", 177 .minimum = 0, 178 .maximum = 1, 179 .step = 1, 180#define MIRROR_DEF 0 181 .default_value = MIRROR_DEF, 182 }, 183 .set = sd_setmirror, 184 .get = sd_getmirror 185 }, 186 { 187 { 188 .id = V4L2_CID_POWER_LINE_FREQUENCY, 189 .type = V4L2_CTRL_TYPE_MENU, 190 .name = "Light Frequency Filter", 191 .minimum = 1, /* 1 -> 0x50, 2->0x60 */ 192 .maximum = 2, 193 .step = 1, 194#define FREQ_DEF 1 195 .default_value = FREQ_DEF, 196 }, 197 .set = sd_setfreq, 198 .get = sd_getfreq}, 199 200 { 201 { 202 .id = V4L2_CID_AUTO_WHITE_BALANCE, 203 .type = V4L2_CTRL_TYPE_INTEGER, 204 .name = "Auto White Balance", 205 .minimum = 0, 206 .maximum = 1, 207 .step = 1, 208#define AWB_DEF 0 209 .default_value = AWB_DEF, 210 }, 211 .set = sd_setawb, 212 .get = sd_getawb 213 }, 214 { 215 { 216 .id = V4L2_CID_SHARPNESS, 217 .type = V4L2_CTRL_TYPE_INTEGER, 218 .name = "Sharpness", 219 .minimum = 0, 220 .maximum = 15, 221 .step = 1, 222#define SHARPNESS_DEF 0x06 223 .default_value = SHARPNESS_DEF, 224 }, 225 .set = sd_setsharpness, 226 .get = sd_getsharpness, 227 }, 228 { 229 { 230 .id = V4L2_CID_EFFECTS, 231 .type = V4L2_CTRL_TYPE_MENU, 232 .name = "Webcam Effects", 233 .minimum = 0, 234 .maximum = 4, 235 .step = 1, 236#define EFFECTS_DEF 0 237 .default_value = EFFECTS_DEF, 238 }, 239 .set = sd_seteffect, 240 .get = sd_geteffect 241 }, 242 { 243 { 244 .id = V4L2_CID_BLUE_BALANCE, 245 .type = V4L2_CTRL_TYPE_INTEGER, 246 .name = "Blue Balance", 247 .minimum = 0x10, 248 .maximum = 0x40, 249 .step = 1, 250#define BLUE_GAIN_DEF 0x20 251 .default_value = BLUE_GAIN_DEF, 252 }, 253 .set = sd_setblue_gain, 254 .get = sd_getblue_gain, 255 }, 256 { 257 { 258 .id = V4L2_CID_RED_BALANCE, 259 .type = V4L2_CTRL_TYPE_INTEGER, 260 .name = "Red Balance", 261 .minimum = 0x10, 262 .maximum = 0x40, 263 .step = 1, 264#define RED_GAIN_DEF 0x20 265 .default_value = RED_GAIN_DEF, 266 }, 267 .set = sd_setred_gain, 268 .get = sd_getred_gain, 269 }, 270 { 271 { 272 .id = V4L2_CID_GAIN, 273 .type = V4L2_CTRL_TYPE_INTEGER, 274 .name = "Gain", 275 .minimum = 0x10, 276 .maximum = 0x40, 277 .step = 1, 278#define GAIN_DEF 0x20 279 .default_value = GAIN_DEF, 280 }, 281 .set = sd_setgain, 282 .get = sd_getgain, 283 }, 284}; 285 286static const struct v4l2_pix_format vga_mode_t16[] = { 287 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 288 .bytesperline = 160, 289 .sizeimage = 160 * 120 * 4 / 8 + 590, 290 .colorspace = V4L2_COLORSPACE_JPEG, 291 .priv = 4}, 292 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 293 .bytesperline = 176, 294 .sizeimage = 176 * 144 * 3 / 8 + 590, 295 .colorspace = V4L2_COLORSPACE_JPEG, 296 .priv = 3}, 297 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 298 .bytesperline = 320, 299 .sizeimage = 320 * 240 * 3 / 8 + 590, 300 .colorspace = V4L2_COLORSPACE_JPEG, 301 .priv = 2}, 302 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 303 .bytesperline = 352, 304 .sizeimage = 352 * 288 * 3 / 8 + 590, 305 .colorspace = V4L2_COLORSPACE_JPEG, 306 .priv = 1}, 307 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 308 .bytesperline = 640, 309 .sizeimage = 640 * 480 * 3 / 8 + 590, 310 .colorspace = V4L2_COLORSPACE_JPEG, 311 .priv = 0}, 312}; 313 314/* sensor specific data */ 315struct additional_sensor_data { 316 const u8 n3[6]; 317 const u8 *n4, n4sz; 318 const u8 reg80, reg8e; 319 const u8 nset8[6]; 320 const u8 data1[10]; 321 const u8 data2[9]; 322 const u8 data3[9]; 323 const u8 data5[6]; 324 const u8 stream[4]; 325}; 326 327static const u8 n4_om6802[] = { 328 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c, 329 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68, 330 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1, 331 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8, 332 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48, 333 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0, 334 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68, 335 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40, 336 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46 337}; 338static const u8 n4_other[] = { 339 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69, 340 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68, 341 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8, 342 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8, 343 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56, 344 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5, 345 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0, 346 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00 347}; 348static const u8 n4_tas5130a[] = { 349 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20, 350 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4, 351 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10, 352 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08, 353 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a, 354 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8, 355 0xc6, 0xda 356}; 357static const u8 n4_lt168g[] = { 358 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28, 359 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70, 360 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3, 361 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20, 362 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68, 363 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40, 364 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0, 365 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c, 366 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80 367}; 368 369static const struct additional_sensor_data sensor_data[] = { 370[SENSOR_OM6802] = { 371 .n3 = 372 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04}, 373 .n4 = n4_om6802, 374 .n4sz = sizeof n4_om6802, 375 .reg80 = 0x3c, 376 .reg8e = 0x33, 377 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00}, 378 .data1 = 379 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06, 380 0xb3, 0xfc}, 381 .data2 = 382 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 383 0xff}, 384 .data3 = 385 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff, 386 0xff}, 387 .data5 = /* this could be removed later */ 388 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23}, 389 .stream = 390 {0x0b, 0x04, 0x0a, 0x78}, 391 }, 392[SENSOR_OTHER] = { 393 .n3 = 394 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00}, 395 .n4 = n4_other, 396 .n4sz = sizeof n4_other, 397 .reg80 = 0xac, 398 .reg8e = 0xb8, 399 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00}, 400 .data1 = 401 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a, 402 0xe8, 0xfc}, 403 .data2 = 404 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96, 405 0xd9}, 406 .data3 = 407 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96, 408 0xd9}, 409 .data5 = 410 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69}, 411 .stream = 412 {0x0b, 0x04, 0x0a, 0x00}, 413 }, 414[SENSOR_TAS5130A] = { 415 .n3 = 416 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08}, 417 .n4 = n4_tas5130a, 418 .n4sz = sizeof n4_tas5130a, 419 .reg80 = 0x3c, 420 .reg8e = 0xb4, 421 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00}, 422 .data1 = 423 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27, 424 0xc8, 0xfc}, 425 .data2 = 426 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, 427 0xe0}, 428 .data3 = 429 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8, 430 0xe0}, 431 .data5 = 432 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20}, 433 .stream = 434 {0x0b, 0x04, 0x0a, 0x40}, 435 }, 436[SENSOR_LT168G] = { 437 .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00}, 438 .n4 = n4_lt168g, 439 .n4sz = sizeof n4_lt168g, 440 .reg80 = 0x7c, 441 .reg8e = 0xb3, 442 .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00}, 443 .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40, 444 0xb0, 0xf4}, 445 .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, 446 0xff}, 447 .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, 448 0xff}, 449 .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b}, 450 .stream = {0x0b, 0x04, 0x0a, 0x28}, 451 }, 452}; 453 454#define MAX_EFFECTS 7 455/* easily done by soft, this table could be removed, 456 * i keep it here just in case */ 457static char *effects_control[MAX_EFFECTS] = { 458 "Normal", 459 "Emboss", /* disabled */ 460 "Monochrome", 461 "Sepia", 462 "Sketch", 463 "Sun Effect", /* disabled */ 464 "Negative", 465}; 466static const u8 effects_table[MAX_EFFECTS][6] = { 467 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */ 468 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */ 469 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */ 470 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */ 471 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */ 472 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */ 473 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */ 474}; 475 476static const u8 gamma_table[GAMMA_MAX][17] = { 477/* gamma table from cam1690.ini */ 478 {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21, /* 0 */ 479 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb, 480 0xff}, 481 {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d, /* 1 */ 482 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1, 483 0xff}, 484 {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35, /* 2 */ 485 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3, 486 0xff}, 487 {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f, /* 3 */ 488 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6, 489 0xff}, 490 {0x00, 0x04, 0x0B, 0x15, 0x20, 0x2d, 0x3b, 0x4a, /* 4 */ 491 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9, 492 0xff}, 493 {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58, /* 5 */ 494 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec, 495 0xff}, 496 {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67, /* 6 */ 497 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 498 0xff}, 499 {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, /* 7 */ 500 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 501 0xff}, 502 {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79, /* 8 */ 503 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0, 504 0xff}, 505 {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84, /* 9 */ 506 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2, 507 0xff}, 508 {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e, /* 10 */ 509 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3, 510 0xff}, 511 {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b, /* 11 */ 512 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5, 513 0xff}, 514 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8, /* 12 */ 515 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6, 516 0xff}, 517 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7, /* 13 */ 518 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9, 519 0xff}, 520 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6, /* 14 */ 521 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa, 522 0xff}, 523 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8, /* 15 */ 524 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc, 525 0xff} 526}; 527 528static const u8 tas5130a_sensor_init[][8] = { 529 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09}, 530 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09}, 531 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}, 532}; 533 534static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07}; 535 536/* read 1 byte */ 537static u8 reg_r(struct gspca_dev *gspca_dev, 538 u16 index) 539{ 540 usb_control_msg(gspca_dev->dev, 541 usb_rcvctrlpipe(gspca_dev->dev, 0), 542 0, /* request */ 543 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 544 0, /* value */ 545 index, 546 gspca_dev->usb_buf, 1, 500); 547 return gspca_dev->usb_buf[0]; 548} 549 550static void reg_w(struct gspca_dev *gspca_dev, 551 u16 index) 552{ 553 usb_control_msg(gspca_dev->dev, 554 usb_sndctrlpipe(gspca_dev->dev, 0), 555 0, 556 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 557 0, index, 558 NULL, 0, 500); 559} 560 561static void reg_w_buf(struct gspca_dev *gspca_dev, 562 const u8 *buffer, u16 len) 563{ 564 if (len <= USB_BUF_SZ) { 565 memcpy(gspca_dev->usb_buf, buffer, len); 566 usb_control_msg(gspca_dev->dev, 567 usb_sndctrlpipe(gspca_dev->dev, 0), 568 0, 569 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 570 0x01, 0, 571 gspca_dev->usb_buf, len, 500); 572 } else { 573 u8 *tmpbuf; 574 575 tmpbuf = kmemdup(buffer, len, GFP_KERNEL); 576 if (!tmpbuf) { 577 err("Out of memory"); 578 return; 579 } 580 usb_control_msg(gspca_dev->dev, 581 usb_sndctrlpipe(gspca_dev->dev, 0), 582 0, 583 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 584 0x01, 0, 585 tmpbuf, len, 500); 586 kfree(tmpbuf); 587 } 588} 589 590/* write values to consecutive registers */ 591static void reg_w_ixbuf(struct gspca_dev *gspca_dev, 592 u8 reg, 593 const u8 *buffer, u16 len) 594{ 595 int i; 596 u8 *p, *tmpbuf; 597 598 if (len * 2 <= USB_BUF_SZ) { 599 p = tmpbuf = gspca_dev->usb_buf; 600 } else { 601 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL); 602 if (!tmpbuf) { 603 err("Out of memory"); 604 return; 605 } 606 } 607 i = len; 608 while (--i >= 0) { 609 *p++ = reg++; 610 *p++ = *buffer++; 611 } 612 usb_control_msg(gspca_dev->dev, 613 usb_sndctrlpipe(gspca_dev->dev, 0), 614 0, 615 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 616 0x01, 0, 617 tmpbuf, len * 2, 500); 618 if (len * 2 > USB_BUF_SZ) 619 kfree(tmpbuf); 620} 621 622static void om6802_sensor_init(struct gspca_dev *gspca_dev) 623{ 624 int i; 625 const u8 *p; 626 u8 byte; 627 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05}; 628 static const u8 sensor_init[] = { 629 0xdf, 0x6d, 630 0xdd, 0x18, 631 0x5a, 0xe0, 632 0x5c, 0x07, 633 0x5d, 0xb0, 634 0x5e, 0x1e, 635 0x60, 0x71, 636 0xef, 0x00, 637 0xe9, 0x00, 638 0xea, 0x00, 639 0x90, 0x24, 640 0x91, 0xb2, 641 0x82, 0x32, 642 0xfd, 0x41, 643 0x00 /* table end */ 644 }; 645 646 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset); 647 msleep(100); 648 i = 4; 649 while (--i > 0) { 650 byte = reg_r(gspca_dev, 0x0060); 651 if (!(byte & 0x01)) 652 break; 653 msleep(100); 654 } 655 byte = reg_r(gspca_dev, 0x0063); 656 if (byte != 0x17) { 657 err("Bad sensor reset %02x", byte); 658 /* continue? */ 659 } 660 661 p = sensor_init; 662 while (*p != 0) { 663 val[1] = *p++; 664 val[3] = *p++; 665 if (*p == 0) 666 reg_w(gspca_dev, 0x3c80); 667 reg_w_buf(gspca_dev, val, sizeof val); 668 i = 4; 669 while (--i >= 0) { 670 msleep(15); 671 byte = reg_r(gspca_dev, 0x60); 672 if (!(byte & 0x01)) 673 break; 674 } 675 } 676 msleep(15); 677 reg_w(gspca_dev, 0x3c80); 678} 679 680/* this function is called at probe time */ 681static int sd_config(struct gspca_dev *gspca_dev, 682 const struct usb_device_id *id) 683{ 684 struct sd *sd = (struct sd *) gspca_dev; 685 struct cam *cam; 686 687 cam = &gspca_dev->cam; 688 689 cam->cam_mode = vga_mode_t16; 690 cam->nmodes = ARRAY_SIZE(vga_mode_t16); 691 692 sd->brightness = BRIGHTNESS_DEF; 693 sd->contrast = CONTRAST_DEF; 694 sd->colors = COLORS_DEF; 695 sd->gamma = GAMMA_DEF; 696 sd->autogain = AUTOGAIN_DEF; 697 sd->mirror = MIRROR_DEF; 698 sd->freq = FREQ_DEF; 699 sd->awb = AWB_DEF; 700 sd->sharpness = SHARPNESS_DEF; 701 sd->effect = EFFECTS_DEF; 702 sd->red_gain = RED_GAIN_DEF; 703 sd->blue_gain = BLUE_GAIN_DEF; 704 sd->green_gain = GAIN_DEF * 3 - RED_GAIN_DEF - BLUE_GAIN_DEF; 705 706 return 0; 707} 708 709static void setbrightness(struct gspca_dev *gspca_dev) 710{ 711 struct sd *sd = (struct sd *) gspca_dev; 712 unsigned int brightness; 713 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 }; 714 715 brightness = sd->brightness; 716 if (brightness < 7) { 717 set6[1] = 0x26; 718 set6[3] = 0x70 - brightness * 0x10; 719 } else { 720 set6[3] = 0x00 + ((brightness - 7) * 0x10); 721 } 722 723 reg_w_buf(gspca_dev, set6, sizeof set6); 724} 725 726static void setcontrast(struct gspca_dev *gspca_dev) 727{ 728 struct sd *sd = (struct sd *) gspca_dev; 729 unsigned int contrast = sd->contrast; 730 u16 reg_to_write; 731 732 if (contrast < 7) 733 reg_to_write = 0x8ea9 - contrast * 0x200; 734 else 735 reg_to_write = 0x00a9 + (contrast - 7) * 0x200; 736 737 reg_w(gspca_dev, reg_to_write); 738} 739 740static void setcolors(struct gspca_dev *gspca_dev) 741{ 742 struct sd *sd = (struct sd *) gspca_dev; 743 u16 reg_to_write; 744 745 reg_to_write = 0x80bb + sd->colors * 0x100; /* was 0xc0 */ 746 reg_w(gspca_dev, reg_to_write); 747} 748 749static void setgamma(struct gspca_dev *gspca_dev) 750{ 751 struct sd *sd = (struct sd *) gspca_dev; 752 753 PDEBUG(D_CONF, "Gamma: %d", sd->gamma); 754 reg_w_ixbuf(gspca_dev, 0x90, 755 gamma_table[sd->gamma], sizeof gamma_table[0]); 756} 757 758static void setRGB(struct gspca_dev *gspca_dev) 759{ 760 struct sd *sd = (struct sd *) gspca_dev; 761 u8 all_gain_reg[6] = 762 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00}; 763 764 all_gain_reg[1] = sd->red_gain; 765 all_gain_reg[3] = sd->blue_gain; 766 all_gain_reg[5] = sd->green_gain; 767 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg); 768} 769 770/* Generic fnc for r/b balance, exposure and awb */ 771static void setawb(struct gspca_dev *gspca_dev) 772{ 773 struct sd *sd = (struct sd *) gspca_dev; 774 u16 reg80; 775 776 reg80 = (sensor_data[sd->sensor].reg80 << 8) | 0x80; 777 778 /* on awb leave defaults values */ 779 if (!sd->awb) { 780 /* shoud we wait here.. */ 781 /* update and reset RGB gains with webcam values */ 782 sd->red_gain = reg_r(gspca_dev, 0x0087); 783 sd->blue_gain = reg_r(gspca_dev, 0x0088); 784 sd->green_gain = reg_r(gspca_dev, 0x0089); 785 reg80 &= ~0x0400; /* AWB off */ 786 } 787 reg_w(gspca_dev, reg80); 788 reg_w(gspca_dev, reg80); 789} 790 791static void init_gains(struct gspca_dev *gspca_dev) 792{ 793 struct sd *sd = (struct sd *) gspca_dev; 794 u16 reg80; 795 u8 all_gain_reg[8] = 796 {0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00}; 797 798 all_gain_reg[1] = sd->red_gain; 799 all_gain_reg[3] = sd->blue_gain; 800 all_gain_reg[5] = sd->green_gain; 801 reg80 = sensor_data[sd->sensor].reg80; 802 if (!sd->awb) 803 reg80 &= ~0x04; 804 all_gain_reg[7] = reg80; 805 reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg); 806 807 reg_w(gspca_dev, (sd->red_gain << 8) + 0x87); 808 reg_w(gspca_dev, (sd->blue_gain << 8) + 0x88); 809 reg_w(gspca_dev, (sd->green_gain << 8) + 0x89); 810} 811 812static void setsharpness(struct gspca_dev *gspca_dev) 813{ 814 struct sd *sd = (struct sd *) gspca_dev; 815 u16 reg_to_write; 816 817 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness; 818 819 reg_w(gspca_dev, reg_to_write); 820} 821 822static void setfreq(struct gspca_dev *gspca_dev) 823{ 824 struct sd *sd = (struct sd *) gspca_dev; 825 u8 reg66; 826 u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 }; 827 828 switch (sd->sensor) { 829 case SENSOR_LT168G: 830 if (sd->freq != 0) 831 freq[3] = 0xa8; 832 reg66 = 0x41; 833 break; 834 case SENSOR_OM6802: 835 reg66 = 0xca; 836 break; 837 default: 838 reg66 = 0x40; 839 break; 840 } 841 switch (sd->freq) { 842 case 0: /* no flicker */ 843 freq[3] = 0xf0; 844 break; 845 case 2: /* 60Hz */ 846 reg66 &= ~0x40; 847 break; 848 } 849 freq[1] = reg66; 850 851 reg_w_buf(gspca_dev, freq, sizeof freq); 852} 853 854/* this function is called at probe and resume time */ 855static int sd_init(struct gspca_dev *gspca_dev) 856{ 857 /* some of this registers are not really neded, because 858 * they are overriden by setbrigthness, setcontrast, etc, 859 * but wont hurt anyway, and can help someone with similar webcam 860 * to see the initial parameters.*/ 861 struct sd *sd = (struct sd *) gspca_dev; 862 const struct additional_sensor_data *sensor; 863 int i; 864 u16 sensor_id; 865 u8 test_byte = 0; 866 867 static const u8 read_indexs[] = 868 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5, 869 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 }; 870 static const u8 n1[] = 871 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04}; 872 static const u8 n2[] = 873 {0x08, 0x00}; 874 875 sensor_id = (reg_r(gspca_dev, 0x06) << 8) 876 | reg_r(gspca_dev, 0x07); 877 switch (sensor_id & 0xff0f) { 878 case 0x0801: 879 PDEBUG(D_PROBE, "sensor tas5130a"); 880 sd->sensor = SENSOR_TAS5130A; 881 break; 882 case 0x0802: 883 PDEBUG(D_PROBE, "sensor lt168g"); 884 sd->sensor = SENSOR_LT168G; 885 break; 886 case 0x0803: 887 PDEBUG(D_PROBE, "sensor 'other'"); 888 sd->sensor = SENSOR_OTHER; 889 break; 890 case 0x0807: 891 PDEBUG(D_PROBE, "sensor om6802"); 892 sd->sensor = SENSOR_OM6802; 893 break; 894 default: 895 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id); 896 return -EINVAL; 897 } 898 899 if (sd->sensor == SENSOR_OM6802) { 900 reg_w_buf(gspca_dev, n1, sizeof n1); 901 i = 5; 902 while (--i >= 0) { 903 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset); 904 test_byte = reg_r(gspca_dev, 0x0063); 905 msleep(100); 906 if (test_byte == 0x17) 907 break; /* OK */ 908 } 909 if (i < 0) { 910 err("Bad sensor reset %02x", test_byte); 911 return -EIO; 912 } 913 reg_w_buf(gspca_dev, n2, sizeof n2); 914 } 915 916 i = 0; 917 while (read_indexs[i] != 0x00) { 918 test_byte = reg_r(gspca_dev, read_indexs[i]); 919 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i], 920 test_byte); 921 i++; 922 } 923 924 sensor = &sensor_data[sd->sensor]; 925 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3); 926 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz); 927 928 if (sd->sensor == SENSOR_LT168G) { 929 test_byte = reg_r(gspca_dev, 0x80); 930 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80, 931 test_byte); 932 reg_w(gspca_dev, 0x6c80); 933 } 934 935 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); 936 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); 937 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); 938 939 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80); 940 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80); 941 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e); 942 943 setbrightness(gspca_dev); 944 setcontrast(gspca_dev); 945 setgamma(gspca_dev); 946 setcolors(gspca_dev); 947 setsharpness(gspca_dev); 948 init_gains(gspca_dev); 949 setfreq(gspca_dev); 950 951 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5); 952 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8); 953 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); 954 955 if (sd->sensor == SENSOR_LT168G) { 956 test_byte = reg_r(gspca_dev, 0x80); 957 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80, 958 test_byte); 959 reg_w(gspca_dev, 0x6c80); 960 } 961 962 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); 963 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); 964 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); 965 966 return 0; 967} 968 969static void setmirror(struct gspca_dev *gspca_dev) 970{ 971 struct sd *sd = (struct sd *) gspca_dev; 972 u8 hflipcmd[8] = 973 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09}; 974 975 if (sd->mirror) 976 hflipcmd[3] = 0x01; 977 978 reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd); 979} 980 981static void seteffect(struct gspca_dev *gspca_dev) 982{ 983 struct sd *sd = (struct sd *) gspca_dev; 984 985 reg_w_buf(gspca_dev, effects_table[sd->effect], 986 sizeof effects_table[0]); 987 if (sd->effect == 1 || sd->effect == 5) { 988 PDEBUG(D_CONF, 989 "This effect have been disabled for webcam \"safety\""); 990 return; 991 } 992 993 if (sd->effect == 1 || sd->effect == 4) 994 reg_w(gspca_dev, 0x4aa6); 995 else 996 reg_w(gspca_dev, 0xfaa6); 997} 998 999/* Is this really needed? 1000 * i added some module parameters for test with some users */ 1001static void poll_sensor(struct gspca_dev *gspca_dev) 1002{ 1003 static const u8 poll1[] = 1004 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82, 1005 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34, 1006 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01, 1007 0x60, 0x14}; 1008 static const u8 poll2[] = 1009 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9, 1010 0x73, 0x02, 0x73, 0x02, 0x60, 0x14}; 1011 static const u8 noise03[] = /* (some differences / ms-drv) */ 1012 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f, 1013 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c, 1014 0xc2, 0x80, 0xc3, 0x10}; 1015 1016 PDEBUG(D_STREAM, "[Sensor requires polling]"); 1017 reg_w_buf(gspca_dev, poll1, sizeof poll1); 1018 reg_w_buf(gspca_dev, poll2, sizeof poll2); 1019 reg_w_buf(gspca_dev, noise03, sizeof noise03); 1020} 1021 1022static int sd_start(struct gspca_dev *gspca_dev) 1023{ 1024 struct sd *sd = (struct sd *) gspca_dev; 1025 const struct additional_sensor_data *sensor; 1026 int i, mode; 1027 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 }; 1028 static const u8 t3[] = 1029 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 }; 1030 1031 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; 1032 switch (mode) { 1033 case 0: /* 640x480 (0x00) */ 1034 break; 1035 case 1: /* 352x288 */ 1036 t2[1] = 0x40; 1037 break; 1038 case 2: /* 320x240 */ 1039 t2[1] = 0x10; 1040 break; 1041 case 3: /* 176x144 */ 1042 t2[1] = 0x50; 1043 break; 1044 default: 1045/* case 4: * 160x120 */ 1046 t2[1] = 0x20; 1047 break; 1048 } 1049 1050 switch (sd->sensor) { 1051 case SENSOR_OM6802: 1052 om6802_sensor_init(gspca_dev); 1053 break; 1054 case SENSOR_TAS5130A: 1055 i = 0; 1056 for (;;) { 1057 reg_w_buf(gspca_dev, tas5130a_sensor_init[i], 1058 sizeof tas5130a_sensor_init[0]); 1059 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1) 1060 break; 1061 i++; 1062 } 1063 reg_w(gspca_dev, 0x3c80); 1064 /* just in case and to keep sync with logs (for mine) */ 1065 reg_w_buf(gspca_dev, tas5130a_sensor_init[i], 1066 sizeof tas5130a_sensor_init[0]); 1067 reg_w(gspca_dev, 0x3c80); 1068 break; 1069 } 1070 sensor = &sensor_data[sd->sensor]; 1071 setfreq(gspca_dev); 1072 reg_r(gspca_dev, 0x0012); 1073 reg_w_buf(gspca_dev, t2, sizeof t2); 1074 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3); 1075 reg_w(gspca_dev, 0x0013); 1076 msleep(15); 1077 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); 1078 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); 1079 1080 if (sd->sensor == SENSOR_OM6802) 1081 poll_sensor(gspca_dev); 1082 1083 return 0; 1084} 1085 1086static void sd_stopN(struct gspca_dev *gspca_dev) 1087{ 1088 struct sd *sd = (struct sd *) gspca_dev; 1089 1090 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream, 1091 sizeof sensor_data[sd->sensor].stream); 1092 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream, 1093 sizeof sensor_data[sd->sensor].stream); 1094 if (sd->sensor == SENSOR_OM6802) { 1095 msleep(20); 1096 reg_w(gspca_dev, 0x0309); 1097 } 1098} 1099 1100static void sd_pkt_scan(struct gspca_dev *gspca_dev, 1101 u8 *data, /* isoc packet */ 1102 int len) /* iso packet length */ 1103{ 1104 int pkt_type; 1105 1106 if (data[0] == 0x5a) { 1107 /* Control Packet, after this came the header again, 1108 * but extra bytes came in the packet before this, 1109 * sometimes an EOF arrives, sometimes not... */ 1110 return; 1111 } 1112 data += 2; 1113 len -= 2; 1114 if (data[0] == 0xff && data[1] == 0xd8) 1115 pkt_type = FIRST_PACKET; 1116 else if (data[len - 2] == 0xff && data[len - 1] == 0xd9) 1117 pkt_type = LAST_PACKET; 1118 else 1119 pkt_type = INTER_PACKET; 1120 gspca_frame_add(gspca_dev, pkt_type, data, len); 1121} 1122 1123static int sd_setblue_gain(struct gspca_dev *gspca_dev, __s32 val) 1124{ 1125 struct sd *sd = (struct sd *) gspca_dev; 1126 1127 sd->blue_gain = val; 1128 if (gspca_dev->streaming) 1129 reg_w(gspca_dev, (val << 8) + 0x88); 1130 return 0; 1131} 1132 1133static int sd_getblue_gain(struct gspca_dev *gspca_dev, __s32 *val) 1134{ 1135 struct sd *sd = (struct sd *) gspca_dev; 1136 1137 *val = sd->blue_gain; 1138 return 0; 1139} 1140 1141static int sd_setred_gain(struct gspca_dev *gspca_dev, __s32 val) 1142{ 1143 struct sd *sd = (struct sd *) gspca_dev; 1144 1145 sd->red_gain = val; 1146 if (gspca_dev->streaming) 1147 reg_w(gspca_dev, (val << 8) + 0x87); 1148 1149 return 0; 1150} 1151 1152static int sd_getred_gain(struct gspca_dev *gspca_dev, __s32 *val) 1153{ 1154 struct sd *sd = (struct sd *) gspca_dev; 1155 1156 *val = sd->red_gain; 1157 return 0; 1158} 1159 1160static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) 1161{ 1162 struct sd *sd = (struct sd *) gspca_dev; 1163 u16 psg, nsg; 1164 1165 psg = sd->red_gain + sd->blue_gain + sd->green_gain; 1166 nsg = val * 3; 1167 sd->red_gain = sd->red_gain * nsg / psg; 1168 if (sd->red_gain > 0x40) 1169 sd->red_gain = 0x40; 1170 else if (sd->red_gain < 0x10) 1171 sd->red_gain = 0x10; 1172 sd->blue_gain = sd->blue_gain * nsg / psg; 1173 if (sd->blue_gain > 0x40) 1174 sd->blue_gain = 0x40; 1175 else if (sd->blue_gain < 0x10) 1176 sd->blue_gain = 0x10; 1177 sd->green_gain = sd->green_gain * nsg / psg; 1178 if (sd->green_gain > 0x40) 1179 sd->green_gain = 0x40; 1180 else if (sd->green_gain < 0x10) 1181 sd->green_gain = 0x10; 1182 1183 if (gspca_dev->streaming) 1184 setRGB(gspca_dev); 1185 return 0; 1186} 1187 1188static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) 1189{ 1190 struct sd *sd = (struct sd *) gspca_dev; 1191 1192 *val = (sd->red_gain + sd->blue_gain + sd->green_gain) / 3; 1193 return 0; 1194} 1195 1196static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 1197{ 1198 struct sd *sd = (struct sd *) gspca_dev; 1199 1200 sd->brightness = val; 1201 if (gspca_dev->streaming) 1202 setbrightness(gspca_dev); 1203 return 0; 1204} 1205 1206static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) 1207{ 1208 struct sd *sd = (struct sd *) gspca_dev; 1209 1210 *val = sd->brightness; 1211 return *val; 1212} 1213 1214static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val) 1215{ 1216 struct sd *sd = (struct sd *) gspca_dev; 1217 1218 sd->awb = val; 1219 if (gspca_dev->streaming) 1220 setawb(gspca_dev); 1221 return 0; 1222} 1223 1224static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val) 1225{ 1226 struct sd *sd = (struct sd *) gspca_dev; 1227 1228 *val = sd->awb; 1229 return *val; 1230} 1231 1232static int sd_setmirror(struct gspca_dev *gspca_dev, __s32 val) 1233{ 1234 struct sd *sd = (struct sd *) gspca_dev; 1235 1236 sd->mirror = val; 1237 if (gspca_dev->streaming) 1238 setmirror(gspca_dev); 1239 return 0; 1240} 1241 1242static int sd_getmirror(struct gspca_dev *gspca_dev, __s32 *val) 1243{ 1244 struct sd *sd = (struct sd *) gspca_dev; 1245 1246 *val = sd->mirror; 1247 return *val; 1248} 1249 1250static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val) 1251{ 1252 struct sd *sd = (struct sd *) gspca_dev; 1253 1254 sd->effect = val; 1255 if (gspca_dev->streaming) 1256 seteffect(gspca_dev); 1257 return 0; 1258} 1259 1260static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val) 1261{ 1262 struct sd *sd = (struct sd *) gspca_dev; 1263 1264 *val = sd->effect; 1265 return *val; 1266} 1267 1268static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) 1269{ 1270 struct sd *sd = (struct sd *) gspca_dev; 1271 1272 sd->contrast = val; 1273 if (gspca_dev->streaming) 1274 setcontrast(gspca_dev); 1275 return 0; 1276} 1277 1278static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) 1279{ 1280 struct sd *sd = (struct sd *) gspca_dev; 1281 1282 *val = sd->contrast; 1283 return *val; 1284} 1285 1286static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) 1287{ 1288 struct sd *sd = (struct sd *) gspca_dev; 1289 1290 sd->colors = val; 1291 if (gspca_dev->streaming) 1292 setcolors(gspca_dev); 1293 return 0; 1294} 1295 1296static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) 1297{ 1298 struct sd *sd = (struct sd *) gspca_dev; 1299 1300 *val = sd->colors; 1301 return 0; 1302} 1303 1304static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val) 1305{ 1306 struct sd *sd = (struct sd *) gspca_dev; 1307 1308 sd->gamma = val; 1309 if (gspca_dev->streaming) 1310 setgamma(gspca_dev); 1311 return 0; 1312} 1313 1314static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val) 1315{ 1316 struct sd *sd = (struct sd *) gspca_dev; 1317 1318 *val = sd->gamma; 1319 return 0; 1320} 1321 1322static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) 1323{ 1324 struct sd *sd = (struct sd *) gspca_dev; 1325 1326 sd->freq = val; 1327 if (gspca_dev->streaming) 1328 setfreq(gspca_dev); 1329 return 0; 1330} 1331 1332static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) 1333{ 1334 struct sd *sd = (struct sd *) gspca_dev; 1335 1336 *val = sd->freq; 1337 return 0; 1338} 1339 1340static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) 1341{ 1342 struct sd *sd = (struct sd *) gspca_dev; 1343 1344 sd->sharpness = val; 1345 if (gspca_dev->streaming) 1346 setsharpness(gspca_dev); 1347 return 0; 1348} 1349 1350static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) 1351{ 1352 struct sd *sd = (struct sd *) gspca_dev; 1353 1354 *val = sd->sharpness; 1355 return 0; 1356} 1357 1358/* Low Light set here......*/ 1359static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val) 1360{ 1361 struct sd *sd = (struct sd *) gspca_dev; 1362 1363 sd->autogain = val; 1364 if (val != 0) 1365 reg_w(gspca_dev, 0xf48e); 1366 else 1367 reg_w(gspca_dev, 0xb48e); 1368 return 0; 1369} 1370 1371static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val) 1372{ 1373 struct sd *sd = (struct sd *) gspca_dev; 1374 1375 *val = sd->autogain; 1376 return 0; 1377} 1378 1379static int sd_querymenu(struct gspca_dev *gspca_dev, 1380 struct v4l2_querymenu *menu) 1381{ 1382 switch (menu->id) { 1383 case V4L2_CID_POWER_LINE_FREQUENCY: 1384 switch (menu->index) { 1385 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ 1386 strcpy((char *) menu->name, "50 Hz"); 1387 return 0; 1388 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ 1389 strcpy((char *) menu->name, "60 Hz"); 1390 return 0; 1391 } 1392 break; 1393 case V4L2_CID_EFFECTS: 1394 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) { 1395 strncpy((char *) menu->name, 1396 effects_control[menu->index], 1397 sizeof menu->name); 1398 return 0; 1399 } 1400 break; 1401 } 1402 return -EINVAL; 1403} 1404 1405/* sub-driver description */ 1406static const struct sd_desc sd_desc = { 1407 .name = MODULE_NAME, 1408 .ctrls = sd_ctrls, 1409 .nctrls = ARRAY_SIZE(sd_ctrls), 1410 .config = sd_config, 1411 .init = sd_init, 1412 .start = sd_start, 1413 .stopN = sd_stopN, 1414 .pkt_scan = sd_pkt_scan, 1415 .querymenu = sd_querymenu, 1416}; 1417 1418/* -- module initialisation -- */ 1419static const __devinitdata struct usb_device_id device_table[] = { 1420 {USB_DEVICE(0x17a1, 0x0128)}, 1421 {} 1422}; 1423MODULE_DEVICE_TABLE(usb, device_table); 1424 1425/* -- device connect -- */ 1426static int sd_probe(struct usb_interface *intf, 1427 const struct usb_device_id *id) 1428{ 1429 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 1430 THIS_MODULE); 1431} 1432 1433static struct usb_driver sd_driver = { 1434 .name = MODULE_NAME, 1435 .id_table = device_table, 1436 .probe = sd_probe, 1437 .disconnect = gspca_disconnect, 1438#ifdef CONFIG_PM 1439 .suspend = gspca_suspend, 1440 .resume = gspca_resume, 1441#endif 1442}; 1443 1444/* -- module insert / remove -- */ 1445static int __init sd_mod_init(void) 1446{ 1447 int ret; 1448 ret = usb_register(&sd_driver); 1449 if (ret < 0) 1450 return ret; 1451 PDEBUG(D_PROBE, "registered"); 1452 return 0; 1453} 1454static void __exit sd_mod_exit(void) 1455{ 1456 usb_deregister(&sd_driver); 1457 PDEBUG(D_PROBE, "deregistered"); 1458} 1459 1460module_init(sd_mod_init); 1461module_exit(sd_mod_exit); 1462