stk014.c revision 95c967c167785eb991cf6b22fb854dd8d61d0ff8
1/* 2 * Syntek DV4000 (STK014) subdriver 3 * 4 * Copyright (C) 2008 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 21#define MODULE_NAME "stk014" 22 23#include "gspca.h" 24#include "jpeg.h" 25 26MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); 27MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver"); 28MODULE_LICENSE("GPL"); 29 30/* controls */ 31enum e_ctrl { 32 BRIGHTNESS, 33 CONTRAST, 34 COLORS, 35 LIGHTFREQ, 36 NCTRLS /* number of controls */ 37}; 38 39/* specific webcam descriptor */ 40struct sd { 41 struct gspca_dev gspca_dev; /* !! must be the first item */ 42 43 struct gspca_ctrl ctrls[NCTRLS]; 44 45 u8 quality; 46#define QUALITY_MIN 70 47#define QUALITY_MAX 95 48#define QUALITY_DEF 88 49 50 u8 jpeg_hdr[JPEG_HDR_SZ]; 51}; 52 53/* V4L2 controls supported by the driver */ 54static void setbrightness(struct gspca_dev *gspca_dev); 55static void setcontrast(struct gspca_dev *gspca_dev); 56static void setcolors(struct gspca_dev *gspca_dev); 57static void setlightfreq(struct gspca_dev *gspca_dev); 58 59static const struct ctrl sd_ctrls[NCTRLS] = { 60[BRIGHTNESS] = { 61 { 62 .id = V4L2_CID_BRIGHTNESS, 63 .type = V4L2_CTRL_TYPE_INTEGER, 64 .name = "Brightness", 65 .minimum = 0, 66 .maximum = 255, 67 .step = 1, 68 .default_value = 127, 69 }, 70 .set_control = setbrightness 71 }, 72[CONTRAST] = { 73 { 74 .id = V4L2_CID_CONTRAST, 75 .type = V4L2_CTRL_TYPE_INTEGER, 76 .name = "Contrast", 77 .minimum = 0, 78 .maximum = 255, 79 .step = 1, 80 .default_value = 127, 81 }, 82 .set_control = setcontrast 83 }, 84[COLORS] = { 85 { 86 .id = V4L2_CID_SATURATION, 87 .type = V4L2_CTRL_TYPE_INTEGER, 88 .name = "Color", 89 .minimum = 0, 90 .maximum = 255, 91 .step = 1, 92 .default_value = 127, 93 }, 94 .set_control = setcolors 95 }, 96[LIGHTFREQ] = { 97 { 98 .id = V4L2_CID_POWER_LINE_FREQUENCY, 99 .type = V4L2_CTRL_TYPE_MENU, 100 .name = "Light frequency filter", 101 .minimum = 1, 102 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ 103 .step = 1, 104 .default_value = 1, 105 }, 106 .set_control = setlightfreq 107 }, 108}; 109 110static const struct v4l2_pix_format vga_mode[] = { 111 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 112 .bytesperline = 320, 113 .sizeimage = 320 * 240 * 3 / 8 + 590, 114 .colorspace = V4L2_COLORSPACE_JPEG, 115 .priv = 1}, 116 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 117 .bytesperline = 640, 118 .sizeimage = 640 * 480 * 3 / 8 + 590, 119 .colorspace = V4L2_COLORSPACE_JPEG, 120 .priv = 0}, 121}; 122 123/* -- read a register -- */ 124static u8 reg_r(struct gspca_dev *gspca_dev, 125 __u16 index) 126{ 127 struct usb_device *dev = gspca_dev->dev; 128 int ret; 129 130 if (gspca_dev->usb_err < 0) 131 return 0; 132 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 133 0x00, 134 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 135 0x00, 136 index, 137 gspca_dev->usb_buf, 1, 138 500); 139 if (ret < 0) { 140 err("reg_r err %d", ret); 141 gspca_dev->usb_err = ret; 142 return 0; 143 } 144 return gspca_dev->usb_buf[0]; 145} 146 147/* -- write a register -- */ 148static void reg_w(struct gspca_dev *gspca_dev, 149 __u16 index, __u16 value) 150{ 151 struct usb_device *dev = gspca_dev->dev; 152 int ret; 153 154 if (gspca_dev->usb_err < 0) 155 return; 156 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 157 0x01, 158 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 159 value, 160 index, 161 NULL, 162 0, 163 500); 164 if (ret < 0) { 165 err("reg_w err %d", ret); 166 gspca_dev->usb_err = ret; 167 } 168} 169 170/* -- get a bulk value (4 bytes) -- */ 171static void rcv_val(struct gspca_dev *gspca_dev, 172 int ads) 173{ 174 struct usb_device *dev = gspca_dev->dev; 175 int alen, ret; 176 177 reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff); 178 reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff); 179 reg_w(gspca_dev, 0x636, ads & 0xff); 180 reg_w(gspca_dev, 0x637, 0); 181 reg_w(gspca_dev, 0x638, 4); /* len & 0xff */ 182 reg_w(gspca_dev, 0x639, 0); /* len >> 8 */ 183 reg_w(gspca_dev, 0x63a, 0); 184 reg_w(gspca_dev, 0x63b, 0); 185 reg_w(gspca_dev, 0x630, 5); 186 if (gspca_dev->usb_err < 0) 187 return; 188 ret = usb_bulk_msg(dev, 189 usb_rcvbulkpipe(dev, 0x05), 190 gspca_dev->usb_buf, 191 4, /* length */ 192 &alen, 193 500); /* timeout in milliseconds */ 194 if (ret < 0) { 195 err("rcv_val err %d", ret); 196 gspca_dev->usb_err = ret; 197 } 198} 199 200/* -- send a bulk value -- */ 201static void snd_val(struct gspca_dev *gspca_dev, 202 int ads, 203 unsigned int val) 204{ 205 struct usb_device *dev = gspca_dev->dev; 206 int alen, ret; 207 __u8 seq = 0; 208 209 if (ads == 0x003f08) { 210 reg_r(gspca_dev, 0x0704); 211 seq = reg_r(gspca_dev, 0x0705); 212 reg_r(gspca_dev, 0x0650); 213 reg_w(gspca_dev, 0x654, seq); 214 } else { 215 reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff); 216 } 217 reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff); 218 reg_w(gspca_dev, 0x656, ads & 0xff); 219 reg_w(gspca_dev, 0x657, 0); 220 reg_w(gspca_dev, 0x658, 0x04); /* size */ 221 reg_w(gspca_dev, 0x659, 0); 222 reg_w(gspca_dev, 0x65a, 0); 223 reg_w(gspca_dev, 0x65b, 0); 224 reg_w(gspca_dev, 0x650, 5); 225 if (gspca_dev->usb_err < 0) 226 return; 227 gspca_dev->usb_buf[0] = val >> 24; 228 gspca_dev->usb_buf[1] = val >> 16; 229 gspca_dev->usb_buf[2] = val >> 8; 230 gspca_dev->usb_buf[3] = val; 231 ret = usb_bulk_msg(dev, 232 usb_sndbulkpipe(dev, 6), 233 gspca_dev->usb_buf, 234 4, 235 &alen, 236 500); /* timeout in milliseconds */ 237 if (ret < 0) { 238 err("snd_val err %d", ret); 239 gspca_dev->usb_err = ret; 240 } else { 241 if (ads == 0x003f08) { 242 seq += 4; 243 seq &= 0x3f; 244 reg_w(gspca_dev, 0x705, seq); 245 } 246 } 247} 248 249/* set a camera parameter */ 250static void set_par(struct gspca_dev *gspca_dev, 251 int parval) 252{ 253 snd_val(gspca_dev, 0x003f08, parval); 254} 255 256static void setbrightness(struct gspca_dev *gspca_dev) 257{ 258 struct sd *sd = (struct sd *) gspca_dev; 259 int parval; 260 261 parval = 0x06000000 /* whiteness */ 262 + (sd->ctrls[BRIGHTNESS].val << 16); 263 set_par(gspca_dev, parval); 264} 265 266static void setcontrast(struct gspca_dev *gspca_dev) 267{ 268 struct sd *sd = (struct sd *) gspca_dev; 269 int parval; 270 271 parval = 0x07000000 /* contrast */ 272 + (sd->ctrls[CONTRAST].val << 16); 273 set_par(gspca_dev, parval); 274} 275 276static void setcolors(struct gspca_dev *gspca_dev) 277{ 278 struct sd *sd = (struct sd *) gspca_dev; 279 int parval; 280 281 parval = 0x08000000 /* saturation */ 282 + (sd->ctrls[COLORS].val << 16); 283 set_par(gspca_dev, parval); 284} 285 286static void setlightfreq(struct gspca_dev *gspca_dev) 287{ 288 struct sd *sd = (struct sd *) gspca_dev; 289 290 set_par(gspca_dev, sd->ctrls[LIGHTFREQ].val == 1 291 ? 0x33640000 /* 50 Hz */ 292 : 0x33780000); /* 60 Hz */ 293} 294 295/* this function is called at probe time */ 296static int sd_config(struct gspca_dev *gspca_dev, 297 const struct usb_device_id *id) 298{ 299 struct sd *sd = (struct sd *) gspca_dev; 300 301 gspca_dev->cam.cam_mode = vga_mode; 302 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); 303 gspca_dev->cam.ctrls = sd->ctrls; 304 sd->quality = QUALITY_DEF; 305 return 0; 306} 307 308/* this function is called at probe and resume time */ 309static int sd_init(struct gspca_dev *gspca_dev) 310{ 311 u8 ret; 312 313 /* check if the device responds */ 314 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); 315 ret = reg_r(gspca_dev, 0x0740); 316 if (gspca_dev->usb_err >= 0) { 317 if (ret != 0xff) { 318 err("init reg: 0x%02x", ret); 319 gspca_dev->usb_err = -EIO; 320 } 321 } 322 return gspca_dev->usb_err; 323} 324 325/* -- start the camera -- */ 326static int sd_start(struct gspca_dev *gspca_dev) 327{ 328 struct sd *sd = (struct sd *) gspca_dev; 329 int ret, value; 330 331 /* create the JPEG header */ 332 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 333 0x22); /* JPEG 411 */ 334 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 335 336 /* work on alternate 1 */ 337 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); 338 339 set_par(gspca_dev, 0x10000000); 340 set_par(gspca_dev, 0x00000000); 341 set_par(gspca_dev, 0x8002e001); 342 set_par(gspca_dev, 0x14000000); 343 if (gspca_dev->width > 320) 344 value = 0x8002e001; /* 640x480 */ 345 else 346 value = 0x4001f000; /* 320x240 */ 347 set_par(gspca_dev, value); 348 ret = usb_set_interface(gspca_dev->dev, 349 gspca_dev->iface, 350 gspca_dev->alt); 351 if (ret < 0) { 352 err("set intf %d %d failed", 353 gspca_dev->iface, gspca_dev->alt); 354 gspca_dev->usb_err = ret; 355 goto out; 356 } 357 reg_r(gspca_dev, 0x0630); 358 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */ 359 reg_r(gspca_dev, 0x0650); 360 snd_val(gspca_dev, 0x000020, 0xffffffff); 361 reg_w(gspca_dev, 0x0620, 0); 362 reg_w(gspca_dev, 0x0630, 0); 363 reg_w(gspca_dev, 0x0640, 0); 364 reg_w(gspca_dev, 0x0650, 0); 365 reg_w(gspca_dev, 0x0660, 0); 366 setbrightness(gspca_dev); /* whiteness */ 367 setcontrast(gspca_dev); /* contrast */ 368 setcolors(gspca_dev); /* saturation */ 369 set_par(gspca_dev, 0x09800000); /* Red ? */ 370 set_par(gspca_dev, 0x0a800000); /* Green ? */ 371 set_par(gspca_dev, 0x0b800000); /* Blue ? */ 372 set_par(gspca_dev, 0x0d030000); /* Gamma ? */ 373 setlightfreq(gspca_dev); 374 375 /* start the video flow */ 376 set_par(gspca_dev, 0x01000000); 377 set_par(gspca_dev, 0x01000000); 378 if (gspca_dev->usb_err >= 0) 379 PDEBUG(D_STREAM, "camera started alt: 0x%02x", 380 gspca_dev->alt); 381out: 382 return gspca_dev->usb_err; 383} 384 385static void sd_stopN(struct gspca_dev *gspca_dev) 386{ 387 struct usb_device *dev = gspca_dev->dev; 388 389 set_par(gspca_dev, 0x02000000); 390 set_par(gspca_dev, 0x02000000); 391 usb_set_interface(dev, gspca_dev->iface, 1); 392 reg_r(gspca_dev, 0x0630); 393 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */ 394 reg_r(gspca_dev, 0x0650); 395 snd_val(gspca_dev, 0x000020, 0xffffffff); 396 reg_w(gspca_dev, 0x0620, 0); 397 reg_w(gspca_dev, 0x0630, 0); 398 reg_w(gspca_dev, 0x0640, 0); 399 reg_w(gspca_dev, 0x0650, 0); 400 reg_w(gspca_dev, 0x0660, 0); 401 PDEBUG(D_STREAM, "camera stopped"); 402} 403 404static void sd_pkt_scan(struct gspca_dev *gspca_dev, 405 u8 *data, /* isoc packet */ 406 int len) /* iso packet length */ 407{ 408 struct sd *sd = (struct sd *) gspca_dev; 409 static unsigned char ffd9[] = {0xff, 0xd9}; 410 411 /* a frame starts with: 412 * - 0xff 0xfe 413 * - 0x08 0x00 - length (little endian ?!) 414 * - 4 bytes = size of whole frame (BE - including header) 415 * - 0x00 0x0c 416 * - 0xff 0xd8 417 * - .. JPEG image with escape sequences (ff 00) 418 * (without ending - ff d9) 419 */ 420 if (data[0] == 0xff && data[1] == 0xfe) { 421 gspca_frame_add(gspca_dev, LAST_PACKET, 422 ffd9, 2); 423 424 /* put the JPEG 411 header */ 425 gspca_frame_add(gspca_dev, FIRST_PACKET, 426 sd->jpeg_hdr, JPEG_HDR_SZ); 427 428 /* beginning of the frame */ 429#define STKHDRSZ 12 430 data += STKHDRSZ; 431 len -= STKHDRSZ; 432 } 433 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 434} 435 436static int sd_querymenu(struct gspca_dev *gspca_dev, 437 struct v4l2_querymenu *menu) 438{ 439 switch (menu->id) { 440 case V4L2_CID_POWER_LINE_FREQUENCY: 441 switch (menu->index) { 442 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ 443 strcpy((char *) menu->name, "50 Hz"); 444 return 0; 445 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ 446 strcpy((char *) menu->name, "60 Hz"); 447 return 0; 448 } 449 break; 450 } 451 return -EINVAL; 452} 453 454static int sd_set_jcomp(struct gspca_dev *gspca_dev, 455 struct v4l2_jpegcompression *jcomp) 456{ 457 struct sd *sd = (struct sd *) gspca_dev; 458 459 if (jcomp->quality < QUALITY_MIN) 460 sd->quality = QUALITY_MIN; 461 else if (jcomp->quality > QUALITY_MAX) 462 sd->quality = QUALITY_MAX; 463 else 464 sd->quality = jcomp->quality; 465 if (gspca_dev->streaming) 466 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 467 return gspca_dev->usb_err; 468} 469 470static int sd_get_jcomp(struct gspca_dev *gspca_dev, 471 struct v4l2_jpegcompression *jcomp) 472{ 473 struct sd *sd = (struct sd *) gspca_dev; 474 475 memset(jcomp, 0, sizeof *jcomp); 476 jcomp->quality = sd->quality; 477 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT 478 | V4L2_JPEG_MARKER_DQT; 479 return 0; 480} 481 482/* sub-driver description */ 483static const struct sd_desc sd_desc = { 484 .name = MODULE_NAME, 485 .ctrls = sd_ctrls, 486 .nctrls = NCTRLS, 487 .config = sd_config, 488 .init = sd_init, 489 .start = sd_start, 490 .stopN = sd_stopN, 491 .pkt_scan = sd_pkt_scan, 492 .querymenu = sd_querymenu, 493 .get_jcomp = sd_get_jcomp, 494 .set_jcomp = sd_set_jcomp, 495}; 496 497/* -- module initialisation -- */ 498static const struct usb_device_id device_table[] = { 499 {USB_DEVICE(0x05e1, 0x0893)}, 500 {} 501}; 502MODULE_DEVICE_TABLE(usb, device_table); 503 504/* -- device connect -- */ 505static int sd_probe(struct usb_interface *intf, 506 const struct usb_device_id *id) 507{ 508 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 509 THIS_MODULE); 510} 511 512static struct usb_driver sd_driver = { 513 .name = MODULE_NAME, 514 .id_table = device_table, 515 .probe = sd_probe, 516 .disconnect = gspca_disconnect, 517#ifdef CONFIG_PM 518 .suspend = gspca_suspend, 519 .resume = gspca_resume, 520#endif 521}; 522 523/* -- module insert / remove -- */ 524static int __init sd_mod_init(void) 525{ 526 return usb_register(&sd_driver); 527} 528static void __exit sd_mod_exit(void) 529{ 530 usb_deregister(&sd_driver); 531} 532 533module_init(sd_mod_init); 534module_exit(sd_mod_exit); 535