diff options
Diffstat (limited to 'drivers/media/video/gspca/zc3xx.c')
-rw-r--r-- | drivers/media/video/gspca/zc3xx.c | 128 |
1 files changed, 97 insertions, 31 deletions
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 47236a58bf33..fa164e861cde 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 * - * Copyright (C) 2009-2010 Jean-Francois Moine <http://moinejf.free.fr> + * Copyright (C) 2009-2011 Jean-Francois Moine <http://moinejf.free.fr> * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr * * This program is free software; you can redistribute it and/or modify @@ -39,6 +39,7 @@ static int force_sensor = -1; enum e_ctrl { BRIGHTNESS, CONTRAST, + EXPOSURE, GAMMA, AUTOGAIN, LIGHTFREQ, @@ -46,6 +47,8 @@ enum e_ctrl { NCTRLS /* number of controls */ }; +#define AUTOGAIN_DEF 1 + /* specific webcam descriptor */ struct sd { struct gspca_dev gspca_dev; /* !! must be the first item */ @@ -73,7 +76,7 @@ enum sensors { SENSOR_CS2102K, SENSOR_GC0303, SENSOR_GC0305, - SENSOR_HDCS2020b, + SENSOR_HDCS2020, SENSOR_HV7131B, SENSOR_HV7131R, SENSOR_ICM105A, @@ -92,7 +95,8 @@ enum sensors { /* V4L2 controls supported by the driver */ static void setcontrast(struct gspca_dev *gspca_dev); -static void setautogain(struct gspca_dev *gspca_dev); +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); @@ -121,6 +125,18 @@ static const struct ctrl sd_ctrls[NCTRLS] = { }, .set_control = setcontrast }, +[EXPOSURE] = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0x30d, + .maximum = 0x493e, + .step = 1, + .default_value = 0x927 + }, + .set_control = setexposure + }, [GAMMA] = { { .id = V4L2_CID_GAMMA, @@ -141,9 +157,10 @@ static const struct ctrl sd_ctrls[NCTRLS] = { .minimum = 0, .maximum = 1, .step = 1, - .default_value = 1, + .default_value = AUTOGAIN_DEF, + .flags = V4L2_CTRL_FLAG_UPDATE }, - .set_control = setautogain + .set = sd_setautogain }, [LIGHTFREQ] = { { @@ -1498,7 +1515,7 @@ static const struct usb_action gc0305_NoFliker[] = { {} }; -static const struct usb_action hdcs2020b_InitialScale[] = { +static const struct usb_action hdcs2020_InitialScale[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* qtable 0x05 */ @@ -1630,7 +1647,7 @@ static const struct usb_action hdcs2020b_InitialScale[] = { {0xa0, 0x40, ZC3XX_R118_BGAIN}, {} }; -static const struct usb_action hdcs2020b_Initial[] = { +static const struct usb_action hdcs2020_Initial[] = { {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, @@ -1758,7 +1775,7 @@ static const struct usb_action hdcs2020b_Initial[] = { {0xa0, 0x40, ZC3XX_R118_BGAIN}, {} }; -static const struct usb_action hdcs2020b_50HZ[] = { +static const struct usb_action hdcs2020_50HZ[] = { {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ {0xaa, 0x13, 0x0018}, /* 00,13,18,aa */ {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */ @@ -1779,7 +1796,7 @@ static const struct usb_action hdcs2020b_50HZ[] = { {0xa0, 0x2f, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2f,cc */ {} }; -static const struct usb_action hdcs2020b_60HZ[] = { +static const struct usb_action hdcs2020_60HZ[] = { {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ {0xaa, 0x13, 0x0031}, /* 00,13,31,aa */ {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */ @@ -1800,7 +1817,7 @@ static const struct usb_action hdcs2020b_60HZ[] = { {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */ {} }; -static const struct usb_action hdcs2020b_NoFliker[] = { +static const struct usb_action hdcs2020_NoFliker[] = { {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ {0xaa, 0x13, 0x0010}, /* 00,13,10,aa */ {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */ @@ -2126,7 +2143,6 @@ static const struct usb_action hv7131r_Initial[] = { {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, - {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, @@ -2878,7 +2894,7 @@ static const struct usb_action mc501cb_Initial[] = { {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */ {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */ {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */ - {0xaa, 0xa0, ZC3XX_R01A_LASTFRAMESTATE}, /* 00,a0,1a,aa */ + {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */ {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */ {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */ {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */ @@ -2998,7 +3014,7 @@ static const struct usb_action mc501cb_InitialScale[] = { /* 320x240 */ {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */ {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */ {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */ - {0xaa, 0xa0, ZC3XX_R01A_LASTFRAMESTATE}, /* 00,a0,1a,aa */ + {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */ {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */ {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */ {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */ @@ -3310,7 +3326,7 @@ static const struct usb_action ov7620_50HZ[] = { {0xaa, 0x10, 0x0082}, /* 00,10,82,aa */ {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */ /* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc - if mode0 (640x480) */ + * if mode0 (640x480) */ {} }; static const struct usb_action ov7620_60HZ[] = { @@ -5828,7 +5844,7 @@ static void setmatrix(struct gspca_dev *gspca_dev) [SENSOR_CS2102K] = NULL, [SENSOR_GC0303] = gc0303_matrix, [SENSOR_GC0305] = gc0305_matrix, - [SENSOR_HDCS2020b] = NULL, + [SENSOR_HDCS2020] = NULL, [SENSOR_HV7131B] = NULL, [SENSOR_HV7131R] = po2030_matrix, [SENSOR_ICM105A] = po2030_matrix, @@ -5927,6 +5943,26 @@ static void setcontrast(struct gspca_dev *gspca_dev) reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */ } +static void getexposure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9) + | (i2c_read(gspca_dev, 0x26) << 1) + | (i2c_read(gspca_dev, 0x27) >> 7); +} + +static void setexposure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + int val; + + val = sd->ctrls[EXPOSURE].val; + i2c_write(gspca_dev, 0x25, val >> 9, 0x00); + i2c_write(gspca_dev, 0x26, val >> 1, 0x00); + i2c_write(gspca_dev, 0x27, val << 7, 0x00); +} + static void setquality(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -5990,10 +6026,10 @@ static void setlightfreq(struct gspca_dev *gspca_dev) {gc0305_NoFliker, gc0305_NoFliker, gc0305_50HZ, gc0305_50HZ, gc0305_60HZ, gc0305_60HZ}, - [SENSOR_HDCS2020b] = - {hdcs2020b_NoFliker, hdcs2020b_NoFliker, - hdcs2020b_50HZ, hdcs2020b_50HZ, - hdcs2020b_60HZ, hdcs2020b_60HZ}, + [SENSOR_HDCS2020] = + {hdcs2020_NoFliker, hdcs2020_NoFliker, + hdcs2020_50HZ, hdcs2020_50HZ, + hdcs2020_60HZ, hdcs2020_60HZ}, [SENSOR_HV7131B] = {hv7131b_NoFliker, hv7131b_NoFlikerScale, hv7131b_50HZ, hv7131b_50HZScale, @@ -6091,7 +6127,7 @@ static void setautogain(struct gspca_dev *gspca_dev) static void send_unknown(struct gspca_dev *gspca_dev, int sensor) { - reg_w(gspca_dev, 0x01, 0x0000); /* led off */ + reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */ switch (sensor) { case SENSOR_PAS106: reg_w(gspca_dev, 0x03, 0x003a); @@ -6310,6 +6346,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) return 0x0a; /* PB0330 */ } + /* probe gc0303 / gc0305 */ reg_w(gspca_dev, 0x01, 0x0000); reg_w(gspca_dev, 0x01, 0x0001); reg_w(gspca_dev, 0x98, 0x008b); @@ -6414,6 +6451,10 @@ static int sd_config(struct gspca_dev *gspca_dev, gspca_dev->cam.ctrls = sd->ctrls; sd->quality = QUALITY_DEF; + /* if USB 1.1, let some bandwidth for the audio device */ + if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH) + gspca_dev->nbalt--; + return 0; } @@ -6429,7 +6470,7 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_CS2102K] = 5, [SENSOR_GC0303] = 3, [SENSOR_GC0305] = 4, - [SENSOR_HDCS2020b] = 4, + [SENSOR_HDCS2020] = 4, [SENSOR_HV7131B] = 4, [SENSOR_HV7131R] = 4, [SENSOR_ICM105A] = 4, @@ -6450,7 +6491,7 @@ static int sd_init(struct gspca_dev *gspca_dev) [SENSOR_CS2102K] = 1, [SENSOR_GC0303] = 1, [SENSOR_GC0305] = 1, - [SENSOR_HDCS2020b] = 1, + [SENSOR_HDCS2020] = 1, [SENSOR_HV7131B] = 1, [SENSOR_HV7131R] = 1, [SENSOR_ICM105A] = 1, @@ -6513,8 +6554,8 @@ static int sd_init(struct gspca_dev *gspca_dev) sd->sensor = SENSOR_CS2102; break; case 0x08: - PDEBUG(D_PROBE, "Find Sensor HDCS2020(b)"); - sd->sensor = SENSOR_HDCS2020b; + PDEBUG(D_PROBE, "Find Sensor HDCS2020"); + sd->sensor = SENSOR_HDCS2020; break; case 0x0a: PDEBUG(D_PROBE, @@ -6619,10 +6660,19 @@ static int sd_init(struct gspca_dev *gspca_dev) sd->ctrls[GAMMA].def = gamma[sd->sensor]; switch (sd->sensor) { + case SENSOR_HV7131R: + break; case SENSOR_OV7630C: - gspca_dev->ctrl_dis = (1 << LIGHTFREQ); + gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE); + break; + default: + gspca_dev->ctrl_dis = (1 << EXPOSURE); break; } +#if AUTOGAIN_DEF + if (sd->ctrls[AUTOGAIN].val) + gspca_dev->ctrl_inac = (1 << EXPOSURE); +#endif /* switch off the led */ reg_w(gspca_dev, 0x01, 0x0000); @@ -6644,8 +6694,8 @@ static int sd_start(struct gspca_dev *gspca_dev) {gc0303_Initial, gc0303_InitialScale}, [SENSOR_GC0305] = {gc0305_Initial, gc0305_InitialScale}, - [SENSOR_HDCS2020b] = - {hdcs2020b_Initial, hdcs2020b_InitialScale}, + [SENSOR_HDCS2020] = + {hdcs2020_Initial, hdcs2020_InitialScale}, [SENSOR_HV7131B] = {hv7131b_Initial, hv7131b_InitialScale}, [SENSOR_HV7131R] = @@ -6739,7 +6789,7 @@ static int sd_start(struct gspca_dev *gspca_dev) /* set the gamma tables when not set */ switch (sd->sensor) { case SENSOR_CS2102K: /* gamma set in xxx_Initial */ - case SENSOR_HDCS2020b: + case SENSOR_HDCS2020: case SENSOR_OV7630C: break; default: @@ -6768,9 +6818,8 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x40, 0x0117); break; case SENSOR_HV7131R: - i2c_write(gspca_dev, 0x25, 0x04, 0x00); /* exposure */ - i2c_write(gspca_dev, 0x26, 0x93, 0x00); - i2c_write(gspca_dev, 0x27, 0xe0, 0x00); + if (!sd->ctrls[AUTOGAIN].val) + setexposure(gspca_dev); reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); break; case SENSOR_GC0305: @@ -6848,6 +6897,23 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, gspca_frame_add(gspca_dev, INTER_PACKET, data, len); } +static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->ctrls[AUTOGAIN].val = val; + if (val) { + gspca_dev->ctrl_inac |= (1 << EXPOSURE); + } else { + gspca_dev->ctrl_inac &= ~(1 << EXPOSURE); + if (gspca_dev->streaming) + getexposure(gspca_dev); + } + if (gspca_dev->streaming) + setautogain(gspca_dev); + return gspca_dev->usb_err; +} + static int sd_querymenu(struct gspca_dev *gspca_dev, struct v4l2_querymenu *menu) { |