spca506.c (18347B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * SPCA506 chip based cameras function 4 * M Xhaard 15/04/2004 based on different work Mark Taylor and others 5 * and my own snoopy file on a pv-321c donate by a german compagny 6 * "Firma Frank Gmbh" from Saarbruecken 7 * 8 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> 9 */ 10 11#define MODULE_NAME "spca506" 12 13#include "gspca.h" 14 15MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); 16MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver"); 17MODULE_LICENSE("GPL"); 18 19/* specific webcam descriptor */ 20struct sd { 21 struct gspca_dev gspca_dev; /* !! must be the first item */ 22 23 char norme; 24 char channel; 25}; 26 27static const struct v4l2_pix_format vga_mode[] = { 28 {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 29 .bytesperline = 160, 30 .sizeimage = 160 * 120 * 3 / 2, 31 .colorspace = V4L2_COLORSPACE_SRGB, 32 .priv = 5}, 33 {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 34 .bytesperline = 176, 35 .sizeimage = 176 * 144 * 3 / 2, 36 .colorspace = V4L2_COLORSPACE_SRGB, 37 .priv = 4}, 38 {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 39 .bytesperline = 320, 40 .sizeimage = 320 * 240 * 3 / 2, 41 .colorspace = V4L2_COLORSPACE_SRGB, 42 .priv = 2}, 43 {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 44 .bytesperline = 352, 45 .sizeimage = 352 * 288 * 3 / 2, 46 .colorspace = V4L2_COLORSPACE_SRGB, 47 .priv = 1}, 48 {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE, 49 .bytesperline = 640, 50 .sizeimage = 640 * 480 * 3 / 2, 51 .colorspace = V4L2_COLORSPACE_SRGB, 52 .priv = 0}, 53}; 54 55#define SPCA50X_OFFSET_DATA 10 56 57#define SAA7113_bright 0x0a /* defaults 0x80 */ 58#define SAA7113_contrast 0x0b /* defaults 0x47 */ 59#define SAA7113_saturation 0x0c /* defaults 0x40 */ 60#define SAA7113_hue 0x0d /* defaults 0x00 */ 61#define SAA7113_I2C_BASE_WRITE 0x4a 62 63/* read 'len' bytes to gspca_dev->usb_buf */ 64static void reg_r(struct gspca_dev *gspca_dev, 65 __u16 req, 66 __u16 index, 67 __u16 length) 68{ 69 usb_control_msg(gspca_dev->dev, 70 usb_rcvctrlpipe(gspca_dev->dev, 0), 71 req, 72 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 73 0, /* value */ 74 index, gspca_dev->usb_buf, length, 75 500); 76} 77 78static void reg_w(struct usb_device *dev, 79 __u16 req, 80 __u16 value, 81 __u16 index) 82{ 83 usb_control_msg(dev, 84 usb_sndctrlpipe(dev, 0), 85 req, 86 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 87 value, index, 88 NULL, 0, 500); 89} 90 91static void spca506_Initi2c(struct gspca_dev *gspca_dev) 92{ 93 reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004); 94} 95 96static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur, 97 __u16 reg) 98{ 99 int retry = 60; 100 101 reg_w(gspca_dev->dev, 0x07, reg, 0x0001); 102 reg_w(gspca_dev->dev, 0x07, valeur, 0x0000); 103 while (retry--) { 104 reg_r(gspca_dev, 0x07, 0x0003, 2); 105 if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00) 106 break; 107 } 108} 109 110static void spca506_SetNormeInput(struct gspca_dev *gspca_dev, 111 __u16 norme, 112 __u16 channel) 113{ 114 struct sd *sd = (struct sd *) gspca_dev; 115/* fixme: check if channel == 0..3 and 6..9 (8 values) */ 116 __u8 setbit0 = 0x00; 117 __u8 setbit1 = 0x00; 118 __u8 videomask = 0x00; 119 120 gspca_dbg(gspca_dev, D_STREAM, "** Open Set Norme **\n"); 121 spca506_Initi2c(gspca_dev); 122 /* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */ 123 /* Composite channel bit1 -> 1 S-video bit 1 -> 0 */ 124 /* and exclude SAA7113 reserved channel set default 0 otherwise */ 125 if (norme & V4L2_STD_NTSC) 126 setbit0 = 0x01; 127 if (channel == 4 || channel == 5 || channel > 9) 128 channel = 0; 129 if (channel < 4) 130 setbit1 = 0x02; 131 videomask = (0x48 | setbit0 | setbit1); 132 reg_w(gspca_dev->dev, 0x08, videomask, 0x0000); 133 spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02); 134 135 if (norme & V4L2_STD_NTSC) 136 spca506_WriteI2c(gspca_dev, 0x33, 0x0e); 137 /* Chrominance Control NTSC N */ 138 else if (norme & V4L2_STD_SECAM) 139 spca506_WriteI2c(gspca_dev, 0x53, 0x0e); 140 /* Chrominance Control SECAM */ 141 else 142 spca506_WriteI2c(gspca_dev, 0x03, 0x0e); 143 /* Chrominance Control PAL BGHIV */ 144 145 sd->norme = norme; 146 sd->channel = channel; 147 gspca_dbg(gspca_dev, D_STREAM, "Set Video Byte to 0x%2x\n", videomask); 148 gspca_dbg(gspca_dev, D_STREAM, "Set Norme: %08x Channel %d", 149 norme, channel); 150} 151 152static void spca506_GetNormeInput(struct gspca_dev *gspca_dev, 153 __u16 *norme, __u16 *channel) 154{ 155 struct sd *sd = (struct sd *) gspca_dev; 156 157 /* Read the register is not so good value change so 158 we use your own copy in spca50x struct */ 159 *norme = sd->norme; 160 *channel = sd->channel; 161 gspca_dbg(gspca_dev, D_STREAM, "Get Norme: %d Channel %d\n", 162 *norme, *channel); 163} 164 165static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code, 166 __u16 xmult, __u16 ymult) 167{ 168 struct usb_device *dev = gspca_dev->dev; 169 170 gspca_dbg(gspca_dev, D_STREAM, "** SetSize **\n"); 171 reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000); 172 /* Soft snap 0x40 Hard 0x41 */ 173 reg_w(dev, 0x04, 0x41, 0x0001); 174 reg_w(dev, 0x04, 0x00, 0x0002); 175 /* reserved */ 176 reg_w(dev, 0x04, 0x00, 0x0003); 177 178 /* reserved */ 179 reg_w(dev, 0x04, 0x00, 0x0004); 180 /* reserved */ 181 reg_w(dev, 0x04, 0x01, 0x0005); 182 /* reserced */ 183 reg_w(dev, 0x04, xmult, 0x0006); 184 /* reserved */ 185 reg_w(dev, 0x04, ymult, 0x0007); 186 /* compression 1 */ 187 reg_w(dev, 0x04, 0x00, 0x0008); 188 /* T=64 -> 2 */ 189 reg_w(dev, 0x04, 0x00, 0x0009); 190 /* threshold2D */ 191 reg_w(dev, 0x04, 0x21, 0x000a); 192 /* quantization */ 193 reg_w(dev, 0x04, 0x00, 0x000b); 194} 195 196/* this function is called at probe time */ 197static int sd_config(struct gspca_dev *gspca_dev, 198 const struct usb_device_id *id) 199{ 200 struct cam *cam; 201 202 cam = &gspca_dev->cam; 203 cam->cam_mode = vga_mode; 204 cam->nmodes = ARRAY_SIZE(vga_mode); 205 return 0; 206} 207 208/* this function is called at probe and resume time */ 209static int sd_init(struct gspca_dev *gspca_dev) 210{ 211 struct usb_device *dev = gspca_dev->dev; 212 213 reg_w(dev, 0x03, 0x00, 0x0004); 214 reg_w(dev, 0x03, 0xFF, 0x0003); 215 reg_w(dev, 0x03, 0x00, 0x0000); 216 reg_w(dev, 0x03, 0x1c, 0x0001); 217 reg_w(dev, 0x03, 0x18, 0x0001); 218 /* Init on PAL and composite input0 */ 219 spca506_SetNormeInput(gspca_dev, 0, 0); 220 reg_w(dev, 0x03, 0x1c, 0x0001); 221 reg_w(dev, 0x03, 0x18, 0x0001); 222 reg_w(dev, 0x05, 0x00, 0x0000); 223 reg_w(dev, 0x05, 0xef, 0x0001); 224 reg_w(dev, 0x05, 0x00, 0x00c1); 225 reg_w(dev, 0x05, 0x00, 0x00c2); 226 reg_w(dev, 0x06, 0x18, 0x0002); 227 reg_w(dev, 0x06, 0xf5, 0x0011); 228 reg_w(dev, 0x06, 0x02, 0x0012); 229 reg_w(dev, 0x06, 0xfb, 0x0013); 230 reg_w(dev, 0x06, 0x00, 0x0014); 231 reg_w(dev, 0x06, 0xa4, 0x0051); 232 reg_w(dev, 0x06, 0x40, 0x0052); 233 reg_w(dev, 0x06, 0x71, 0x0053); 234 reg_w(dev, 0x06, 0x40, 0x0054); 235 /************************************************/ 236 reg_w(dev, 0x03, 0x00, 0x0004); 237 reg_w(dev, 0x03, 0x00, 0x0003); 238 reg_w(dev, 0x03, 0x00, 0x0004); 239 reg_w(dev, 0x03, 0xFF, 0x0003); 240 reg_w(dev, 0x02, 0x00, 0x0000); 241 reg_w(dev, 0x03, 0x60, 0x0000); 242 reg_w(dev, 0x03, 0x18, 0x0001); 243 /* for a better reading mx :) */ 244 /*sdca506_WriteI2c(value,register) */ 245 spca506_Initi2c(gspca_dev); 246 spca506_WriteI2c(gspca_dev, 0x08, 0x01); 247 spca506_WriteI2c(gspca_dev, 0xc0, 0x02); 248 /* input composite video */ 249 spca506_WriteI2c(gspca_dev, 0x33, 0x03); 250 spca506_WriteI2c(gspca_dev, 0x00, 0x04); 251 spca506_WriteI2c(gspca_dev, 0x00, 0x05); 252 spca506_WriteI2c(gspca_dev, 0x0d, 0x06); 253 spca506_WriteI2c(gspca_dev, 0xf0, 0x07); 254 spca506_WriteI2c(gspca_dev, 0x98, 0x08); 255 spca506_WriteI2c(gspca_dev, 0x03, 0x09); 256 spca506_WriteI2c(gspca_dev, 0x80, 0x0a); 257 spca506_WriteI2c(gspca_dev, 0x47, 0x0b); 258 spca506_WriteI2c(gspca_dev, 0x48, 0x0c); 259 spca506_WriteI2c(gspca_dev, 0x00, 0x0d); 260 spca506_WriteI2c(gspca_dev, 0x03, 0x0e); /* Chroma Pal adjust */ 261 spca506_WriteI2c(gspca_dev, 0x2a, 0x0f); 262 spca506_WriteI2c(gspca_dev, 0x00, 0x10); 263 spca506_WriteI2c(gspca_dev, 0x0c, 0x11); 264 spca506_WriteI2c(gspca_dev, 0xb8, 0x12); 265 spca506_WriteI2c(gspca_dev, 0x01, 0x13); 266 spca506_WriteI2c(gspca_dev, 0x00, 0x14); 267 spca506_WriteI2c(gspca_dev, 0x00, 0x15); 268 spca506_WriteI2c(gspca_dev, 0x00, 0x16); 269 spca506_WriteI2c(gspca_dev, 0x00, 0x17); 270 spca506_WriteI2c(gspca_dev, 0x00, 0x18); 271 spca506_WriteI2c(gspca_dev, 0x00, 0x19); 272 spca506_WriteI2c(gspca_dev, 0x00, 0x1a); 273 spca506_WriteI2c(gspca_dev, 0x00, 0x1b); 274 spca506_WriteI2c(gspca_dev, 0x00, 0x1c); 275 spca506_WriteI2c(gspca_dev, 0x00, 0x1d); 276 spca506_WriteI2c(gspca_dev, 0x00, 0x1e); 277 spca506_WriteI2c(gspca_dev, 0xa1, 0x1f); 278 spca506_WriteI2c(gspca_dev, 0x02, 0x40); 279 spca506_WriteI2c(gspca_dev, 0xff, 0x41); 280 spca506_WriteI2c(gspca_dev, 0xff, 0x42); 281 spca506_WriteI2c(gspca_dev, 0xff, 0x43); 282 spca506_WriteI2c(gspca_dev, 0xff, 0x44); 283 spca506_WriteI2c(gspca_dev, 0xff, 0x45); 284 spca506_WriteI2c(gspca_dev, 0xff, 0x46); 285 spca506_WriteI2c(gspca_dev, 0xff, 0x47); 286 spca506_WriteI2c(gspca_dev, 0xff, 0x48); 287 spca506_WriteI2c(gspca_dev, 0xff, 0x49); 288 spca506_WriteI2c(gspca_dev, 0xff, 0x4a); 289 spca506_WriteI2c(gspca_dev, 0xff, 0x4b); 290 spca506_WriteI2c(gspca_dev, 0xff, 0x4c); 291 spca506_WriteI2c(gspca_dev, 0xff, 0x4d); 292 spca506_WriteI2c(gspca_dev, 0xff, 0x4e); 293 spca506_WriteI2c(gspca_dev, 0xff, 0x4f); 294 spca506_WriteI2c(gspca_dev, 0xff, 0x50); 295 spca506_WriteI2c(gspca_dev, 0xff, 0x51); 296 spca506_WriteI2c(gspca_dev, 0xff, 0x52); 297 spca506_WriteI2c(gspca_dev, 0xff, 0x53); 298 spca506_WriteI2c(gspca_dev, 0xff, 0x54); 299 spca506_WriteI2c(gspca_dev, 0xff, 0x55); 300 spca506_WriteI2c(gspca_dev, 0xff, 0x56); 301 spca506_WriteI2c(gspca_dev, 0xff, 0x57); 302 spca506_WriteI2c(gspca_dev, 0x00, 0x58); 303 spca506_WriteI2c(gspca_dev, 0x54, 0x59); 304 spca506_WriteI2c(gspca_dev, 0x07, 0x5a); 305 spca506_WriteI2c(gspca_dev, 0x83, 0x5b); 306 spca506_WriteI2c(gspca_dev, 0x00, 0x5c); 307 spca506_WriteI2c(gspca_dev, 0x00, 0x5d); 308 spca506_WriteI2c(gspca_dev, 0x00, 0x5e); 309 spca506_WriteI2c(gspca_dev, 0x00, 0x5f); 310 spca506_WriteI2c(gspca_dev, 0x00, 0x60); 311 spca506_WriteI2c(gspca_dev, 0x05, 0x61); 312 spca506_WriteI2c(gspca_dev, 0x9f, 0x62); 313 gspca_dbg(gspca_dev, D_STREAM, "** Close Init *\n"); 314 return 0; 315} 316 317static int sd_start(struct gspca_dev *gspca_dev) 318{ 319 struct usb_device *dev = gspca_dev->dev; 320 __u16 norme; 321 __u16 channel; 322 323 /**************************************/ 324 reg_w(dev, 0x03, 0x00, 0x0004); 325 reg_w(dev, 0x03, 0x00, 0x0003); 326 reg_w(dev, 0x03, 0x00, 0x0004); 327 reg_w(dev, 0x03, 0xFF, 0x0003); 328 reg_w(dev, 0x02, 0x00, 0x0000); 329 reg_w(dev, 0x03, 0x60, 0x0000); 330 reg_w(dev, 0x03, 0x18, 0x0001); 331 332 /*sdca506_WriteI2c(value,register) */ 333 spca506_Initi2c(gspca_dev); 334 spca506_WriteI2c(gspca_dev, 0x08, 0x01); /* Increment Delay */ 335/* spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */ 336 spca506_WriteI2c(gspca_dev, 0x33, 0x03); 337 /* Analog Input Control 2 */ 338 spca506_WriteI2c(gspca_dev, 0x00, 0x04); 339 /* Analog Input Control 3 */ 340 spca506_WriteI2c(gspca_dev, 0x00, 0x05); 341 /* Analog Input Control 4 */ 342 spca506_WriteI2c(gspca_dev, 0x0d, 0x06); 343 /* Horizontal Sync Start 0xe9-0x0d */ 344 spca506_WriteI2c(gspca_dev, 0xf0, 0x07); 345 /* Horizontal Sync Stop 0x0d-0xf0 */ 346 347 spca506_WriteI2c(gspca_dev, 0x98, 0x08); /* Sync Control */ 348/* Defaults value */ 349 spca506_WriteI2c(gspca_dev, 0x03, 0x09); /* Luminance Control */ 350 spca506_WriteI2c(gspca_dev, 0x80, 0x0a); 351 /* Luminance Brightness */ 352 spca506_WriteI2c(gspca_dev, 0x47, 0x0b); /* Luminance Contrast */ 353 spca506_WriteI2c(gspca_dev, 0x48, 0x0c); 354 /* Chrominance Saturation */ 355 spca506_WriteI2c(gspca_dev, 0x00, 0x0d); 356 /* Chrominance Hue Control */ 357 spca506_WriteI2c(gspca_dev, 0x2a, 0x0f); 358 /* Chrominance Gain Control */ 359 /**************************************/ 360 spca506_WriteI2c(gspca_dev, 0x00, 0x10); 361 /* Format/Delay Control */ 362 spca506_WriteI2c(gspca_dev, 0x0c, 0x11); /* Output Control 1 */ 363 spca506_WriteI2c(gspca_dev, 0xb8, 0x12); /* Output Control 2 */ 364 spca506_WriteI2c(gspca_dev, 0x01, 0x13); /* Output Control 3 */ 365 spca506_WriteI2c(gspca_dev, 0x00, 0x14); /* reserved */ 366 spca506_WriteI2c(gspca_dev, 0x00, 0x15); /* VGATE START */ 367 spca506_WriteI2c(gspca_dev, 0x00, 0x16); /* VGATE STOP */ 368 spca506_WriteI2c(gspca_dev, 0x00, 0x17); /* VGATE Control (MSB) */ 369 spca506_WriteI2c(gspca_dev, 0x00, 0x18); 370 spca506_WriteI2c(gspca_dev, 0x00, 0x19); 371 spca506_WriteI2c(gspca_dev, 0x00, 0x1a); 372 spca506_WriteI2c(gspca_dev, 0x00, 0x1b); 373 spca506_WriteI2c(gspca_dev, 0x00, 0x1c); 374 spca506_WriteI2c(gspca_dev, 0x00, 0x1d); 375 spca506_WriteI2c(gspca_dev, 0x00, 0x1e); 376 spca506_WriteI2c(gspca_dev, 0xa1, 0x1f); 377 spca506_WriteI2c(gspca_dev, 0x02, 0x40); 378 spca506_WriteI2c(gspca_dev, 0xff, 0x41); 379 spca506_WriteI2c(gspca_dev, 0xff, 0x42); 380 spca506_WriteI2c(gspca_dev, 0xff, 0x43); 381 spca506_WriteI2c(gspca_dev, 0xff, 0x44); 382 spca506_WriteI2c(gspca_dev, 0xff, 0x45); 383 spca506_WriteI2c(gspca_dev, 0xff, 0x46); 384 spca506_WriteI2c(gspca_dev, 0xff, 0x47); 385 spca506_WriteI2c(gspca_dev, 0xff, 0x48); 386 spca506_WriteI2c(gspca_dev, 0xff, 0x49); 387 spca506_WriteI2c(gspca_dev, 0xff, 0x4a); 388 spca506_WriteI2c(gspca_dev, 0xff, 0x4b); 389 spca506_WriteI2c(gspca_dev, 0xff, 0x4c); 390 spca506_WriteI2c(gspca_dev, 0xff, 0x4d); 391 spca506_WriteI2c(gspca_dev, 0xff, 0x4e); 392 spca506_WriteI2c(gspca_dev, 0xff, 0x4f); 393 spca506_WriteI2c(gspca_dev, 0xff, 0x50); 394 spca506_WriteI2c(gspca_dev, 0xff, 0x51); 395 spca506_WriteI2c(gspca_dev, 0xff, 0x52); 396 spca506_WriteI2c(gspca_dev, 0xff, 0x53); 397 spca506_WriteI2c(gspca_dev, 0xff, 0x54); 398 spca506_WriteI2c(gspca_dev, 0xff, 0x55); 399 spca506_WriteI2c(gspca_dev, 0xff, 0x56); 400 spca506_WriteI2c(gspca_dev, 0xff, 0x57); 401 spca506_WriteI2c(gspca_dev, 0x00, 0x58); 402 spca506_WriteI2c(gspca_dev, 0x54, 0x59); 403 spca506_WriteI2c(gspca_dev, 0x07, 0x5a); 404 spca506_WriteI2c(gspca_dev, 0x83, 0x5b); 405 spca506_WriteI2c(gspca_dev, 0x00, 0x5c); 406 spca506_WriteI2c(gspca_dev, 0x00, 0x5d); 407 spca506_WriteI2c(gspca_dev, 0x00, 0x5e); 408 spca506_WriteI2c(gspca_dev, 0x00, 0x5f); 409 spca506_WriteI2c(gspca_dev, 0x00, 0x60); 410 spca506_WriteI2c(gspca_dev, 0x05, 0x61); 411 spca506_WriteI2c(gspca_dev, 0x9f, 0x62); 412 /**************************************/ 413 reg_w(dev, 0x05, 0x00, 0x0003); 414 reg_w(dev, 0x05, 0x00, 0x0004); 415 reg_w(dev, 0x03, 0x10, 0x0001); 416 reg_w(dev, 0x03, 0x78, 0x0000); 417 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { 418 case 0: 419 spca506_Setsize(gspca_dev, 0, 0x10, 0x10); 420 break; 421 case 1: 422 spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a); 423 break; 424 case 2: 425 spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c); 426 break; 427 case 4: 428 spca506_Setsize(gspca_dev, 4, 0x34, 0x34); 429 break; 430 default: 431/* case 5: */ 432 spca506_Setsize(gspca_dev, 5, 0x40, 0x40); 433 break; 434 } 435 436 /* compress setting and size */ 437 /* set i2c luma */ 438 reg_w(dev, 0x02, 0x01, 0x0000); 439 reg_w(dev, 0x03, 0x12, 0x0000); 440 reg_r(gspca_dev, 0x04, 0x0001, 2); 441 gspca_dbg(gspca_dev, D_STREAM, "webcam started\n"); 442 spca506_GetNormeInput(gspca_dev, &norme, &channel); 443 spca506_SetNormeInput(gspca_dev, norme, channel); 444 return 0; 445} 446 447static void sd_stopN(struct gspca_dev *gspca_dev) 448{ 449 struct usb_device *dev = gspca_dev->dev; 450 451 reg_w(dev, 0x02, 0x00, 0x0000); 452 reg_w(dev, 0x03, 0x00, 0x0004); 453 reg_w(dev, 0x03, 0x00, 0x0003); 454} 455 456static void sd_pkt_scan(struct gspca_dev *gspca_dev, 457 u8 *data, /* isoc packet */ 458 int len) /* iso packet length */ 459{ 460 switch (data[0]) { 461 case 0: /* start of frame */ 462 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); 463 data += SPCA50X_OFFSET_DATA; 464 len -= SPCA50X_OFFSET_DATA; 465 gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); 466 break; 467 case 0xff: /* drop */ 468/* gspca_dev->last_packet_type = DISCARD_PACKET; */ 469 break; 470 default: 471 data += 1; 472 len -= 1; 473 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 474 break; 475 } 476} 477 478static void setbrightness(struct gspca_dev *gspca_dev, s32 val) 479{ 480 spca506_Initi2c(gspca_dev); 481 spca506_WriteI2c(gspca_dev, val, SAA7113_bright); 482 spca506_WriteI2c(gspca_dev, 0x01, 0x09); 483} 484 485static void setcontrast(struct gspca_dev *gspca_dev, s32 val) 486{ 487 spca506_Initi2c(gspca_dev); 488 spca506_WriteI2c(gspca_dev, val, SAA7113_contrast); 489 spca506_WriteI2c(gspca_dev, 0x01, 0x09); 490} 491 492static void setcolors(struct gspca_dev *gspca_dev, s32 val) 493{ 494 spca506_Initi2c(gspca_dev); 495 spca506_WriteI2c(gspca_dev, val, SAA7113_saturation); 496 spca506_WriteI2c(gspca_dev, 0x01, 0x09); 497} 498 499static void sethue(struct gspca_dev *gspca_dev, s32 val) 500{ 501 spca506_Initi2c(gspca_dev); 502 spca506_WriteI2c(gspca_dev, val, SAA7113_hue); 503 spca506_WriteI2c(gspca_dev, 0x01, 0x09); 504} 505 506static int sd_s_ctrl(struct v4l2_ctrl *ctrl) 507{ 508 struct gspca_dev *gspca_dev = 509 container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 510 511 gspca_dev->usb_err = 0; 512 513 if (!gspca_dev->streaming) 514 return 0; 515 516 switch (ctrl->id) { 517 case V4L2_CID_BRIGHTNESS: 518 setbrightness(gspca_dev, ctrl->val); 519 break; 520 case V4L2_CID_CONTRAST: 521 setcontrast(gspca_dev, ctrl->val); 522 break; 523 case V4L2_CID_SATURATION: 524 setcolors(gspca_dev, ctrl->val); 525 break; 526 case V4L2_CID_HUE: 527 sethue(gspca_dev, ctrl->val); 528 break; 529 } 530 return gspca_dev->usb_err; 531} 532 533static const struct v4l2_ctrl_ops sd_ctrl_ops = { 534 .s_ctrl = sd_s_ctrl, 535}; 536 537static int sd_init_controls(struct gspca_dev *gspca_dev) 538{ 539 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 540 541 gspca_dev->vdev.ctrl_handler = hdl; 542 v4l2_ctrl_handler_init(hdl, 4); 543 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 544 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); 545 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 546 V4L2_CID_CONTRAST, 0, 255, 1, 0x47); 547 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 548 V4L2_CID_SATURATION, 0, 255, 1, 0x40); 549 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 550 V4L2_CID_HUE, 0, 255, 1, 0); 551 552 if (hdl->error) { 553 pr_err("Could not initialize controls\n"); 554 return hdl->error; 555 } 556 return 0; 557} 558 559/* sub-driver description */ 560static const struct sd_desc sd_desc = { 561 .name = MODULE_NAME, 562 .config = sd_config, 563 .init = sd_init, 564 .init_controls = sd_init_controls, 565 .start = sd_start, 566 .stopN = sd_stopN, 567 .pkt_scan = sd_pkt_scan, 568}; 569 570/* -- module initialisation -- */ 571static const struct usb_device_id device_table[] = { 572 {USB_DEVICE(0x06e1, 0xa190)}, 573/* {USB_DEVICE(0x0733, 0x0430)}, FIXME: may be IntelPCCameraPro BRIDGE_SPCA505 */ 574 {USB_DEVICE(0x0734, 0x043b)}, 575 {USB_DEVICE(0x99fa, 0x8988)}, 576 {} 577}; 578MODULE_DEVICE_TABLE(usb, device_table); 579 580/* -- device connect -- */ 581static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) 582{ 583 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 584 THIS_MODULE); 585} 586 587static struct usb_driver sd_driver = { 588 .name = MODULE_NAME, 589 .id_table = device_table, 590 .probe = sd_probe, 591 .disconnect = gspca_disconnect, 592#ifdef CONFIG_PM 593 .suspend = gspca_suspend, 594 .resume = gspca_resume, 595 .reset_resume = gspca_resume, 596#endif 597}; 598 599module_usb_driver(sd_driver);