From 30c73d464a10bee4bb8375bb2ed8cc102c507bb7 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Mon, 27 Feb 2012 07:26:30 -0300 Subject: [media] gspca - zc3xx: Adjust the JPEG decompression tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the bridge register 08 defines the JPEG compression quality, it must be changed on JPEG quality change and also, the decompression tables must be adjusted when the register varies. [mchehab@redhat.com: replace a // comment by a /* */ one] Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 97 ++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 47 deletions(-) (limited to 'drivers/media/video/gspca/zc3xx.c') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index b9e15bb0328..c02fb31987c 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -34,7 +34,7 @@ MODULE_LICENSE("GPL"); static int force_sensor = -1; -#define QUANT_VAL 1 /* quantization table */ +#define REG08_DEF 3 /* default JPEG compression (70%) */ #include "zc3xx-reg.h" /* controls */ @@ -57,10 +57,7 @@ struct sd { struct gspca_ctrl ctrls[NCTRLS]; - u8 quality; /* image quality */ -#define QUALITY_MIN 50 -#define QUALITY_MAX 80 -#define QUALITY_DEF 70 + u8 reg08; /* webcam compression quality */ u8 bridge; u8 sensor; /* Type of image sensor chip */ @@ -229,6 +226,9 @@ static const struct v4l2_pix_format sif_mode[] = { .priv = 0}, }; +/* bridge reg08 -> JPEG quality conversion table */ +static u8 jpeg_qual[] = {40, 50, 60, 70, /*80*/}; + /* usb exchanges */ struct usb_action { u8 req; @@ -5925,32 +5925,17 @@ static void setexposure(struct gspca_dev *gspca_dev) static void setquality(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - u8 frxt; + s8 reg07; + reg07 = 0; switch (sd->sensor) { - case SENSOR_ADCM2700: - case SENSOR_GC0305: - case SENSOR_HV7131B: - case SENSOR_HV7131R: case SENSOR_OV7620: - case SENSOR_PAS202B: - case SENSOR_PO2030: - return; + reg07 = 0x30; + break; } -/*fixme: is it really 0008 0007 0018 for all other sensors? */ - reg_w(gspca_dev, QUANT_VAL, 0x0008); - frxt = 0x30; - reg_w(gspca_dev, frxt, 0x0007); -#if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2 - frxt = 0xff; -#elif QUANT_VAL == 3 - frxt = 0xf0; -#elif QUANT_VAL == 4 - frxt = 0xe0; -#else - frxt = 0x20; -#endif - reg_w(gspca_dev, frxt, 0x0018); + reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); + if (reg07 != 0) + reg_w(gspca_dev, reg07, 0x0007); } /* Matches the sensor's internal frame rate to the lighting frequency. @@ -6411,7 +6396,7 @@ static int sd_config(struct gspca_dev *gspca_dev, sd->sensor = id->driver_info; gspca_dev->cam.ctrls = sd->ctrls; - sd->quality = QUALITY_DEF; + sd->reg08 = REG08_DEF; return 0; } @@ -6464,6 +6449,27 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_PO2030] = 1, [SENSOR_TAS5130C] = 1, }; + static const u8 reg08_tb[SENSOR_MAX] = { + [SENSOR_ADCM2700] = 1, + [SENSOR_CS2102] = 3, +/* [SENSOR_CS2102K] = 3, */ + [SENSOR_GC0303] = 2, + [SENSOR_GC0305] = 3, + [SENSOR_HDCS2020] = 1, + [SENSOR_HV7131B] = 3, + [SENSOR_HV7131R] = 3, + [SENSOR_ICM105A] = 3, + [SENSOR_MC501CB] = 3, + [SENSOR_MT9V111_1] = 3, + [SENSOR_MT9V111_3] = 3, + [SENSOR_OV7620] = 1, + [SENSOR_OV7630C] = 3, + [SENSOR_PAS106] = 3, + [SENSOR_PAS202B] = 3, + [SENSOR_PB0330] = 3, + [SENSOR_PO2030] = 2, + [SENSOR_TAS5130C] = 3, + }; sensor = zcxx_probeSensor(gspca_dev); if (sensor >= 0) @@ -6616,6 +6622,7 @@ static int sd_init(struct gspca_dev *gspca_dev) } sd->ctrls[GAMMA].def = gamma[sd->sensor]; + sd->reg08 = reg08_tb[sd->sensor]; switch (sd->sensor) { case SENSOR_HV7131R: @@ -6685,7 +6692,6 @@ static int sd_start(struct gspca_dev *gspca_dev) /* create the JPEG header */ jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 0x21); /* JPEG 422 */ - jpeg_set_qual(sd->jpeg_hdr, sd->quality); mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; switch (sd->sensor) { @@ -6761,10 +6767,9 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_r(gspca_dev, 0x0180); /* from win */ reg_w(gspca_dev, 0x00, 0x0180); break; - default: - setquality(gspca_dev); - break; } + setquality(gspca_dev); + jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08]); setlightfreq(gspca_dev); switch (sd->sensor) { @@ -6802,13 +6807,6 @@ static int sd_start(struct gspca_dev *gspca_dev) } setautogain(gspca_dev); - switch (sd->sensor) { - case SENSOR_PO2030: - msleep(50); - reg_w(gspca_dev, 0x00, 0x0007); /* (from win traces) */ - reg_w(gspca_dev, 0x02, ZC3XX_R008_CLOCKSETTING); - break; - } return gspca_dev->usb_err; } @@ -6897,15 +6895,20 @@ static int sd_set_jcomp(struct gspca_dev *gspca_dev, struct v4l2_jpegcompression *jcomp) { struct sd *sd = (struct sd *) gspca_dev; + int i; - if (jcomp->quality < QUALITY_MIN) - sd->quality = QUALITY_MIN; - else if (jcomp->quality > QUALITY_MAX) - sd->quality = QUALITY_MAX; - else - sd->quality = jcomp->quality; + for (i = 0; i < ARRAY_SIZE(jpeg_qual) - 1; i++) { + if (jcomp->quality <= jpeg_qual[i]) + break; + } + if (i > 0 + && i == sd->reg08 + && jcomp->quality < jpeg_qual[sd->reg08]) + i--; + sd->reg08 = i; + jcomp->quality = jpeg_qual[i]; if (gspca_dev->streaming) - jpeg_set_qual(sd->jpeg_hdr, sd->quality); + jpeg_set_qual(sd->jpeg_hdr, jcomp->quality); return gspca_dev->usb_err; } @@ -6915,7 +6918,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; memset(jcomp, 0, sizeof *jcomp); - jcomp->quality = sd->quality; + jcomp->quality = jpeg_qual[sd->reg08]; jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT; return 0; -- cgit v1.2.3-70-g09d2 From f1801904eeb79f46e7854e4d18c7107160a16093 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Mon, 27 Feb 2012 07:48:32 -0300 Subject: [media] gspca - zc3xx: Do automatic transfer control for hv7131r and pas202b MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bridge register 11 reports the current transfer status. This value is used to know about a possible overflow and to adjust the transfer parameters (registers 07 and 08). Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 134 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) (limited to 'drivers/media/video/gspca/zc3xx.c') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index c02fb31987c..d6175f5d105 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -57,6 +57,9 @@ struct sd { struct gspca_ctrl ctrls[NCTRLS]; + struct work_struct work; + struct workqueue_struct *work_thread; + u8 reg08; /* webcam compression quality */ u8 bridge; @@ -5932,6 +5935,9 @@ static void setquality(struct gspca_dev *gspca_dev) case SENSOR_OV7620: reg07 = 0x30; break; + case SENSOR_HV7131R: + case SENSOR_PAS202B: + return; /* done by work queue */ } reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); if (reg07 != 0) @@ -6069,6 +6075,114 @@ static void setautogain(struct gspca_dev *gspca_dev) reg_w(gspca_dev, autoval, 0x0180); } +/* update the transfer parameters */ +/* This function is executed from a work queue. */ +/* The exact use of the bridge registers 07 and 08 is not known. + * The following algorithm has been adapted from ms-win traces */ +static void transfer_update(struct work_struct *work) +{ + struct sd *sd = container_of(work, struct sd, work); + struct gspca_dev *gspca_dev = &sd->gspca_dev; + int change, good; + u8 reg07, reg11; + + /* synchronize with the main driver and initialize the registers */ + mutex_lock(&gspca_dev->usb_lock); + reg07 = 0; /* max */ + reg_w(gspca_dev, reg07, 0x0007); + reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); + mutex_unlock(&gspca_dev->usb_lock); + + good = 0; + for (;;) { + msleep(100); + + /* get the transfer status */ + /* the bit 0 of the bridge register 11 indicates overflow */ + mutex_lock(&gspca_dev->usb_lock); + if (!gspca_dev->present || !gspca_dev->streaming) + goto err; + reg11 = reg_r(gspca_dev, 0x0011); + if (gspca_dev->usb_err < 0 + || !gspca_dev->present || !gspca_dev->streaming) + goto err; + + change = reg11 & 0x01; + if (change) { /* overflow */ + switch (reg07) { + case 0: /* max */ + reg07 = sd->sensor == SENSOR_HV7131R + ? 0x30 : 0x32; + if (sd->reg08 != 0) { + change = 3; + sd->reg08--; + } + break; + case 0x32: + reg07 -= 4; + break; + default: + reg07 -= 2; + break; + case 2: + change = 0; /* already min */ + break; + } + good = 0; + } else { /* no overflow */ + if (reg07 != 0) { /* if not max */ + good++; + if (good >= 10) { + good = 0; + change = 1; + reg07 += 2; + switch (reg07) { + case 0x30: + if (sd->sensor == SENSOR_PAS202B) + reg07 += 2; + break; + case 0x32: + case 0x34: + reg07 = 0; + break; + } + } + } else { /* reg07 max */ + if (sd->reg08 < sizeof jpeg_qual - 1) { + good++; + if (good > 10) { + sd->reg08++; + change = 2; + } + } + } + } + if (change) { + if (change & 1) { + reg_w(gspca_dev, reg07, 0x0007); + if (gspca_dev->usb_err < 0 + || !gspca_dev->present + || !gspca_dev->streaming) + goto err; + } + if (change & 2) { + reg_w(gspca_dev, sd->reg08, + ZC3XX_R008_CLOCKSETTING); + if (gspca_dev->usb_err < 0 + || !gspca_dev->present + || !gspca_dev->streaming) + goto err; + jpeg_set_qual(sd->jpeg_hdr, + jpeg_qual[sd->reg08]); + } + } + mutex_unlock(&gspca_dev->usb_lock); + } + return; +err: + mutex_unlock(&gspca_dev->usb_lock); +} + static void send_unknown(struct gspca_dev *gspca_dev, int sensor) { reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */ @@ -6398,6 +6512,8 @@ static int sd_config(struct gspca_dev *gspca_dev, gspca_dev->cam.ctrls = sd->ctrls; sd->reg08 = REG08_DEF; + INIT_WORK(&sd->work, transfer_update); + return 0; } @@ -6807,6 +6923,18 @@ static int sd_start(struct gspca_dev *gspca_dev) } setautogain(gspca_dev); + + /* start the transfer update thread if needed */ + if (gspca_dev->usb_err >= 0) { + switch (sd->sensor) { + case SENSOR_HV7131R: + case SENSOR_PAS202B: + sd->work_thread = create_singlethread_workqueue(MODULE_NAME); + queue_work(sd->work_thread, &sd->work); + break; + } + } + return gspca_dev->usb_err; } @@ -6815,6 +6943,12 @@ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (sd->work_thread != NULL) { + mutex_unlock(&gspca_dev->usb_lock); + destroy_workqueue(sd->work_thread); + mutex_lock(&gspca_dev->usb_lock); + sd->work_thread = NULL; + } if (!gspca_dev->present) return; send_unknown(gspca_dev, sd->sensor); -- cgit v1.2.3-70-g09d2 From 1b3b21206b7506a1abdd411419bc871438efc89c Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Mon, 27 Feb 2012 07:51:09 -0300 Subject: [media] gspca - zc3xx: Remove the low level traces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The low level traces are better done by usbmon. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 48 +++++++++++---------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) (limited to 'drivers/media/video/gspca/zc3xx.c') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index d6175f5d105..4ad1cd1f95e 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -5643,7 +5643,7 @@ static const struct usb_action gc0303_NoFlikerScale[] = { {} }; -static u8 reg_r_i(struct gspca_dev *gspca_dev, +static u8 reg_r(struct gspca_dev *gspca_dev, u16 index) { int ret; @@ -5658,24 +5658,14 @@ static u8 reg_r_i(struct gspca_dev *gspca_dev, index, gspca_dev->usb_buf, 1, 500); if (ret < 0) { - pr_err("reg_r_i err %d\n", ret); + pr_err("reg_r err %d\n", ret); gspca_dev->usb_err = ret; return 0; } return gspca_dev->usb_buf[0]; } -static u8 reg_r(struct gspca_dev *gspca_dev, - u16 index) -{ - u8 ret; - - ret = reg_r_i(gspca_dev, index); - PDEBUG(D_USBI, "reg r [%04x] -> %02x", index, ret); - return ret; -} - -static void reg_w_i(struct gspca_dev *gspca_dev, +static void reg_w(struct gspca_dev *gspca_dev, u8 value, u16 index) { @@ -5695,14 +5685,6 @@ static void reg_w_i(struct gspca_dev *gspca_dev, } } -static void reg_w(struct gspca_dev *gspca_dev, - u8 value, - u16 index) -{ - PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value); - reg_w_i(gspca_dev, value, index); -} - static u16 i2c_read(struct gspca_dev *gspca_dev, u8 reg) { @@ -5711,16 +5693,14 @@ static u16 i2c_read(struct gspca_dev *gspca_dev, if (gspca_dev->usb_err < 0) return 0; - reg_w_i(gspca_dev, reg, 0x0092); - reg_w_i(gspca_dev, 0x02, 0x0090); /* <- read command */ + reg_w(gspca_dev, reg, 0x0092); + reg_w(gspca_dev, 0x02, 0x0090); /* <- read command */ msleep(20); - retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ + retbyte = reg_r(gspca_dev, 0x0091); /* read status */ if (retbyte != 0x00) pr_err("i2c_r status error %02x\n", retbyte); - retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ - retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */ - PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)", - reg, retval, retbyte); + retval = reg_r(gspca_dev, 0x0095); /* read Lowbyte */ + retval |= reg_r(gspca_dev, 0x0096) << 8; /* read Hightbyte */ return retval; } @@ -5733,16 +5713,14 @@ static u8 i2c_write(struct gspca_dev *gspca_dev, if (gspca_dev->usb_err < 0) return 0; - reg_w_i(gspca_dev, reg, 0x92); - reg_w_i(gspca_dev, valL, 0x93); - reg_w_i(gspca_dev, valH, 0x94); - reg_w_i(gspca_dev, 0x01, 0x90); /* <- write command */ + reg_w(gspca_dev, reg, 0x92); + reg_w(gspca_dev, valL, 0x93); + reg_w(gspca_dev, valH, 0x94); + reg_w(gspca_dev, 0x01, 0x90); /* <- write command */ msleep(1); - retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ + retbyte = reg_r(gspca_dev, 0x0091); /* read status */ if (retbyte != 0x00) pr_err("i2c_w status error %02x\n", retbyte); - PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)", - reg, valH, valL, retbyte); return retbyte; } -- cgit v1.2.3-70-g09d2 From 0b74e2c460a4a3977f40c40580f1d7af4f976447 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Mon, 27 Feb 2012 08:26:05 -0300 Subject: [media] gspca - zc3xx: Cleanup source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - copyright change - use the kbuild module name for messages - remove useless comments Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/media/video/gspca/zc3xx.c') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 4ad1cd1f95e..2ff96ca2cee 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -1,7 +1,7 @@ /* - * Z-Star/Vimicro zc301/zc302p/vc30x library + * Z-Star/Vimicro zc301/zc302p/vc30x driver * - * Copyright (C) 2009-2011 Jean-Francois Moine + * Copyright (C) 2009-2012 Jean-Francois Moine * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr * * This program is free software; you can redistribute it and/or modify @@ -21,8 +21,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define MODULE_NAME "zc3xx" - #include #include "gspca.h" #include "jpeg.h" @@ -3897,7 +3895,6 @@ static const struct usb_action pas106b_Initial[] = { /* 352x288 */ /* Gains */ {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, - {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN}, {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* Auto correction */ {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, @@ -6628,7 +6625,6 @@ static int sd_init(struct gspca_dev *gspca_dev) case 0x0e: PDEBUG(D_PROBE, "Find Sensor PAS202B"); sd->sensor = SENSOR_PAS202B; -/* sd->sharpness = 1; */ break; case 0x0f: PDEBUG(D_PROBE, "Find Sensor PAS106"); @@ -6907,7 +6903,8 @@ static int sd_start(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_HV7131R: case SENSOR_PAS202B: - sd->work_thread = create_singlethread_workqueue(MODULE_NAME); + sd->work_thread = + create_singlethread_workqueue(KBUILD_MODNAME); queue_work(sd->work_thread, &sd->work); break; } @@ -7053,7 +7050,7 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, #endif static const struct sd_desc sd_desc = { - .name = MODULE_NAME, + .name = KBUILD_MODNAME, .ctrls = sd_ctrls, .nctrls = ARRAY_SIZE(sd_ctrls), .config = sd_config, @@ -7138,7 +7135,7 @@ static int sd_probe(struct usb_interface *intf, /* USB driver */ static struct usb_driver sd_driver = { - .name = MODULE_NAME, + .name = KBUILD_MODNAME, .id_table = device_table, .probe = sd_probe, .disconnect = gspca_disconnect, -- cgit v1.2.3-70-g09d2 From 6028c3268404c1323da09b1dc5bbff56b79364a1 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Mon, 27 Feb 2012 08:37:37 -0300 Subject: [media] gspca - zc3xx: Fix bad sensor values when changing autogain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The setexposure added in commit 590f21680616 works only for the sensor hv7131r, but it is called for all sensors when changing the autogain. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/media/video/gspca/zc3xx.c') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 2ff96ca2cee..09100061152 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -5884,6 +5884,8 @@ static void getexposure(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (sd->sensor != SENSOR_HV7131R) + return; sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9) | (i2c_read(gspca_dev, 0x26) << 1) | (i2c_read(gspca_dev, 0x27) >> 7); @@ -5894,6 +5896,8 @@ static void setexposure(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int val; + if (sd->sensor != SENSOR_HV7131R) + return; val = sd->ctrls[EXPOSURE].val; i2c_write(gspca_dev, 0x25, val >> 9, 0x00); i2c_write(gspca_dev, 0x26, val >> 1, 0x00); -- cgit v1.2.3-70-g09d2 From a2d2b25ce623757a87b35ef336d2d2c3b0a6fa13 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Mon, 27 Feb 2012 08:49:49 -0300 Subject: [media] gspca - zc3xx: Set the exposure at start of hv7131r MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The exposure was not set when autogain was set. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/media/video/gspca/zc3xx.c') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 09100061152..c10bdb42227 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6875,8 +6875,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x40, 0x0117); break; case SENSOR_HV7131R: - if (!sd->ctrls[AUTOGAIN].val) - setexposure(gspca_dev); + setexposure(gspca_dev); reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); break; case SENSOR_GC0305: -- cgit v1.2.3-70-g09d2 From cd7f98fcd8573bb29f768f70c58e3d1f8057f7e3 Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Fri, 16 Mar 2012 06:47:23 -0300 Subject: [media] gspca - zc3xx: Add V4L2_CID_JPEG_COMPRESSION_QUALITY control support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch is adapted from Sylwester's patch proposed on 2012/02/22. The JPEG compression control does not work with the autoquality done for the sensors hv7131r and pas202b. Acked-by: Sylwester Nawrocki Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 45 +++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 7 deletions(-) (limited to 'drivers/media/video/gspca/zc3xx.c') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index c10bdb42227..7bbdf8331a9 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -44,6 +44,7 @@ enum e_ctrl { AUTOGAIN, LIGHTFREQ, SHARPNESS, + QUALITY, NCTRLS /* number of controls */ }; @@ -99,6 +100,7 @@ static void setexposure(struct gspca_dev *gspca_dev); static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static void setlightfreq(struct gspca_dev *gspca_dev); static void setsharpness(struct gspca_dev *gspca_dev); +static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val); static const struct ctrl sd_ctrls[NCTRLS] = { [BRIGHTNESS] = { @@ -186,6 +188,18 @@ static const struct ctrl sd_ctrls[NCTRLS] = { }, .set_control = setsharpness }, +[QUALITY] = { + { + .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Compression Quality", + .minimum = 40, + .maximum = 70, + .step = 1, + .default_value = 70 /* updated in sd_init() */ + }, + .set = sd_setquality + }, }; static const struct v4l2_pix_format vga_mode[] = { @@ -6151,6 +6165,7 @@ static void transfer_update(struct work_struct *work) || !gspca_dev->present || !gspca_dev->streaming) goto err; + sd->ctrls[QUALITY].val = jpeg_qual[sd->reg08]; jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08]); } @@ -6717,13 +6732,20 @@ static int sd_init(struct gspca_dev *gspca_dev) sd->ctrls[GAMMA].def = gamma[sd->sensor]; sd->reg08 = reg08_tb[sd->sensor]; + sd->ctrls[QUALITY].def = jpeg_qual[sd->reg08]; + sd->ctrls[QUALITY].min = jpeg_qual[0]; + sd->ctrls[QUALITY].max = jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1]; switch (sd->sensor) { case SENSOR_HV7131R: + gspca_dev->ctrl_dis = (1 << QUALITY); break; case SENSOR_OV7630C: gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE); break; + case SENSOR_PAS202B: + gspca_dev->ctrl_dis = (1 << QUALITY) | (1 << EXPOSURE); + break; default: gspca_dev->ctrl_dis = (1 << EXPOSURE); break; @@ -7003,24 +7025,33 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, return -EINVAL; } -static int sd_set_jcomp(struct gspca_dev *gspca_dev, - struct v4l2_jpegcompression *jcomp) +static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val) { struct sd *sd = (struct sd *) gspca_dev; int i; for (i = 0; i < ARRAY_SIZE(jpeg_qual) - 1; i++) { - if (jcomp->quality <= jpeg_qual[i]) + if (val <= jpeg_qual[i]) break; } if (i > 0 && i == sd->reg08 - && jcomp->quality < jpeg_qual[sd->reg08]) + && val < jpeg_qual[sd->reg08]) i--; sd->reg08 = i; - jcomp->quality = jpeg_qual[i]; + sd->ctrls[QUALITY].val = jpeg_qual[i]; if (gspca_dev->streaming) - jpeg_set_qual(sd->jpeg_hdr, jcomp->quality); + jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); + return gspca_dev->usb_err; +} + +static int sd_set_jcomp(struct gspca_dev *gspca_dev, + struct v4l2_jpegcompression *jcomp) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd_setquality(gspca_dev, jcomp->quality); + jcomp->quality = sd->ctrls[QUALITY].val; return gspca_dev->usb_err; } @@ -7030,7 +7061,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; memset(jcomp, 0, sizeof *jcomp); - jcomp->quality = jpeg_qual[sd->reg08]; + jcomp->quality = sd->ctrls[QUALITY].val; jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT; return 0; -- cgit v1.2.3-70-g09d2 From a2816edaaca2586cac66270844614586810f53ea Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Fri, 16 Mar 2012 07:30:03 -0300 Subject: [media] gspca - zc3xx: Lack of register 08 value for sensor cs2102k MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The line defining the value of the register 08 for the sensor cs2102k was commented by error in commit 30c73d46. Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video/gspca/zc3xx.c') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 7bbdf8331a9..7d9a4f1be9d 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -6562,7 +6562,7 @@ static int sd_init(struct gspca_dev *gspca_dev) static const u8 reg08_tb[SENSOR_MAX] = { [SENSOR_ADCM2700] = 1, [SENSOR_CS2102] = 3, -/* [SENSOR_CS2102K] = 3, */ + [SENSOR_CS2102K] = 3, [SENSOR_GC0303] = 2, [SENSOR_GC0305] = 3, [SENSOR_HDCS2020] = 1, -- cgit v1.2.3-70-g09d2