1fd9871f7SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 25bdd00b9STheodore Kilgore /* 35bdd00b9STheodore Kilgore * SN9C2028 library 45bdd00b9STheodore Kilgore * 55bdd00b9STheodore Kilgore * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> 65bdd00b9STheodore Kilgore */ 75bdd00b9STheodore Kilgore 8133a9fe9SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9133a9fe9SJoe Perches 105bdd00b9STheodore Kilgore #define MODULE_NAME "sn9c2028" 115bdd00b9STheodore Kilgore 125bdd00b9STheodore Kilgore #include "gspca.h" 135bdd00b9STheodore Kilgore 145bdd00b9STheodore Kilgore MODULE_AUTHOR("Theodore Kilgore"); 155bdd00b9STheodore Kilgore MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver"); 165bdd00b9STheodore Kilgore MODULE_LICENSE("GPL"); 175bdd00b9STheodore Kilgore 185bdd00b9STheodore Kilgore /* specific webcam descriptor */ 195bdd00b9STheodore Kilgore struct sd { 205bdd00b9STheodore Kilgore struct gspca_dev gspca_dev; /* !! must be the first item */ 215bdd00b9STheodore Kilgore u8 sof_read; 225bdd00b9STheodore Kilgore u16 model; 23d8fd9f56SVasily Khoruzhick 24d8fd9f56SVasily Khoruzhick #define MIN_AVG_LUM 8500 25d8fd9f56SVasily Khoruzhick #define MAX_AVG_LUM 10000 26d8fd9f56SVasily Khoruzhick int avg_lum; 27d8fd9f56SVasily Khoruzhick u8 avg_lum_l; 28d8fd9f56SVasily Khoruzhick 29d8fd9f56SVasily Khoruzhick struct { /* autogain and gain control cluster */ 30d8fd9f56SVasily Khoruzhick struct v4l2_ctrl *autogain; 31d8fd9f56SVasily Khoruzhick struct v4l2_ctrl *gain; 32d8fd9f56SVasily Khoruzhick }; 335bdd00b9STheodore Kilgore }; 345bdd00b9STheodore Kilgore 355bdd00b9STheodore Kilgore struct init_command { 365bdd00b9STheodore Kilgore unsigned char instruction[6]; 375bdd00b9STheodore Kilgore unsigned char to_read; /* length to read. 0 means no reply requested */ 385bdd00b9STheodore Kilgore }; 395bdd00b9STheodore Kilgore 405bdd00b9STheodore Kilgore /* How to change the resolution of any of the VGA cams is unknown */ 415bdd00b9STheodore Kilgore static const struct v4l2_pix_format vga_mode[] = { 425bdd00b9STheodore Kilgore {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, 435bdd00b9STheodore Kilgore .bytesperline = 640, 445bdd00b9STheodore Kilgore .sizeimage = 640 * 480 * 3 / 4, 455bdd00b9STheodore Kilgore .colorspace = V4L2_COLORSPACE_SRGB, 465bdd00b9STheodore Kilgore .priv = 0}, 475bdd00b9STheodore Kilgore }; 485bdd00b9STheodore Kilgore 495bdd00b9STheodore Kilgore /* No way to change the resolution of the CIF cams is known */ 505bdd00b9STheodore Kilgore static const struct v4l2_pix_format cif_mode[] = { 515bdd00b9STheodore Kilgore {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, 525bdd00b9STheodore Kilgore .bytesperline = 352, 535bdd00b9STheodore Kilgore .sizeimage = 352 * 288 * 3 / 4, 545bdd00b9STheodore Kilgore .colorspace = V4L2_COLORSPACE_SRGB, 555bdd00b9STheodore Kilgore .priv = 0}, 565bdd00b9STheodore Kilgore }; 575bdd00b9STheodore Kilgore 585bdd00b9STheodore Kilgore /* the bytes to write are in gspca_dev->usb_buf */ 595bdd00b9STheodore Kilgore static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command) 605bdd00b9STheodore Kilgore { 615bdd00b9STheodore Kilgore int rc; 625bdd00b9STheodore Kilgore 6337d5efb0SJoe Perches gspca_dbg(gspca_dev, D_USBO, "sending command %02x%02x%02x%02x%02x%02x\n", 6437d5efb0SJoe Perches command[0], command[1], command[2], 6537d5efb0SJoe Perches command[3], command[4], command[5]); 665bdd00b9STheodore Kilgore 675bdd00b9STheodore Kilgore memcpy(gspca_dev->usb_buf, command, 6); 685bdd00b9STheodore Kilgore rc = usb_control_msg(gspca_dev->dev, 695bdd00b9STheodore Kilgore usb_sndctrlpipe(gspca_dev->dev, 0), 705bdd00b9STheodore Kilgore USB_REQ_GET_CONFIGURATION, 715bdd00b9STheodore Kilgore USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 725bdd00b9STheodore Kilgore 2, 0, gspca_dev->usb_buf, 6, 500); 735bdd00b9STheodore Kilgore if (rc < 0) { 74133a9fe9SJoe Perches pr_err("command write [%02x] error %d\n", 755bdd00b9STheodore Kilgore gspca_dev->usb_buf[0], rc); 765bdd00b9STheodore Kilgore return rc; 775bdd00b9STheodore Kilgore } 785bdd00b9STheodore Kilgore 795bdd00b9STheodore Kilgore return 0; 805bdd00b9STheodore Kilgore } 815bdd00b9STheodore Kilgore 825bdd00b9STheodore Kilgore static int sn9c2028_read1(struct gspca_dev *gspca_dev) 835bdd00b9STheodore Kilgore { 845bdd00b9STheodore Kilgore int rc; 855bdd00b9STheodore Kilgore 865bdd00b9STheodore Kilgore rc = usb_control_msg(gspca_dev->dev, 875bdd00b9STheodore Kilgore usb_rcvctrlpipe(gspca_dev->dev, 0), 885bdd00b9STheodore Kilgore USB_REQ_GET_STATUS, 895bdd00b9STheodore Kilgore USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 905bdd00b9STheodore Kilgore 1, 0, gspca_dev->usb_buf, 1, 500); 915bdd00b9STheodore Kilgore if (rc != 1) { 92133a9fe9SJoe Perches pr_err("read1 error %d\n", rc); 935bdd00b9STheodore Kilgore return (rc < 0) ? rc : -EIO; 945bdd00b9STheodore Kilgore } 9537d5efb0SJoe Perches gspca_dbg(gspca_dev, D_USBI, "read1 response %02x\n", 9637d5efb0SJoe Perches gspca_dev->usb_buf[0]); 975bdd00b9STheodore Kilgore return gspca_dev->usb_buf[0]; 985bdd00b9STheodore Kilgore } 995bdd00b9STheodore Kilgore 1005bdd00b9STheodore Kilgore static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading) 1015bdd00b9STheodore Kilgore { 1025bdd00b9STheodore Kilgore int rc; 1035bdd00b9STheodore Kilgore rc = usb_control_msg(gspca_dev->dev, 1045bdd00b9STheodore Kilgore usb_rcvctrlpipe(gspca_dev->dev, 0), 1055bdd00b9STheodore Kilgore USB_REQ_GET_STATUS, 1065bdd00b9STheodore Kilgore USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 1075bdd00b9STheodore Kilgore 4, 0, gspca_dev->usb_buf, 4, 500); 1085bdd00b9STheodore Kilgore if (rc != 4) { 109133a9fe9SJoe Perches pr_err("read4 error %d\n", rc); 1105bdd00b9STheodore Kilgore return (rc < 0) ? rc : -EIO; 1115bdd00b9STheodore Kilgore } 1125bdd00b9STheodore Kilgore memcpy(reading, gspca_dev->usb_buf, 4); 11337d5efb0SJoe Perches gspca_dbg(gspca_dev, D_USBI, "read4 response %02x%02x%02x%02x\n", 11437d5efb0SJoe Perches reading[0], reading[1], reading[2], reading[3]); 1155bdd00b9STheodore Kilgore return rc; 1165bdd00b9STheodore Kilgore } 1175bdd00b9STheodore Kilgore 1185bdd00b9STheodore Kilgore static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command) 1195bdd00b9STheodore Kilgore { 1205bdd00b9STheodore Kilgore int i, status; 1215bdd00b9STheodore Kilgore __u8 reading[4]; 1225bdd00b9STheodore Kilgore 1235bdd00b9STheodore Kilgore status = sn9c2028_command(gspca_dev, command); 1245bdd00b9STheodore Kilgore if (status < 0) 1255bdd00b9STheodore Kilgore return status; 1265bdd00b9STheodore Kilgore 1275bdd00b9STheodore Kilgore status = -1; 1285bdd00b9STheodore Kilgore for (i = 0; i < 256 && status < 2; i++) 1295bdd00b9STheodore Kilgore status = sn9c2028_read1(gspca_dev); 13048c291edSVasily Khoruzhick if (status < 0) { 131133a9fe9SJoe Perches pr_err("long command status read error %d\n", status); 1320a2a89c4SDan Carpenter return status; 1335bdd00b9STheodore Kilgore } 1345bdd00b9STheodore Kilgore 1355bdd00b9STheodore Kilgore memset(reading, 0, 4); 1365bdd00b9STheodore Kilgore status = sn9c2028_read4(gspca_dev, reading); 1375bdd00b9STheodore Kilgore if (status < 0) 1385bdd00b9STheodore Kilgore return status; 1395bdd00b9STheodore Kilgore 1405bdd00b9STheodore Kilgore /* in general, the first byte of the response is the first byte of 1415bdd00b9STheodore Kilgore * the command, or'ed with 8 */ 1425bdd00b9STheodore Kilgore status = sn9c2028_read1(gspca_dev); 1435bdd00b9STheodore Kilgore if (status < 0) 1445bdd00b9STheodore Kilgore return status; 1455bdd00b9STheodore Kilgore 1465bdd00b9STheodore Kilgore return 0; 1475bdd00b9STheodore Kilgore } 1485bdd00b9STheodore Kilgore 1495bdd00b9STheodore Kilgore static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command) 1505bdd00b9STheodore Kilgore { 1515bdd00b9STheodore Kilgore int err_code; 1525bdd00b9STheodore Kilgore 1535bdd00b9STheodore Kilgore err_code = sn9c2028_command(gspca_dev, command); 1545bdd00b9STheodore Kilgore if (err_code < 0) 1555bdd00b9STheodore Kilgore return err_code; 1565bdd00b9STheodore Kilgore 1575bdd00b9STheodore Kilgore err_code = sn9c2028_read1(gspca_dev); 1585bdd00b9STheodore Kilgore if (err_code < 0) 1595bdd00b9STheodore Kilgore return err_code; 1605bdd00b9STheodore Kilgore 1615bdd00b9STheodore Kilgore return 0; 1625bdd00b9STheodore Kilgore } 1635bdd00b9STheodore Kilgore 1645bdd00b9STheodore Kilgore /* this function is called at probe time */ 1655bdd00b9STheodore Kilgore static int sd_config(struct gspca_dev *gspca_dev, 1665bdd00b9STheodore Kilgore const struct usb_device_id *id) 1675bdd00b9STheodore Kilgore { 1685bdd00b9STheodore Kilgore struct sd *sd = (struct sd *) gspca_dev; 1695bdd00b9STheodore Kilgore struct cam *cam = &gspca_dev->cam; 1705bdd00b9STheodore Kilgore 17137d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)\n", 1725bdd00b9STheodore Kilgore id->idVendor, id->idProduct); 1735bdd00b9STheodore Kilgore 1745bdd00b9STheodore Kilgore sd->model = id->idProduct; 1755bdd00b9STheodore Kilgore 1765bdd00b9STheodore Kilgore switch (sd->model) { 1775bdd00b9STheodore Kilgore case 0x7005: 17837d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "Genius Smart 300 camera\n"); 1795bdd00b9STheodore Kilgore break; 18048c291edSVasily Khoruzhick case 0x7003: 18137d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "Genius Videocam Live v2\n"); 18248c291edSVasily Khoruzhick break; 1835bdd00b9STheodore Kilgore case 0x8000: 18437d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "DC31VC\n"); 1855bdd00b9STheodore Kilgore break; 1865bdd00b9STheodore Kilgore case 0x8001: 18737d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "Spy camera\n"); 1885bdd00b9STheodore Kilgore break; 1895bdd00b9STheodore Kilgore case 0x8003: 19037d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "CIF camera\n"); 1915bdd00b9STheodore Kilgore break; 1925bdd00b9STheodore Kilgore case 0x8008: 19337d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "Mini-Shotz ms-350 camera\n"); 1945bdd00b9STheodore Kilgore break; 1955bdd00b9STheodore Kilgore case 0x800a: 19637d5efb0SJoe Perches gspca_dbg(gspca_dev, D_PROBE, "Vivitar 3350b type camera\n"); 1975bdd00b9STheodore Kilgore cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP; 1985bdd00b9STheodore Kilgore break; 1995bdd00b9STheodore Kilgore } 2005bdd00b9STheodore Kilgore 2015bdd00b9STheodore Kilgore switch (sd->model) { 2025bdd00b9STheodore Kilgore case 0x8000: 2035bdd00b9STheodore Kilgore case 0x8001: 2045bdd00b9STheodore Kilgore case 0x8003: 2055bdd00b9STheodore Kilgore cam->cam_mode = cif_mode; 2065bdd00b9STheodore Kilgore cam->nmodes = ARRAY_SIZE(cif_mode); 2075bdd00b9STheodore Kilgore break; 2085bdd00b9STheodore Kilgore default: 2095bdd00b9STheodore Kilgore cam->cam_mode = vga_mode; 2105bdd00b9STheodore Kilgore cam->nmodes = ARRAY_SIZE(vga_mode); 2115bdd00b9STheodore Kilgore } 2125bdd00b9STheodore Kilgore return 0; 2135bdd00b9STheodore Kilgore } 2145bdd00b9STheodore Kilgore 2155bdd00b9STheodore Kilgore /* this function is called at probe and resume time */ 2165bdd00b9STheodore Kilgore static int sd_init(struct gspca_dev *gspca_dev) 2175bdd00b9STheodore Kilgore { 218*77d7ceb1SColin Ian King int status; 2195bdd00b9STheodore Kilgore 2205bdd00b9STheodore Kilgore sn9c2028_read1(gspca_dev); 2215bdd00b9STheodore Kilgore sn9c2028_read1(gspca_dev); 2225bdd00b9STheodore Kilgore status = sn9c2028_read1(gspca_dev); 2235bdd00b9STheodore Kilgore 2245bdd00b9STheodore Kilgore return (status < 0) ? status : 0; 2255bdd00b9STheodore Kilgore } 2265bdd00b9STheodore Kilgore 2275bdd00b9STheodore Kilgore static int run_start_commands(struct gspca_dev *gspca_dev, 2285bdd00b9STheodore Kilgore struct init_command *cam_commands, int n) 2295bdd00b9STheodore Kilgore { 2305bdd00b9STheodore Kilgore int i, err_code = -1; 2315bdd00b9STheodore Kilgore 2325bdd00b9STheodore Kilgore for (i = 0; i < n; i++) { 2335bdd00b9STheodore Kilgore switch (cam_commands[i].to_read) { 2345bdd00b9STheodore Kilgore case 4: 2355bdd00b9STheodore Kilgore err_code = sn9c2028_long_command(gspca_dev, 2365bdd00b9STheodore Kilgore cam_commands[i].instruction); 2375bdd00b9STheodore Kilgore break; 2385bdd00b9STheodore Kilgore case 1: 2395bdd00b9STheodore Kilgore err_code = sn9c2028_short_command(gspca_dev, 2405bdd00b9STheodore Kilgore cam_commands[i].instruction); 2415bdd00b9STheodore Kilgore break; 2425bdd00b9STheodore Kilgore case 0: 2435bdd00b9STheodore Kilgore err_code = sn9c2028_command(gspca_dev, 2445bdd00b9STheodore Kilgore cam_commands[i].instruction); 2455bdd00b9STheodore Kilgore break; 2465bdd00b9STheodore Kilgore } 2475bdd00b9STheodore Kilgore if (err_code < 0) 2485bdd00b9STheodore Kilgore return err_code; 2495bdd00b9STheodore Kilgore } 2505bdd00b9STheodore Kilgore return 0; 2515bdd00b9STheodore Kilgore } 2525bdd00b9STheodore Kilgore 253d8fd9f56SVasily Khoruzhick static void set_gain(struct gspca_dev *gspca_dev, s32 g) 254d8fd9f56SVasily Khoruzhick { 255d8fd9f56SVasily Khoruzhick struct sd *sd = (struct sd *) gspca_dev; 256d8fd9f56SVasily Khoruzhick 257d8fd9f56SVasily Khoruzhick struct init_command genius_vcam_live_gain_cmds[] = { 258d8fd9f56SVasily Khoruzhick {{0x1d, 0x25, 0x10 /* This byte is gain */, 259d8fd9f56SVasily Khoruzhick 0x20, 0xab, 0x00}, 0}, 260d8fd9f56SVasily Khoruzhick }; 261d8fd9f56SVasily Khoruzhick if (!gspca_dev->streaming) 262d8fd9f56SVasily Khoruzhick return; 263d8fd9f56SVasily Khoruzhick 264d8fd9f56SVasily Khoruzhick switch (sd->model) { 265d8fd9f56SVasily Khoruzhick case 0x7003: 266d8fd9f56SVasily Khoruzhick genius_vcam_live_gain_cmds[0].instruction[2] = g; 267d8fd9f56SVasily Khoruzhick run_start_commands(gspca_dev, genius_vcam_live_gain_cmds, 268d8fd9f56SVasily Khoruzhick ARRAY_SIZE(genius_vcam_live_gain_cmds)); 269d8fd9f56SVasily Khoruzhick break; 270d8fd9f56SVasily Khoruzhick default: 271d8fd9f56SVasily Khoruzhick break; 272d8fd9f56SVasily Khoruzhick } 273d8fd9f56SVasily Khoruzhick } 274d8fd9f56SVasily Khoruzhick 275d8fd9f56SVasily Khoruzhick static int sd_s_ctrl(struct v4l2_ctrl *ctrl) 276d8fd9f56SVasily Khoruzhick { 277d8fd9f56SVasily Khoruzhick struct gspca_dev *gspca_dev = 278d8fd9f56SVasily Khoruzhick container_of(ctrl->handler, struct gspca_dev, ctrl_handler); 279d8fd9f56SVasily Khoruzhick struct sd *sd = (struct sd *)gspca_dev; 280d8fd9f56SVasily Khoruzhick 281d8fd9f56SVasily Khoruzhick gspca_dev->usb_err = 0; 282d8fd9f56SVasily Khoruzhick 283d8fd9f56SVasily Khoruzhick if (!gspca_dev->streaming) 284d8fd9f56SVasily Khoruzhick return 0; 285d8fd9f56SVasily Khoruzhick 286d8fd9f56SVasily Khoruzhick switch (ctrl->id) { 287d8fd9f56SVasily Khoruzhick /* standalone gain control */ 288d8fd9f56SVasily Khoruzhick case V4L2_CID_GAIN: 289d8fd9f56SVasily Khoruzhick set_gain(gspca_dev, ctrl->val); 290d8fd9f56SVasily Khoruzhick break; 291d8fd9f56SVasily Khoruzhick /* autogain */ 292d8fd9f56SVasily Khoruzhick case V4L2_CID_AUTOGAIN: 293d8fd9f56SVasily Khoruzhick set_gain(gspca_dev, sd->gain->val); 294d8fd9f56SVasily Khoruzhick break; 295d8fd9f56SVasily Khoruzhick } 296d8fd9f56SVasily Khoruzhick return gspca_dev->usb_err; 297d8fd9f56SVasily Khoruzhick } 298d8fd9f56SVasily Khoruzhick 299d8fd9f56SVasily Khoruzhick static const struct v4l2_ctrl_ops sd_ctrl_ops = { 300d8fd9f56SVasily Khoruzhick .s_ctrl = sd_s_ctrl, 301d8fd9f56SVasily Khoruzhick }; 302d8fd9f56SVasily Khoruzhick 303d8fd9f56SVasily Khoruzhick 304d8fd9f56SVasily Khoruzhick static int sd_init_controls(struct gspca_dev *gspca_dev) 305d8fd9f56SVasily Khoruzhick { 306d8fd9f56SVasily Khoruzhick struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; 307d8fd9f56SVasily Khoruzhick struct sd *sd = (struct sd *)gspca_dev; 308d8fd9f56SVasily Khoruzhick 309d8fd9f56SVasily Khoruzhick gspca_dev->vdev.ctrl_handler = hdl; 310d8fd9f56SVasily Khoruzhick v4l2_ctrl_handler_init(hdl, 2); 311d8fd9f56SVasily Khoruzhick 312d8fd9f56SVasily Khoruzhick switch (sd->model) { 313d8fd9f56SVasily Khoruzhick case 0x7003: 314d8fd9f56SVasily Khoruzhick sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 315d8fd9f56SVasily Khoruzhick V4L2_CID_GAIN, 0, 20, 1, 0); 316d8fd9f56SVasily Khoruzhick sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, 317d8fd9f56SVasily Khoruzhick V4L2_CID_AUTOGAIN, 0, 1, 1, 1); 318d8fd9f56SVasily Khoruzhick break; 319d8fd9f56SVasily Khoruzhick default: 320d8fd9f56SVasily Khoruzhick break; 321d8fd9f56SVasily Khoruzhick } 322d8fd9f56SVasily Khoruzhick 323d8fd9f56SVasily Khoruzhick return 0; 324d8fd9f56SVasily Khoruzhick } 3255bdd00b9STheodore Kilgore static int start_spy_cam(struct gspca_dev *gspca_dev) 3265bdd00b9STheodore Kilgore { 3275bdd00b9STheodore Kilgore struct init_command spy_start_commands[] = { 3285bdd00b9STheodore Kilgore {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 3295bdd00b9STheodore Kilgore {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 3305bdd00b9STheodore Kilgore {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 3315bdd00b9STheodore Kilgore {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, 3325bdd00b9STheodore Kilgore {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, 3335bdd00b9STheodore Kilgore {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 3345bdd00b9STheodore Kilgore {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width 352 */ 3355bdd00b9STheodore Kilgore {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */ 3365bdd00b9STheodore Kilgore /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */ 3375bdd00b9STheodore Kilgore {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, 3385bdd00b9STheodore Kilgore {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/ 3395bdd00b9STheodore Kilgore /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */ 3405bdd00b9STheodore Kilgore {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, 3415bdd00b9STheodore Kilgore /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */ 3425bdd00b9STheodore Kilgore {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 3435bdd00b9STheodore Kilgore {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 3445bdd00b9STheodore Kilgore /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */ 3455bdd00b9STheodore Kilgore {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 3465bdd00b9STheodore Kilgore {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 3475bdd00b9STheodore Kilgore /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */ 3485bdd00b9STheodore Kilgore {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 3495bdd00b9STheodore Kilgore {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 3505bdd00b9STheodore Kilgore {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 3515bdd00b9STheodore Kilgore {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 3525bdd00b9STheodore Kilgore {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 3535bdd00b9STheodore Kilgore {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4}, 3545bdd00b9STheodore Kilgore {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/ 3555bdd00b9STheodore Kilgore /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ 3565bdd00b9STheodore Kilgore {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ 3575bdd00b9STheodore Kilgore /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */ 3585bdd00b9STheodore Kilgore {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ 3595bdd00b9STheodore Kilgore {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */ 3605bdd00b9STheodore Kilgore {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4}, 3615bdd00b9STheodore Kilgore /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ 3625bdd00b9STheodore Kilgore {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4}, 3635bdd00b9STheodore Kilgore {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4}, 3645bdd00b9STheodore Kilgore {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4}, 3655bdd00b9STheodore Kilgore {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, 3665bdd00b9STheodore Kilgore {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4}, 3675bdd00b9STheodore Kilgore {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4}, 3685bdd00b9STheodore Kilgore {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4}, 3695bdd00b9STheodore Kilgore /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */ 3705bdd00b9STheodore Kilgore /* brightness or gain. 0 is default. 4 is good 3715bdd00b9STheodore Kilgore * indoors at night with incandescent lighting */ 3725bdd00b9STheodore Kilgore {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4}, 3735bdd00b9STheodore Kilgore {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/ 3745bdd00b9STheodore Kilgore {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4}, 3755bdd00b9STheodore Kilgore {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 3765bdd00b9STheodore Kilgore {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4}, 3775bdd00b9STheodore Kilgore {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4}, 3785bdd00b9STheodore Kilgore /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */ 3795bdd00b9STheodore Kilgore {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */ 3805bdd00b9STheodore Kilgore /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */ 3815bdd00b9STheodore Kilgore {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1}, 3825bdd00b9STheodore Kilgore {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */ 3835bdd00b9STheodore Kilgore /* Camera should start to capture now. */ 3845bdd00b9STheodore Kilgore }; 3855bdd00b9STheodore Kilgore 3865bdd00b9STheodore Kilgore return run_start_commands(gspca_dev, spy_start_commands, 3875bdd00b9STheodore Kilgore ARRAY_SIZE(spy_start_commands)); 3885bdd00b9STheodore Kilgore } 3895bdd00b9STheodore Kilgore 3905bdd00b9STheodore Kilgore static int start_cif_cam(struct gspca_dev *gspca_dev) 3915bdd00b9STheodore Kilgore { 3925bdd00b9STheodore Kilgore struct init_command cif_start_commands[] = { 3935bdd00b9STheodore Kilgore {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 3945bdd00b9STheodore Kilgore /* The entire sequence below seems redundant */ 3955bdd00b9STheodore Kilgore /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 3965bdd00b9STheodore Kilgore {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 3975bdd00b9STheodore Kilgore {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4}, 3985bdd00b9STheodore Kilgore {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4}, 3995bdd00b9STheodore Kilgore {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 4005bdd00b9STheodore Kilgore {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width? 4015bdd00b9STheodore Kilgore {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height? 4025bdd00b9STheodore Kilgore {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? 4035bdd00b9STheodore Kilgore {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, 4045bdd00b9STheodore Kilgore {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, 4055bdd00b9STheodore Kilgore {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 4065bdd00b9STheodore Kilgore {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 4075bdd00b9STheodore Kilgore {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 4085bdd00b9STheodore Kilgore {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 4095bdd00b9STheodore Kilgore {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 4105bdd00b9STheodore Kilgore {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 4115bdd00b9STheodore Kilgore {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 4125bdd00b9STheodore Kilgore {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 4135bdd00b9STheodore Kilgore {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/ 4145bdd00b9STheodore Kilgore {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1}, 4155bdd00b9STheodore Kilgore {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1}, 4165bdd00b9STheodore Kilgore {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1}, 4175bdd00b9STheodore Kilgore {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, 4185bdd00b9STheodore Kilgore {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1}, 4195bdd00b9STheodore Kilgore {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1}, 4205bdd00b9STheodore Kilgore {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1}, 4215bdd00b9STheodore Kilgore {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1}, 4225bdd00b9STheodore Kilgore {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, 4235bdd00b9STheodore Kilgore {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1}, 4245bdd00b9STheodore Kilgore {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1}, 4255bdd00b9STheodore Kilgore {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1}, 4265bdd00b9STheodore Kilgore {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1}, 4275bdd00b9STheodore Kilgore {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1}, 4285bdd00b9STheodore Kilgore {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1}, 4295bdd00b9STheodore Kilgore {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1}, 4305bdd00b9STheodore Kilgore {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1}, 4315bdd00b9STheodore Kilgore {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1}, 4325bdd00b9STheodore Kilgore {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, 4335bdd00b9STheodore Kilgore {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1}, 4345bdd00b9STheodore Kilgore {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1}, 4355bdd00b9STheodore Kilgore {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, 4365bdd00b9STheodore Kilgore {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */ 4375bdd00b9STheodore Kilgore {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */ 4385bdd00b9STheodore Kilgore /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? 4395bdd00b9STheodore Kilgore * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing 4405bdd00b9STheodore Kilgore * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */ 4415bdd00b9STheodore Kilgore /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 4425bdd00b9STheodore Kilgore * causes subsampling 4435bdd00b9STheodore Kilgore * but not a change in the resolution setting! */ 4445bdd00b9STheodore Kilgore {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 4455bdd00b9STheodore Kilgore {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4}, 4465bdd00b9STheodore Kilgore {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4}, 4475bdd00b9STheodore Kilgore {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4}, 4485bdd00b9STheodore Kilgore {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, 4495bdd00b9STheodore Kilgore {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1}, 4505bdd00b9STheodore Kilgore {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1}, 4515bdd00b9STheodore Kilgore {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, 4525bdd00b9STheodore Kilgore {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1}, 4535bdd00b9STheodore Kilgore {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, 4545bdd00b9STheodore Kilgore {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, 4555bdd00b9STheodore Kilgore {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, 4565bdd00b9STheodore Kilgore {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1}, 4575bdd00b9STheodore Kilgore {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, 4585bdd00b9STheodore Kilgore {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, 4595bdd00b9STheodore Kilgore {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */ 4605bdd00b9STheodore Kilgore /* Camera should start to capture now. */ 4615bdd00b9STheodore Kilgore }; 4625bdd00b9STheodore Kilgore 4635bdd00b9STheodore Kilgore return run_start_commands(gspca_dev, cif_start_commands, 4645bdd00b9STheodore Kilgore ARRAY_SIZE(cif_start_commands)); 4655bdd00b9STheodore Kilgore } 4665bdd00b9STheodore Kilgore 4675bdd00b9STheodore Kilgore static int start_ms350_cam(struct gspca_dev *gspca_dev) 4685bdd00b9STheodore Kilgore { 4695bdd00b9STheodore Kilgore struct init_command ms350_start_commands[] = { 4705bdd00b9STheodore Kilgore {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 4715bdd00b9STheodore Kilgore {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 4725bdd00b9STheodore Kilgore {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 4735bdd00b9STheodore Kilgore {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 4745bdd00b9STheodore Kilgore {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, 4755bdd00b9STheodore Kilgore {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, 4765bdd00b9STheodore Kilgore {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 4775bdd00b9STheodore Kilgore {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 4785bdd00b9STheodore Kilgore {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 4795bdd00b9STheodore Kilgore {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, 4805bdd00b9STheodore Kilgore {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, 4815bdd00b9STheodore Kilgore {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, 4825bdd00b9STheodore Kilgore {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 4835bdd00b9STheodore Kilgore {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 4845bdd00b9STheodore Kilgore {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 4855bdd00b9STheodore Kilgore {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 4865bdd00b9STheodore Kilgore {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 4875bdd00b9STheodore Kilgore {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 4885bdd00b9STheodore Kilgore {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 4895bdd00b9STheodore Kilgore {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 4905bdd00b9STheodore Kilgore {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 4915bdd00b9STheodore Kilgore {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4}, 4925bdd00b9STheodore Kilgore {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4}, 4935bdd00b9STheodore Kilgore {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4}, 4945bdd00b9STheodore Kilgore {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4}, 4955bdd00b9STheodore Kilgore {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4}, 4965bdd00b9STheodore Kilgore {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4}, 4975bdd00b9STheodore Kilgore {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4}, 4985bdd00b9STheodore Kilgore {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4}, 4995bdd00b9STheodore Kilgore {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4}, 5005bdd00b9STheodore Kilgore {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4}, 5015bdd00b9STheodore Kilgore {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4}, 5025bdd00b9STheodore Kilgore {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, 5035bdd00b9STheodore Kilgore {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4}, 5045bdd00b9STheodore Kilgore {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4}, 5055bdd00b9STheodore Kilgore {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4}, 5065bdd00b9STheodore Kilgore {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, 5075bdd00b9STheodore Kilgore {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 5085bdd00b9STheodore Kilgore {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4}, 5095bdd00b9STheodore Kilgore {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 5105bdd00b9STheodore Kilgore {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4}, 5115bdd00b9STheodore Kilgore {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4}, 5125bdd00b9STheodore Kilgore {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4}, 5135bdd00b9STheodore Kilgore {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4}, 5145bdd00b9STheodore Kilgore {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width */ 5155bdd00b9STheodore Kilgore {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */ 5165bdd00b9STheodore Kilgore {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */ 5175bdd00b9STheodore Kilgore {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, 5185bdd00b9STheodore Kilgore {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */ 5195bdd00b9STheodore Kilgore {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 5205bdd00b9STheodore Kilgore {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 5215bdd00b9STheodore Kilgore {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 5225bdd00b9STheodore Kilgore {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 5235bdd00b9STheodore Kilgore {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1}, 5245bdd00b9STheodore Kilgore {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, 5255bdd00b9STheodore Kilgore {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1}, 5265bdd00b9STheodore Kilgore {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1}, 5275bdd00b9STheodore Kilgore {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0}, 5285bdd00b9STheodore Kilgore /* Camera should start to capture now. */ 5295bdd00b9STheodore Kilgore }; 5305bdd00b9STheodore Kilgore 5315bdd00b9STheodore Kilgore return run_start_commands(gspca_dev, ms350_start_commands, 5325bdd00b9STheodore Kilgore ARRAY_SIZE(ms350_start_commands)); 5335bdd00b9STheodore Kilgore } 5345bdd00b9STheodore Kilgore 5355bdd00b9STheodore Kilgore static int start_genius_cam(struct gspca_dev *gspca_dev) 5365bdd00b9STheodore Kilgore { 5375bdd00b9STheodore Kilgore struct init_command genius_start_commands[] = { 5385bdd00b9STheodore Kilgore {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 5395bdd00b9STheodore Kilgore {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 5405bdd00b9STheodore Kilgore {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4}, 5415bdd00b9STheodore Kilgore {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 5425bdd00b9STheodore Kilgore {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 5435bdd00b9STheodore Kilgore /* "preliminary" width and height settings */ 5445bdd00b9STheodore Kilgore {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 5455bdd00b9STheodore Kilgore {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 5465bdd00b9STheodore Kilgore {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 5475bdd00b9STheodore Kilgore {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 5485bdd00b9STheodore Kilgore {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 5495bdd00b9STheodore Kilgore {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 5505bdd00b9STheodore Kilgore {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 5515bdd00b9STheodore Kilgore {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 5525bdd00b9STheodore Kilgore {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 5535bdd00b9STheodore Kilgore {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 5545bdd00b9STheodore Kilgore {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 5555bdd00b9STheodore Kilgore {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 5565bdd00b9STheodore Kilgore {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, 5575bdd00b9STheodore Kilgore {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 5585bdd00b9STheodore Kilgore {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, 5595bdd00b9STheodore Kilgore {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 5605bdd00b9STheodore Kilgore {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, 5615bdd00b9STheodore Kilgore {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, 5625bdd00b9STheodore Kilgore {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, 5635bdd00b9STheodore Kilgore {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 5645bdd00b9STheodore Kilgore {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 5655bdd00b9STheodore Kilgore {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 5665bdd00b9STheodore Kilgore {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 5675bdd00b9STheodore Kilgore {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4}, 5685bdd00b9STheodore Kilgore {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4}, 5695bdd00b9STheodore Kilgore {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4}, 5705bdd00b9STheodore Kilgore {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4}, 5715bdd00b9STheodore Kilgore {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4}, 5725bdd00b9STheodore Kilgore {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4}, 5735bdd00b9STheodore Kilgore {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4}, 5745bdd00b9STheodore Kilgore {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4}, 5755bdd00b9STheodore Kilgore {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4}, 5765bdd00b9STheodore Kilgore {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */ 5775bdd00b9STheodore Kilgore {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */ 5785bdd00b9STheodore Kilgore {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 5795bdd00b9STheodore Kilgore {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 5805bdd00b9STheodore Kilgore {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4}, 5815bdd00b9STheodore Kilgore {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 5825bdd00b9STheodore Kilgore {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 5835bdd00b9STheodore Kilgore {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 5845bdd00b9STheodore Kilgore {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 5855bdd00b9STheodore Kilgore {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 5865bdd00b9STheodore Kilgore {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4}, 5875bdd00b9STheodore Kilgore {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 5885bdd00b9STheodore Kilgore {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4}, 5895bdd00b9STheodore Kilgore {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 5905bdd00b9STheodore Kilgore {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4}, 5915bdd00b9STheodore Kilgore {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 5925bdd00b9STheodore Kilgore {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4}, 5935bdd00b9STheodore Kilgore {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 5945bdd00b9STheodore Kilgore {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4}, 5955bdd00b9STheodore Kilgore {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4}, 5965bdd00b9STheodore Kilgore {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4}, 5975bdd00b9STheodore Kilgore {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, 5985bdd00b9STheodore Kilgore {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, 5995bdd00b9STheodore Kilgore {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0} 6005bdd00b9STheodore Kilgore /* Camera should start to capture now. */ 6015bdd00b9STheodore Kilgore }; 6025bdd00b9STheodore Kilgore 6035bdd00b9STheodore Kilgore return run_start_commands(gspca_dev, genius_start_commands, 6045bdd00b9STheodore Kilgore ARRAY_SIZE(genius_start_commands)); 6055bdd00b9STheodore Kilgore } 6065bdd00b9STheodore Kilgore 60748c291edSVasily Khoruzhick static int start_genius_videocam_live(struct gspca_dev *gspca_dev) 60848c291edSVasily Khoruzhick { 60948c291edSVasily Khoruzhick int r; 61048c291edSVasily Khoruzhick struct sd *sd = (struct sd *) gspca_dev; 61148c291edSVasily Khoruzhick struct init_command genius_vcam_live_start_commands[] = { 61248c291edSVasily Khoruzhick {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 0}, 61348c291edSVasily Khoruzhick {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 61448c291edSVasily Khoruzhick {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4}, 61548c291edSVasily Khoruzhick {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 61648c291edSVasily Khoruzhick {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 61748c291edSVasily Khoruzhick 61848c291edSVasily Khoruzhick {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 61948c291edSVasily Khoruzhick {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 62048c291edSVasily Khoruzhick {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 62148c291edSVasily Khoruzhick {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 62248c291edSVasily Khoruzhick {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 62348c291edSVasily Khoruzhick {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 62448c291edSVasily Khoruzhick {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 62548c291edSVasily Khoruzhick {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 62648c291edSVasily Khoruzhick {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 62748c291edSVasily Khoruzhick {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 62848c291edSVasily Khoruzhick {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 62948c291edSVasily Khoruzhick {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 63048c291edSVasily Khoruzhick {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, 63148c291edSVasily Khoruzhick {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 63248c291edSVasily Khoruzhick {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, 63348c291edSVasily Khoruzhick {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 63448c291edSVasily Khoruzhick {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, 63548c291edSVasily Khoruzhick {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, 63648c291edSVasily Khoruzhick {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, 63748c291edSVasily Khoruzhick {{0x1c, 0x20, 0x00, 0x2d, 0x00, 0x00}, 4}, 63848c291edSVasily Khoruzhick {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 63948c291edSVasily Khoruzhick {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 64048c291edSVasily Khoruzhick {{0x13, 0x22, 0x01, 0x00, 0x00, 0x00}, 4}, 64148c291edSVasily Khoruzhick {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4}, 64248c291edSVasily Khoruzhick {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 64348c291edSVasily Khoruzhick {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, 64448c291edSVasily Khoruzhick {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, 64548c291edSVasily Khoruzhick {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 64648c291edSVasily Khoruzhick {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 64748c291edSVasily Khoruzhick {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, 64848c291edSVasily Khoruzhick {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 64948c291edSVasily Khoruzhick {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 65048c291edSVasily Khoruzhick {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 65148c291edSVasily Khoruzhick {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, 65248c291edSVasily Khoruzhick {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, 65348c291edSVasily Khoruzhick {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, 65448c291edSVasily Khoruzhick {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 65548c291edSVasily Khoruzhick {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 65648c291edSVasily Khoruzhick {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 65748c291edSVasily Khoruzhick {{0x11, 0x01, 0x04, 0x00, 0x00, 0x00}, 4}, 65848c291edSVasily Khoruzhick {{0x11, 0x02, 0x92, 0x00, 0x00, 0x00}, 4}, 65948c291edSVasily Khoruzhick {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 66048c291edSVasily Khoruzhick {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, 66148c291edSVasily Khoruzhick {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 66248c291edSVasily Khoruzhick {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, 66348c291edSVasily Khoruzhick {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 66448c291edSVasily Khoruzhick {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, 66548c291edSVasily Khoruzhick {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, 66648c291edSVasily Khoruzhick {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, 66748c291edSVasily Khoruzhick {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 66848c291edSVasily Khoruzhick {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, 66948c291edSVasily Khoruzhick {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 67048c291edSVasily Khoruzhick {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, 67148c291edSVasily Khoruzhick {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4}, 67248c291edSVasily Khoruzhick {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4}, 67348c291edSVasily Khoruzhick {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4}, 67448c291edSVasily Khoruzhick {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4}, 67548c291edSVasily Khoruzhick {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4}, 67648c291edSVasily Khoruzhick {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4}, 67748c291edSVasily Khoruzhick {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4}, 67848c291edSVasily Khoruzhick {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4}, 67948c291edSVasily Khoruzhick {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4}, 68048c291edSVasily Khoruzhick {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, 68148c291edSVasily Khoruzhick {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, 68248c291edSVasily Khoruzhick {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, 68348c291edSVasily Khoruzhick {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 68448c291edSVasily Khoruzhick {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4}, 68548c291edSVasily Khoruzhick {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 68648c291edSVasily Khoruzhick {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 68748c291edSVasily Khoruzhick {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 68848c291edSVasily Khoruzhick {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 68948c291edSVasily Khoruzhick {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, 69048c291edSVasily Khoruzhick {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4}, 69148c291edSVasily Khoruzhick {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, 69248c291edSVasily Khoruzhick {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4}, 69348c291edSVasily Khoruzhick {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, 69448c291edSVasily Khoruzhick {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4}, 69548c291edSVasily Khoruzhick {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, 69648c291edSVasily Khoruzhick {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4}, 69748c291edSVasily Khoruzhick {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, 69848c291edSVasily Khoruzhick {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4}, 69948c291edSVasily Khoruzhick {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4}, 70048c291edSVasily Khoruzhick {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4}, 70148c291edSVasily Khoruzhick {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, 70248c291edSVasily Khoruzhick {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}, 70348c291edSVasily Khoruzhick /* Camera should start to capture now. */ 70448c291edSVasily Khoruzhick {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 0}, 70548c291edSVasily Khoruzhick {{0x1b, 0x32, 0x26, 0x00, 0x00, 0x00}, 0}, 70648c291edSVasily Khoruzhick {{0x1d, 0x25, 0x10, 0x20, 0xab, 0x00}, 0}, 70748c291edSVasily Khoruzhick }; 70848c291edSVasily Khoruzhick 70948c291edSVasily Khoruzhick r = run_start_commands(gspca_dev, genius_vcam_live_start_commands, 71048c291edSVasily Khoruzhick ARRAY_SIZE(genius_vcam_live_start_commands)); 71148c291edSVasily Khoruzhick if (r < 0) 71248c291edSVasily Khoruzhick return r; 71348c291edSVasily Khoruzhick 714d8fd9f56SVasily Khoruzhick if (sd->gain) 715d8fd9f56SVasily Khoruzhick set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain)); 716d8fd9f56SVasily Khoruzhick 71748c291edSVasily Khoruzhick return r; 71848c291edSVasily Khoruzhick } 71948c291edSVasily Khoruzhick 7205bdd00b9STheodore Kilgore static int start_vivitar_cam(struct gspca_dev *gspca_dev) 7215bdd00b9STheodore Kilgore { 7225bdd00b9STheodore Kilgore struct init_command vivitar_start_commands[] = { 7235bdd00b9STheodore Kilgore {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, 7245bdd00b9STheodore Kilgore {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, 7255bdd00b9STheodore Kilgore {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, 7265bdd00b9STheodore Kilgore {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4}, 7275bdd00b9STheodore Kilgore {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4}, 7285bdd00b9STheodore Kilgore {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, 7295bdd00b9STheodore Kilgore {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, 7305bdd00b9STheodore Kilgore {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, 7315bdd00b9STheodore Kilgore {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, 7325bdd00b9STheodore Kilgore {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4}, 7335bdd00b9STheodore Kilgore /* 7345bdd00b9STheodore Kilgore * Above is changed from OEM 0x0b. Fixes Bayer tiling. 7355bdd00b9STheodore Kilgore * Presumably gives a vertical shift of one row. 7365bdd00b9STheodore Kilgore */ 7375bdd00b9STheodore Kilgore {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, 7385bdd00b9STheodore Kilgore /* Above seems to do horizontal shift. */ 7395bdd00b9STheodore Kilgore {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, 7405bdd00b9STheodore Kilgore {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, 7415bdd00b9STheodore Kilgore {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, 7425bdd00b9STheodore Kilgore {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, 7435bdd00b9STheodore Kilgore {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, 7445bdd00b9STheodore Kilgore {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, 7455bdd00b9STheodore Kilgore /* Above three commands seem to relate to brightness. */ 7465bdd00b9STheodore Kilgore {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, 7475bdd00b9STheodore Kilgore {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, 7485bdd00b9STheodore Kilgore {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, 7495bdd00b9STheodore Kilgore {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1}, 7505bdd00b9STheodore Kilgore {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1}, 7515bdd00b9STheodore Kilgore {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1}, 7525bdd00b9STheodore Kilgore {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1}, 7535bdd00b9STheodore Kilgore {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, 7545bdd00b9STheodore Kilgore {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1}, 7555bdd00b9STheodore Kilgore {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1}, 7565bdd00b9STheodore Kilgore {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1}, 7575bdd00b9STheodore Kilgore {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1}, 7585bdd00b9STheodore Kilgore {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1}, 7595bdd00b9STheodore Kilgore {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1}, 7605bdd00b9STheodore Kilgore {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1}, 7615bdd00b9STheodore Kilgore {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1}, 7625bdd00b9STheodore Kilgore {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, 7635bdd00b9STheodore Kilgore {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1}, 7645bdd00b9STheodore Kilgore {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1}, 7655bdd00b9STheodore Kilgore {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1}, 7665bdd00b9STheodore Kilgore {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1}, 7675bdd00b9STheodore Kilgore {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1}, 7685bdd00b9STheodore Kilgore {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1}, 7695bdd00b9STheodore Kilgore {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1}, 7705bdd00b9STheodore Kilgore {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1}, 7715bdd00b9STheodore Kilgore {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1}, 7725bdd00b9STheodore Kilgore {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1}, 7735bdd00b9STheodore Kilgore {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1}, 7745bdd00b9STheodore Kilgore {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1}, 7755bdd00b9STheodore Kilgore {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1}, 7765bdd00b9STheodore Kilgore {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1}, 7775bdd00b9STheodore Kilgore {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1}, 7785bdd00b9STheodore Kilgore {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1}, 7795bdd00b9STheodore Kilgore {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1}, 7805bdd00b9STheodore Kilgore {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1}, 7815bdd00b9STheodore Kilgore {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1}, 7825bdd00b9STheodore Kilgore {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1}, 7835bdd00b9STheodore Kilgore /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, 7845bdd00b9STheodore Kilgore {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, 7855bdd00b9STheodore Kilgore {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */ 7865bdd00b9STheodore Kilgore {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, 7875bdd00b9STheodore Kilgore {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1}, 7885bdd00b9STheodore Kilgore {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, 7895bdd00b9STheodore Kilgore {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1}, 7905bdd00b9STheodore Kilgore {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, 7915bdd00b9STheodore Kilgore {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1}, 7925bdd00b9STheodore Kilgore /* Above is brightness; OEM driver setting is 0x10 */ 7935bdd00b9STheodore Kilgore {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, 7945bdd00b9STheodore Kilgore {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, 7955bdd00b9STheodore Kilgore {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1} 7965bdd00b9STheodore Kilgore }; 7975bdd00b9STheodore Kilgore 7985bdd00b9STheodore Kilgore return run_start_commands(gspca_dev, vivitar_start_commands, 7995bdd00b9STheodore Kilgore ARRAY_SIZE(vivitar_start_commands)); 8005bdd00b9STheodore Kilgore } 8015bdd00b9STheodore Kilgore 8025bdd00b9STheodore Kilgore static int sd_start(struct gspca_dev *gspca_dev) 8035bdd00b9STheodore Kilgore { 8045bdd00b9STheodore Kilgore struct sd *sd = (struct sd *) gspca_dev; 8055bdd00b9STheodore Kilgore int err_code; 8065bdd00b9STheodore Kilgore 8075bdd00b9STheodore Kilgore sd->sof_read = 0; 8085bdd00b9STheodore Kilgore 8095bdd00b9STheodore Kilgore switch (sd->model) { 8105bdd00b9STheodore Kilgore case 0x7005: 8115bdd00b9STheodore Kilgore err_code = start_genius_cam(gspca_dev); 8125bdd00b9STheodore Kilgore break; 81348c291edSVasily Khoruzhick case 0x7003: 81448c291edSVasily Khoruzhick err_code = start_genius_videocam_live(gspca_dev); 81548c291edSVasily Khoruzhick break; 8165bdd00b9STheodore Kilgore case 0x8001: 8175bdd00b9STheodore Kilgore err_code = start_spy_cam(gspca_dev); 8185bdd00b9STheodore Kilgore break; 8195bdd00b9STheodore Kilgore case 0x8003: 8205bdd00b9STheodore Kilgore err_code = start_cif_cam(gspca_dev); 8215bdd00b9STheodore Kilgore break; 8225bdd00b9STheodore Kilgore case 0x8008: 8235bdd00b9STheodore Kilgore err_code = start_ms350_cam(gspca_dev); 8245bdd00b9STheodore Kilgore break; 8255bdd00b9STheodore Kilgore case 0x800a: 8265bdd00b9STheodore Kilgore err_code = start_vivitar_cam(gspca_dev); 8275bdd00b9STheodore Kilgore break; 8285bdd00b9STheodore Kilgore default: 829133a9fe9SJoe Perches pr_err("Starting unknown camera, please report this\n"); 8305bdd00b9STheodore Kilgore return -ENXIO; 8315bdd00b9STheodore Kilgore } 8325bdd00b9STheodore Kilgore 833d8fd9f56SVasily Khoruzhick sd->avg_lum = -1; 834d8fd9f56SVasily Khoruzhick 8355bdd00b9STheodore Kilgore return err_code; 8365bdd00b9STheodore Kilgore } 8375bdd00b9STheodore Kilgore 8385bdd00b9STheodore Kilgore static void sd_stopN(struct gspca_dev *gspca_dev) 8395bdd00b9STheodore Kilgore { 8405bdd00b9STheodore Kilgore int result; 8415bdd00b9STheodore Kilgore __u8 data[6]; 8425bdd00b9STheodore Kilgore 8435bdd00b9STheodore Kilgore result = sn9c2028_read1(gspca_dev); 8445bdd00b9STheodore Kilgore if (result < 0) 84552173c5fSJoe Perches gspca_err(gspca_dev, "Camera Stop read failed\n"); 8465bdd00b9STheodore Kilgore 8475bdd00b9STheodore Kilgore memset(data, 0, 6); 8485bdd00b9STheodore Kilgore data[0] = 0x14; 8495bdd00b9STheodore Kilgore result = sn9c2028_command(gspca_dev, data); 8505bdd00b9STheodore Kilgore if (result < 0) 85152173c5fSJoe Perches gspca_err(gspca_dev, "Camera Stop command failed\n"); 8525bdd00b9STheodore Kilgore } 8535bdd00b9STheodore Kilgore 854d8fd9f56SVasily Khoruzhick static void do_autogain(struct gspca_dev *gspca_dev, int avg_lum) 855d8fd9f56SVasily Khoruzhick { 856d8fd9f56SVasily Khoruzhick struct sd *sd = (struct sd *) gspca_dev; 857d8fd9f56SVasily Khoruzhick s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain); 858d8fd9f56SVasily Khoruzhick 859d8fd9f56SVasily Khoruzhick if (avg_lum == -1) 860d8fd9f56SVasily Khoruzhick return; 861d8fd9f56SVasily Khoruzhick 862d8fd9f56SVasily Khoruzhick if (avg_lum < MIN_AVG_LUM) { 863d8fd9f56SVasily Khoruzhick if (cur_gain == sd->gain->maximum) 864d8fd9f56SVasily Khoruzhick return; 865d8fd9f56SVasily Khoruzhick cur_gain++; 866d8fd9f56SVasily Khoruzhick v4l2_ctrl_s_ctrl(sd->gain, cur_gain); 867d8fd9f56SVasily Khoruzhick } 868d8fd9f56SVasily Khoruzhick if (avg_lum > MAX_AVG_LUM) { 869d8fd9f56SVasily Khoruzhick if (cur_gain == sd->gain->minimum) 870d8fd9f56SVasily Khoruzhick return; 871d8fd9f56SVasily Khoruzhick cur_gain--; 872d8fd9f56SVasily Khoruzhick v4l2_ctrl_s_ctrl(sd->gain, cur_gain); 873d8fd9f56SVasily Khoruzhick } 874d8fd9f56SVasily Khoruzhick 875d8fd9f56SVasily Khoruzhick } 876d8fd9f56SVasily Khoruzhick 877d8fd9f56SVasily Khoruzhick static void sd_dqcallback(struct gspca_dev *gspca_dev) 878d8fd9f56SVasily Khoruzhick { 879d8fd9f56SVasily Khoruzhick struct sd *sd = (struct sd *) gspca_dev; 880d8fd9f56SVasily Khoruzhick 881d8fd9f56SVasily Khoruzhick if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain)) 882d8fd9f56SVasily Khoruzhick return; 883d8fd9f56SVasily Khoruzhick 884d8fd9f56SVasily Khoruzhick do_autogain(gspca_dev, sd->avg_lum); 885d8fd9f56SVasily Khoruzhick } 886d8fd9f56SVasily Khoruzhick 8875bdd00b9STheodore Kilgore /* Include sn9c2028 sof detection functions */ 8885bdd00b9STheodore Kilgore #include "sn9c2028.h" 8895bdd00b9STheodore Kilgore 8905bdd00b9STheodore Kilgore static void sd_pkt_scan(struct gspca_dev *gspca_dev, 8915bdd00b9STheodore Kilgore __u8 *data, /* isoc packet */ 8925bdd00b9STheodore Kilgore int len) /* iso packet length */ 8935bdd00b9STheodore Kilgore { 8945bdd00b9STheodore Kilgore unsigned char *sof; 8955bdd00b9STheodore Kilgore 8965bdd00b9STheodore Kilgore sof = sn9c2028_find_sof(gspca_dev, data, len); 8975bdd00b9STheodore Kilgore if (sof) { 8985bdd00b9STheodore Kilgore int n; 8995bdd00b9STheodore Kilgore 9005bdd00b9STheodore Kilgore /* finish decoding current frame */ 9015bdd00b9STheodore Kilgore n = sof - data; 9025bdd00b9STheodore Kilgore if (n > sizeof sn9c2028_sof_marker) 9035bdd00b9STheodore Kilgore n -= sizeof sn9c2028_sof_marker; 9045bdd00b9STheodore Kilgore else 9055bdd00b9STheodore Kilgore n = 0; 9065bdd00b9STheodore Kilgore gspca_frame_add(gspca_dev, LAST_PACKET, data, n); 9075bdd00b9STheodore Kilgore /* Start next frame. */ 9085bdd00b9STheodore Kilgore gspca_frame_add(gspca_dev, FIRST_PACKET, 9095bdd00b9STheodore Kilgore sn9c2028_sof_marker, sizeof sn9c2028_sof_marker); 9105bdd00b9STheodore Kilgore len -= sof - data; 9115bdd00b9STheodore Kilgore data = sof; 9125bdd00b9STheodore Kilgore } 9135bdd00b9STheodore Kilgore gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 9145bdd00b9STheodore Kilgore } 9155bdd00b9STheodore Kilgore 9165bdd00b9STheodore Kilgore /* sub-driver description */ 9175bdd00b9STheodore Kilgore static const struct sd_desc sd_desc = { 9185bdd00b9STheodore Kilgore .name = MODULE_NAME, 9195bdd00b9STheodore Kilgore .config = sd_config, 9205bdd00b9STheodore Kilgore .init = sd_init, 921d8fd9f56SVasily Khoruzhick .init_controls = sd_init_controls, 9225bdd00b9STheodore Kilgore .start = sd_start, 9235bdd00b9STheodore Kilgore .stopN = sd_stopN, 924d8fd9f56SVasily Khoruzhick .dq_callback = sd_dqcallback, 9255bdd00b9STheodore Kilgore .pkt_scan = sd_pkt_scan, 9265bdd00b9STheodore Kilgore }; 9275bdd00b9STheodore Kilgore 9285bdd00b9STheodore Kilgore /* -- module initialisation -- */ 92995c967c1SJean-François Moine static const struct usb_device_id device_table[] = { 9305bdd00b9STheodore Kilgore {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */ 93148c291edSVasily Khoruzhick {USB_DEVICE(0x0458, 0x7003)}, /* Genius Videocam Live v2 */ 9325bdd00b9STheodore Kilgore /* The Genius Smart is untested. I can't find an owner ! */ 9335bdd00b9STheodore Kilgore /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */ 9345bdd00b9STheodore Kilgore {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */ 9355bdd00b9STheodore Kilgore {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */ 9365bdd00b9STheodore Kilgore /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */ 9375bdd00b9STheodore Kilgore {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */ 9385bdd00b9STheodore Kilgore {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */ 9395bdd00b9STheodore Kilgore {} 9405bdd00b9STheodore Kilgore }; 9415bdd00b9STheodore Kilgore MODULE_DEVICE_TABLE(usb, device_table); 9425bdd00b9STheodore Kilgore 9435bdd00b9STheodore Kilgore /* -- device connect -- */ 9445bdd00b9STheodore Kilgore static int sd_probe(struct usb_interface *intf, 9455bdd00b9STheodore Kilgore const struct usb_device_id *id) 9465bdd00b9STheodore Kilgore { 9475bdd00b9STheodore Kilgore return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), 9485bdd00b9STheodore Kilgore THIS_MODULE); 9495bdd00b9STheodore Kilgore } 9505bdd00b9STheodore Kilgore 9515bdd00b9STheodore Kilgore static struct usb_driver sd_driver = { 9525bdd00b9STheodore Kilgore .name = MODULE_NAME, 9535bdd00b9STheodore Kilgore .id_table = device_table, 9545bdd00b9STheodore Kilgore .probe = sd_probe, 9555bdd00b9STheodore Kilgore .disconnect = gspca_disconnect, 9565bdd00b9STheodore Kilgore #ifdef CONFIG_PM 9575bdd00b9STheodore Kilgore .suspend = gspca_suspend, 9585bdd00b9STheodore Kilgore .resume = gspca_resume, 9598bb58964SHans de Goede .reset_resume = gspca_resume, 9605bdd00b9STheodore Kilgore #endif 9615bdd00b9STheodore Kilgore }; 9625bdd00b9STheodore Kilgore 963ecb3b2b3SGreg Kroah-Hartman module_usb_driver(sd_driver); 964