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