From e5fd91f1ef340da553f7a79da9540c3db711c937 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Tue, 8 Sep 2015 01:01:14 -0300 Subject: Linux-libre 4.2-gnu --- drivers/media/usb/gspca/benq.c | 4 +- drivers/media/usb/gspca/sn9c2028.c | 241 +++++++++++++++++++++++++++++++++- drivers/media/usb/gspca/sn9c2028.h | 18 ++- drivers/media/usb/gspca/sonixj.c | 2 +- drivers/media/usb/gspca/stk014.c | 2 +- drivers/media/usb/gspca/xirlink_cit.c | 12 +- drivers/media/usb/gspca/zc3xx.c | 16 +-- 7 files changed, 276 insertions(+), 19 deletions(-) (limited to 'drivers/media/usb/gspca') diff --git a/drivers/media/usb/gspca/benq.c b/drivers/media/usb/gspca/benq.c index 05f406dea..790baed33 100644 --- a/drivers/media/usb/gspca/benq.c +++ b/drivers/media/usb/gspca/benq.c @@ -236,8 +236,8 @@ static void sd_isoc_irq(struct urb *urb) } data = (u8 *) urb->transfer_buffer + urb->iso_frame_desc[i].offset; - gspca_frame_add(gspca_dev, INTER_PACKET, - data, SD_PKT_SZ); + gspca_frame_add(gspca_dev, INTER_PACKET, + data, SD_PKT_SZ); } /* resubmit the URBs */ diff --git a/drivers/media/usb/gspca/sn9c2028.c b/drivers/media/usb/gspca/sn9c2028.c index 39b6b2e02..c75b7388a 100644 --- a/drivers/media/usb/gspca/sn9c2028.c +++ b/drivers/media/usb/gspca/sn9c2028.c @@ -33,6 +33,16 @@ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ u8 sof_read; u16 model; + +#define MIN_AVG_LUM 8500 +#define MAX_AVG_LUM 10000 + int avg_lum; + u8 avg_lum_l; + + struct { /* autogain and gain control cluster */ + struct v4l2_ctrl *autogain; + struct v4l2_ctrl *gain; + }; }; struct init_command { @@ -128,7 +138,7 @@ static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command) status = -1; for (i = 0; i < 256 && status < 2; i++) status = sn9c2028_read1(gspca_dev); - if (status != 2) { + if (status < 0) { pr_err("long command status read error %d\n", status); return (status < 0) ? status : -EIO; } @@ -178,6 +188,9 @@ static int sd_config(struct gspca_dev *gspca_dev, case 0x7005: PDEBUG(D_PROBE, "Genius Smart 300 camera"); break; + case 0x7003: + PDEBUG(D_PROBE, "Genius Videocam Live v2"); + break; case 0x8000: PDEBUG(D_PROBE, "DC31VC"); break; @@ -248,6 +261,78 @@ static int run_start_commands(struct gspca_dev *gspca_dev, return 0; } +static void set_gain(struct gspca_dev *gspca_dev, s32 g) +{ + struct sd *sd = (struct sd *) gspca_dev; + + struct init_command genius_vcam_live_gain_cmds[] = { + {{0x1d, 0x25, 0x10 /* This byte is gain */, + 0x20, 0xab, 0x00}, 0}, + }; + if (!gspca_dev->streaming) + return; + + switch (sd->model) { + case 0x7003: + genius_vcam_live_gain_cmds[0].instruction[2] = g; + run_start_commands(gspca_dev, genius_vcam_live_gain_cmds, + ARRAY_SIZE(genius_vcam_live_gain_cmds)); + break; + default: + break; + } +} + +static int sd_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct gspca_dev *gspca_dev = + container_of(ctrl->handler, struct gspca_dev, ctrl_handler); + struct sd *sd = (struct sd *)gspca_dev; + + gspca_dev->usb_err = 0; + + if (!gspca_dev->streaming) + return 0; + + switch (ctrl->id) { + /* standalone gain control */ + case V4L2_CID_GAIN: + set_gain(gspca_dev, ctrl->val); + break; + /* autogain */ + case V4L2_CID_AUTOGAIN: + set_gain(gspca_dev, sd->gain->val); + break; + } + return gspca_dev->usb_err; +} + +static const struct v4l2_ctrl_ops sd_ctrl_ops = { + .s_ctrl = sd_s_ctrl, +}; + + +static int sd_init_controls(struct gspca_dev *gspca_dev) +{ + struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; + struct sd *sd = (struct sd *)gspca_dev; + + gspca_dev->vdev.ctrl_handler = hdl; + v4l2_ctrl_handler_init(hdl, 2); + + switch (sd->model) { + case 0x7003: + sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + V4L2_CID_GAIN, 0, 20, 1, 0); + sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, + V4L2_CID_AUTOGAIN, 0, 1, 1, 1); + break; + default: + break; + } + + return 0; +} static int start_spy_cam(struct gspca_dev *gspca_dev) { struct init_command spy_start_commands[] = { @@ -530,6 +615,119 @@ static int start_genius_cam(struct gspca_dev *gspca_dev) ARRAY_SIZE(genius_start_commands)); } +static int start_genius_videocam_live(struct gspca_dev *gspca_dev) +{ + int r; + struct sd *sd = (struct sd *) gspca_dev; + struct init_command genius_vcam_live_start_commands[] = { + {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 0}, + {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, + {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, + + {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, + {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, + {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, + {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, + {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, + {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, + {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, + {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, + {{0x1c, 0x20, 0x00, 0x2d, 0x00, 0x00}, 4}, + {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x13, 0x22, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4}, + {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, + {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, + {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, + {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, + {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, + {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, + {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, + {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, + {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, + {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, + {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x01, 0x04, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x02, 0x92, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4}, + {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, + {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, + {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, + {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, + {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4}, + {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, + {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, + {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, + {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, + {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4}, + {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4}, + {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, + {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}, + /* Camera should start to capture now. */ + {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 0}, + {{0x1b, 0x32, 0x26, 0x00, 0x00, 0x00}, 0}, + {{0x1d, 0x25, 0x10, 0x20, 0xab, 0x00}, 0}, + }; + + r = run_start_commands(gspca_dev, genius_vcam_live_start_commands, + ARRAY_SIZE(genius_vcam_live_start_commands)); + if (r < 0) + return r; + + if (sd->gain) + set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain)); + + return r; +} + static int start_vivitar_cam(struct gspca_dev *gspca_dev) { struct init_command vivitar_start_commands[] = { @@ -623,6 +821,9 @@ static int sd_start(struct gspca_dev *gspca_dev) case 0x7005: err_code = start_genius_cam(gspca_dev); break; + case 0x7003: + err_code = start_genius_videocam_live(gspca_dev); + break; case 0x8001: err_code = start_spy_cam(gspca_dev); break; @@ -640,6 +841,8 @@ static int sd_start(struct gspca_dev *gspca_dev) return -ENXIO; } + sd->avg_lum = -1; + return err_code; } @@ -659,6 +862,39 @@ static void sd_stopN(struct gspca_dev *gspca_dev) PERR("Camera Stop command failed"); } +static void do_autogain(struct gspca_dev *gspca_dev, int avg_lum) +{ + struct sd *sd = (struct sd *) gspca_dev; + s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain); + + if (avg_lum == -1) + return; + + if (avg_lum < MIN_AVG_LUM) { + if (cur_gain == sd->gain->maximum) + return; + cur_gain++; + v4l2_ctrl_s_ctrl(sd->gain, cur_gain); + } + if (avg_lum > MAX_AVG_LUM) { + if (cur_gain == sd->gain->minimum) + return; + cur_gain--; + v4l2_ctrl_s_ctrl(sd->gain, cur_gain); + } + +} + +static void sd_dqcallback(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain)) + return; + + do_autogain(gspca_dev, sd->avg_lum); +} + /* Include sn9c2028 sof detection functions */ #include "sn9c2028.h" @@ -693,14 +929,17 @@ static const struct sd_desc sd_desc = { .name = MODULE_NAME, .config = sd_config, .init = sd_init, + .init_controls = sd_init_controls, .start = sd_start, .stopN = sd_stopN, + .dq_callback = sd_dqcallback, .pkt_scan = sd_pkt_scan, }; /* -- module initialisation -- */ static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */ + {USB_DEVICE(0x0458, 0x7003)}, /* Genius Videocam Live v2 */ /* The Genius Smart is untested. I can't find an owner ! */ /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */ {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */ diff --git a/drivers/media/usb/gspca/sn9c2028.h b/drivers/media/usb/gspca/sn9c2028.h index 8fd1d3e05..f85bc106b 100644 --- a/drivers/media/usb/gspca/sn9c2028.h +++ b/drivers/media/usb/gspca/sn9c2028.h @@ -21,8 +21,15 @@ * */ -static const unsigned char sn9c2028_sof_marker[5] = - { 0xff, 0xff, 0x00, 0xc4, 0xc4 }; +static const unsigned char sn9c2028_sof_marker[] = { + 0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, + 0x00, + 0x00, /* seq */ + 0x00, + 0x00, + 0x00, /* avg luminance lower 8 bit */ + 0x00, /* avg luminance higher 8 bit */ +}; static unsigned char *sn9c2028_find_sof(struct gspca_dev *gspca_dev, unsigned char *m, int len) @@ -32,8 +39,13 @@ static unsigned char *sn9c2028_find_sof(struct gspca_dev *gspca_dev, /* Search for the SOF marker (fixed part) in the header */ for (i = 0; i < len; i++) { - if (m[i] == sn9c2028_sof_marker[sd->sof_read]) { + if ((m[i] == sn9c2028_sof_marker[sd->sof_read]) || + (sd->sof_read > 5)) { sd->sof_read++; + if (sd->sof_read == 11) + sd->avg_lum_l = m[i]; + if (sd->sof_read == 12) + sd->avg_lum = (m[i] << 8) + sd->avg_lum_l; if (sd->sof_read == sizeof(sn9c2028_sof_marker)) { PDEBUG(D_FRAM, "SOF found, bytes to analyze: %u." diff --git a/drivers/media/usb/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c index c69b45d7c..fd1c8706d 100644 --- a/drivers/media/usb/gspca/sonixj.c +++ b/drivers/media/usb/gspca/sonixj.c @@ -1789,7 +1789,7 @@ static u32 expo_adjust(struct gspca_dev *gspca_dev, if (expo > 0x03ff) expo = 0x03ff; - if (expo < 0x0001) + if (expo < 0x0001) expo = 0x0001; gainOm[3] = expo >> 2; i2c_w8(gspca_dev, gainOm); diff --git a/drivers/media/usb/gspca/stk014.c b/drivers/media/usb/gspca/stk014.c index b0c70fea7..d324d001e 100644 --- a/drivers/media/usb/gspca/stk014.c +++ b/drivers/media/usb/gspca/stk014.c @@ -276,7 +276,7 @@ static int sd_start(struct gspca_dev *gspca_dev) gspca_dev->usb_err = ret; goto out; } - reg_r(gspca_dev, 0x0630); + reg_r(gspca_dev, 0x0630); rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */ reg_r(gspca_dev, 0x0650); snd_val(gspca_dev, 0x000020, 0xffffffff); diff --git a/drivers/media/usb/gspca/xirlink_cit.c b/drivers/media/usb/gspca/xirlink_cit.c index a41aa7817..d5ed9d36c 100644 --- a/drivers/media/usb/gspca/xirlink_cit.c +++ b/drivers/media/usb/gspca/xirlink_cit.c @@ -1772,7 +1772,8 @@ static int cit_start_model2(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */ sd->sof_len = 2; break; - /* case VIDEOSIZE_352x240: */ +#if 0 + case VIDEOSIZE_352x240: cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */ cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */ cit_write_reg(gspca_dev, 0x001e, 0x0105); /* 320x240, 352x240 */ @@ -1780,6 +1781,7 @@ static int cit_start_model2(struct gspca_dev *gspca_dev) cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */ sd->sof_len = 2; break; +#endif case 352: /* 352x288 */ cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */ cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */ @@ -1853,13 +1855,15 @@ static int cit_start_model2(struct gspca_dev *gspca_dev) cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Another hardware setting */ clock_div = 8; break; - /* case VIDEOSIZE_352x240: */ +#if 0 + case VIDEOSIZE_352x240: /* This mode doesn't work as Windows programs it; changed to work */ cit_model2_Packet1(gspca_dev, 0x0014, 0x0009); /* Windows sets this to 8 */ cit_model2_Packet1(gspca_dev, 0x0016, 0x0003); /* Horizontal shift */ cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Windows sets this to 0x0045 */ clock_div = 10; break; +#endif case 352: /* 352x288 */ cit_model2_Packet1(gspca_dev, 0x0014, 0x0003); cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */ @@ -1906,9 +1910,11 @@ static int cit_start_model2(struct gspca_dev *gspca_dev) case 320: /* 320x240 */ cit_model2_Packet1(gspca_dev, 0x0026, 0x0044); break; - /* case VIDEOSIZE_352x240: */ +#if 0 + case VIDEOSIZE_352x240: cit_model2_Packet1(gspca_dev, 0x0026, 0x0046); break; +#endif case 352: /* 352x288 */ cit_model2_Packet1(gspca_dev, 0x0026, 0x0048); break; diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c index d3e1b6d8b..c5d8ee6fa 100644 --- a/drivers/media/usb/gspca/zc3xx.c +++ b/drivers/media/usb/gspca/zc3xx.c @@ -5942,23 +5942,23 @@ static void transfer_update(struct work_struct *work) reg07 = 0; good = 0; - for (;;) { + while (1) { msleep(100); /* To protect gspca_dev->usb_buf and gspca_dev->usb_err */ mutex_lock(&gspca_dev->usb_lock); #ifdef CONFIG_PM if (gspca_dev->frozen) - goto err; + break; #endif if (!gspca_dev->present || !gspca_dev->streaming) - goto err; + break; /* Bit 0 of register 11 indicates FIFO overflow */ gspca_dev->usb_err = 0; reg11 = reg_r(gspca_dev, 0x0011); if (gspca_dev->usb_err) - goto err; + break; change = reg11 & 0x01; if (change) { /* overflow */ @@ -5987,12 +5987,12 @@ static void transfer_update(struct work_struct *work) gspca_dev->usb_err = 0; reg_w(gspca_dev, reg07, 0x0007); if (gspca_dev->usb_err) - goto err; + break; } mutex_unlock(&gspca_dev->usb_lock); } - return; -err: + + /* Something went wrong. Unlock and return */ mutex_unlock(&gspca_dev->usb_lock); } @@ -6360,7 +6360,7 @@ static int zcxx_s_ctrl(struct v4l2_ctrl *ctrl) if (ctrl->val <= jpeg_qual[i]) break; } - if (i > 0 && i == qual && ctrl->val < jpeg_qual[i]) + if (i == ARRAY_SIZE(jpeg_qual) || (i > 0 && i == qual && ctrl->val < jpeg_qual[i])) i--; /* With high quality settings we need max bandwidth */ -- cgit v1.2.3-54-g00ecf