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