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