diff options
Diffstat (limited to 'drivers/media/video/gspca/zc3xx.c')
-rw-r--r-- | drivers/media/video/gspca/zc3xx.c | 328 |
1 files changed, 237 insertions, 91 deletions
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index b9e15bb0328b..7d9a4f1be9dc 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Z-Star/Vimicro zc301/zc302p/vc30x library | 2 | * Z-Star/Vimicro zc301/zc302p/vc30x driver |
3 | * | 3 | * |
4 | * Copyright (C) 2009-2011 Jean-Francois Moine <http://moinejf.free.fr> | 4 | * Copyright (C) 2009-2012 Jean-Francois Moine <http://moinejf.free.fr> |
5 | * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr | 5 | * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -21,8 +21,6 @@ | |||
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
23 | 23 | ||
24 | #define MODULE_NAME "zc3xx" | ||
25 | |||
26 | #include <linux/input.h> | 24 | #include <linux/input.h> |
27 | #include "gspca.h" | 25 | #include "gspca.h" |
28 | #include "jpeg.h" | 26 | #include "jpeg.h" |
@@ -34,7 +32,7 @@ MODULE_LICENSE("GPL"); | |||
34 | 32 | ||
35 | static int force_sensor = -1; | 33 | static int force_sensor = -1; |
36 | 34 | ||
37 | #define QUANT_VAL 1 /* quantization table */ | 35 | #define REG08_DEF 3 /* default JPEG compression (70%) */ |
38 | #include "zc3xx-reg.h" | 36 | #include "zc3xx-reg.h" |
39 | 37 | ||
40 | /* controls */ | 38 | /* controls */ |
@@ -46,6 +44,7 @@ enum e_ctrl { | |||
46 | AUTOGAIN, | 44 | AUTOGAIN, |
47 | LIGHTFREQ, | 45 | LIGHTFREQ, |
48 | SHARPNESS, | 46 | SHARPNESS, |
47 | QUALITY, | ||
49 | NCTRLS /* number of controls */ | 48 | NCTRLS /* number of controls */ |
50 | }; | 49 | }; |
51 | 50 | ||
@@ -57,10 +56,10 @@ struct sd { | |||
57 | 56 | ||
58 | struct gspca_ctrl ctrls[NCTRLS]; | 57 | struct gspca_ctrl ctrls[NCTRLS]; |
59 | 58 | ||
60 | u8 quality; /* image quality */ | 59 | struct work_struct work; |
61 | #define QUALITY_MIN 50 | 60 | struct workqueue_struct *work_thread; |
62 | #define QUALITY_MAX 80 | 61 | |
63 | #define QUALITY_DEF 70 | 62 | u8 reg08; /* webcam compression quality */ |
64 | 63 | ||
65 | u8 bridge; | 64 | u8 bridge; |
66 | u8 sensor; /* Type of image sensor chip */ | 65 | u8 sensor; /* Type of image sensor chip */ |
@@ -101,6 +100,7 @@ static void setexposure(struct gspca_dev *gspca_dev); | |||
101 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 100 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
102 | static void setlightfreq(struct gspca_dev *gspca_dev); | 101 | static void setlightfreq(struct gspca_dev *gspca_dev); |
103 | static void setsharpness(struct gspca_dev *gspca_dev); | 102 | static void setsharpness(struct gspca_dev *gspca_dev); |
103 | static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val); | ||
104 | 104 | ||
105 | static const struct ctrl sd_ctrls[NCTRLS] = { | 105 | static const struct ctrl sd_ctrls[NCTRLS] = { |
106 | [BRIGHTNESS] = { | 106 | [BRIGHTNESS] = { |
@@ -188,6 +188,18 @@ static const struct ctrl sd_ctrls[NCTRLS] = { | |||
188 | }, | 188 | }, |
189 | .set_control = setsharpness | 189 | .set_control = setsharpness |
190 | }, | 190 | }, |
191 | [QUALITY] = { | ||
192 | { | ||
193 | .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, | ||
194 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
195 | .name = "Compression Quality", | ||
196 | .minimum = 40, | ||
197 | .maximum = 70, | ||
198 | .step = 1, | ||
199 | .default_value = 70 /* updated in sd_init() */ | ||
200 | }, | ||
201 | .set = sd_setquality | ||
202 | }, | ||
191 | }; | 203 | }; |
192 | 204 | ||
193 | static const struct v4l2_pix_format vga_mode[] = { | 205 | static const struct v4l2_pix_format vga_mode[] = { |
@@ -229,6 +241,9 @@ static const struct v4l2_pix_format sif_mode[] = { | |||
229 | .priv = 0}, | 241 | .priv = 0}, |
230 | }; | 242 | }; |
231 | 243 | ||
244 | /* bridge reg08 -> JPEG quality conversion table */ | ||
245 | static u8 jpeg_qual[] = {40, 50, 60, 70, /*80*/}; | ||
246 | |||
232 | /* usb exchanges */ | 247 | /* usb exchanges */ |
233 | struct usb_action { | 248 | struct usb_action { |
234 | u8 req; | 249 | u8 req; |
@@ -3894,7 +3909,6 @@ static const struct usb_action pas106b_Initial[] = { /* 352x288 */ | |||
3894 | /* Gains */ | 3909 | /* Gains */ |
3895 | {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, | 3910 | {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
3896 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, | 3911 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, |
3897 | {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN}, | ||
3898 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, | 3912 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, |
3899 | /* Auto correction */ | 3913 | /* Auto correction */ |
3900 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, | 3914 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, |
@@ -5640,7 +5654,7 @@ static const struct usb_action gc0303_NoFlikerScale[] = { | |||
5640 | {} | 5654 | {} |
5641 | }; | 5655 | }; |
5642 | 5656 | ||
5643 | static u8 reg_r_i(struct gspca_dev *gspca_dev, | 5657 | static u8 reg_r(struct gspca_dev *gspca_dev, |
5644 | u16 index) | 5658 | u16 index) |
5645 | { | 5659 | { |
5646 | int ret; | 5660 | int ret; |
@@ -5655,24 +5669,14 @@ static u8 reg_r_i(struct gspca_dev *gspca_dev, | |||
5655 | index, gspca_dev->usb_buf, 1, | 5669 | index, gspca_dev->usb_buf, 1, |
5656 | 500); | 5670 | 500); |
5657 | if (ret < 0) { | 5671 | if (ret < 0) { |
5658 | pr_err("reg_r_i err %d\n", ret); | 5672 | pr_err("reg_r err %d\n", ret); |
5659 | gspca_dev->usb_err = ret; | 5673 | gspca_dev->usb_err = ret; |
5660 | return 0; | 5674 | return 0; |
5661 | } | 5675 | } |
5662 | return gspca_dev->usb_buf[0]; | 5676 | return gspca_dev->usb_buf[0]; |
5663 | } | 5677 | } |
5664 | 5678 | ||
5665 | static u8 reg_r(struct gspca_dev *gspca_dev, | 5679 | static void reg_w(struct gspca_dev *gspca_dev, |
5666 | u16 index) | ||
5667 | { | ||
5668 | u8 ret; | ||
5669 | |||
5670 | ret = reg_r_i(gspca_dev, index); | ||
5671 | PDEBUG(D_USBI, "reg r [%04x] -> %02x", index, ret); | ||
5672 | return ret; | ||
5673 | } | ||
5674 | |||
5675 | static void reg_w_i(struct gspca_dev *gspca_dev, | ||
5676 | u8 value, | 5680 | u8 value, |
5677 | u16 index) | 5681 | u16 index) |
5678 | { | 5682 | { |
@@ -5692,14 +5696,6 @@ static void reg_w_i(struct gspca_dev *gspca_dev, | |||
5692 | } | 5696 | } |
5693 | } | 5697 | } |
5694 | 5698 | ||
5695 | static void reg_w(struct gspca_dev *gspca_dev, | ||
5696 | u8 value, | ||
5697 | u16 index) | ||
5698 | { | ||
5699 | PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value); | ||
5700 | reg_w_i(gspca_dev, value, index); | ||
5701 | } | ||
5702 | |||
5703 | static u16 i2c_read(struct gspca_dev *gspca_dev, | 5699 | static u16 i2c_read(struct gspca_dev *gspca_dev, |
5704 | u8 reg) | 5700 | u8 reg) |
5705 | { | 5701 | { |
@@ -5708,16 +5704,14 @@ static u16 i2c_read(struct gspca_dev *gspca_dev, | |||
5708 | 5704 | ||
5709 | if (gspca_dev->usb_err < 0) | 5705 | if (gspca_dev->usb_err < 0) |
5710 | return 0; | 5706 | return 0; |
5711 | reg_w_i(gspca_dev, reg, 0x0092); | 5707 | reg_w(gspca_dev, reg, 0x0092); |
5712 | reg_w_i(gspca_dev, 0x02, 0x0090); /* <- read command */ | 5708 | reg_w(gspca_dev, 0x02, 0x0090); /* <- read command */ |
5713 | msleep(20); | 5709 | msleep(20); |
5714 | retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ | 5710 | retbyte = reg_r(gspca_dev, 0x0091); /* read status */ |
5715 | if (retbyte != 0x00) | 5711 | if (retbyte != 0x00) |
5716 | pr_err("i2c_r status error %02x\n", retbyte); | 5712 | pr_err("i2c_r status error %02x\n", retbyte); |
5717 | retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ | 5713 | retval = reg_r(gspca_dev, 0x0095); /* read Lowbyte */ |
5718 | retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */ | 5714 | retval |= reg_r(gspca_dev, 0x0096) << 8; /* read Hightbyte */ |
5719 | PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)", | ||
5720 | reg, retval, retbyte); | ||
5721 | return retval; | 5715 | return retval; |
5722 | } | 5716 | } |
5723 | 5717 | ||
@@ -5730,16 +5724,14 @@ static u8 i2c_write(struct gspca_dev *gspca_dev, | |||
5730 | 5724 | ||
5731 | if (gspca_dev->usb_err < 0) | 5725 | if (gspca_dev->usb_err < 0) |
5732 | return 0; | 5726 | return 0; |
5733 | reg_w_i(gspca_dev, reg, 0x92); | 5727 | reg_w(gspca_dev, reg, 0x92); |
5734 | reg_w_i(gspca_dev, valL, 0x93); | 5728 | reg_w(gspca_dev, valL, 0x93); |
5735 | reg_w_i(gspca_dev, valH, 0x94); | 5729 | reg_w(gspca_dev, valH, 0x94); |
5736 | reg_w_i(gspca_dev, 0x01, 0x90); /* <- write command */ | 5730 | reg_w(gspca_dev, 0x01, 0x90); /* <- write command */ |
5737 | msleep(1); | 5731 | msleep(1); |
5738 | retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ | 5732 | retbyte = reg_r(gspca_dev, 0x0091); /* read status */ |
5739 | if (retbyte != 0x00) | 5733 | if (retbyte != 0x00) |
5740 | pr_err("i2c_w status error %02x\n", retbyte); | 5734 | pr_err("i2c_w status error %02x\n", retbyte); |
5741 | PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)", | ||
5742 | reg, valH, valL, retbyte); | ||
5743 | return retbyte; | 5735 | return retbyte; |
5744 | } | 5736 | } |
5745 | 5737 | ||
@@ -5906,6 +5898,8 @@ static void getexposure(struct gspca_dev *gspca_dev) | |||
5906 | { | 5898 | { |
5907 | struct sd *sd = (struct sd *) gspca_dev; | 5899 | struct sd *sd = (struct sd *) gspca_dev; |
5908 | 5900 | ||
5901 | if (sd->sensor != SENSOR_HV7131R) | ||
5902 | return; | ||
5909 | sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9) | 5903 | sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9) |
5910 | | (i2c_read(gspca_dev, 0x26) << 1) | 5904 | | (i2c_read(gspca_dev, 0x26) << 1) |
5911 | | (i2c_read(gspca_dev, 0x27) >> 7); | 5905 | | (i2c_read(gspca_dev, 0x27) >> 7); |
@@ -5916,6 +5910,8 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
5916 | struct sd *sd = (struct sd *) gspca_dev; | 5910 | struct sd *sd = (struct sd *) gspca_dev; |
5917 | int val; | 5911 | int val; |
5918 | 5912 | ||
5913 | if (sd->sensor != SENSOR_HV7131R) | ||
5914 | return; | ||
5919 | val = sd->ctrls[EXPOSURE].val; | 5915 | val = sd->ctrls[EXPOSURE].val; |
5920 | i2c_write(gspca_dev, 0x25, val >> 9, 0x00); | 5916 | i2c_write(gspca_dev, 0x25, val >> 9, 0x00); |
5921 | i2c_write(gspca_dev, 0x26, val >> 1, 0x00); | 5917 | i2c_write(gspca_dev, 0x26, val >> 1, 0x00); |
@@ -5925,32 +5921,20 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
5925 | static void setquality(struct gspca_dev *gspca_dev) | 5921 | static void setquality(struct gspca_dev *gspca_dev) |
5926 | { | 5922 | { |
5927 | struct sd *sd = (struct sd *) gspca_dev; | 5923 | struct sd *sd = (struct sd *) gspca_dev; |
5928 | u8 frxt; | 5924 | s8 reg07; |
5929 | 5925 | ||
5926 | reg07 = 0; | ||
5930 | switch (sd->sensor) { | 5927 | switch (sd->sensor) { |
5931 | case SENSOR_ADCM2700: | ||
5932 | case SENSOR_GC0305: | ||
5933 | case SENSOR_HV7131B: | ||
5934 | case SENSOR_HV7131R: | ||
5935 | case SENSOR_OV7620: | 5928 | case SENSOR_OV7620: |
5929 | reg07 = 0x30; | ||
5930 | break; | ||
5931 | case SENSOR_HV7131R: | ||
5936 | case SENSOR_PAS202B: | 5932 | case SENSOR_PAS202B: |
5937 | case SENSOR_PO2030: | 5933 | return; /* done by work queue */ |
5938 | return; | ||
5939 | } | 5934 | } |
5940 | /*fixme: is it really 0008 0007 0018 for all other sensors? */ | 5935 | reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); |
5941 | reg_w(gspca_dev, QUANT_VAL, 0x0008); | 5936 | if (reg07 != 0) |
5942 | frxt = 0x30; | 5937 | reg_w(gspca_dev, reg07, 0x0007); |
5943 | reg_w(gspca_dev, frxt, 0x0007); | ||
5944 | #if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2 | ||
5945 | frxt = 0xff; | ||
5946 | #elif QUANT_VAL == 3 | ||
5947 | frxt = 0xf0; | ||
5948 | #elif QUANT_VAL == 4 | ||
5949 | frxt = 0xe0; | ||
5950 | #else | ||
5951 | frxt = 0x20; | ||
5952 | #endif | ||
5953 | reg_w(gspca_dev, frxt, 0x0018); | ||
5954 | } | 5938 | } |
5955 | 5939 | ||
5956 | /* Matches the sensor's internal frame rate to the lighting frequency. | 5940 | /* Matches the sensor's internal frame rate to the lighting frequency. |
@@ -6084,6 +6068,115 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
6084 | reg_w(gspca_dev, autoval, 0x0180); | 6068 | reg_w(gspca_dev, autoval, 0x0180); |
6085 | } | 6069 | } |
6086 | 6070 | ||
6071 | /* update the transfer parameters */ | ||
6072 | /* This function is executed from a work queue. */ | ||
6073 | /* The exact use of the bridge registers 07 and 08 is not known. | ||
6074 | * The following algorithm has been adapted from ms-win traces */ | ||
6075 | static void transfer_update(struct work_struct *work) | ||
6076 | { | ||
6077 | struct sd *sd = container_of(work, struct sd, work); | ||
6078 | struct gspca_dev *gspca_dev = &sd->gspca_dev; | ||
6079 | int change, good; | ||
6080 | u8 reg07, reg11; | ||
6081 | |||
6082 | /* synchronize with the main driver and initialize the registers */ | ||
6083 | mutex_lock(&gspca_dev->usb_lock); | ||
6084 | reg07 = 0; /* max */ | ||
6085 | reg_w(gspca_dev, reg07, 0x0007); | ||
6086 | reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); | ||
6087 | mutex_unlock(&gspca_dev->usb_lock); | ||
6088 | |||
6089 | good = 0; | ||
6090 | for (;;) { | ||
6091 | msleep(100); | ||
6092 | |||
6093 | /* get the transfer status */ | ||
6094 | /* the bit 0 of the bridge register 11 indicates overflow */ | ||
6095 | mutex_lock(&gspca_dev->usb_lock); | ||
6096 | if (!gspca_dev->present || !gspca_dev->streaming) | ||
6097 | goto err; | ||
6098 | reg11 = reg_r(gspca_dev, 0x0011); | ||
6099 | if (gspca_dev->usb_err < 0 | ||
6100 | || !gspca_dev->present || !gspca_dev->streaming) | ||
6101 | goto err; | ||
6102 | |||
6103 | change = reg11 & 0x01; | ||
6104 | if (change) { /* overflow */ | ||
6105 | switch (reg07) { | ||
6106 | case 0: /* max */ | ||
6107 | reg07 = sd->sensor == SENSOR_HV7131R | ||
6108 | ? 0x30 : 0x32; | ||
6109 | if (sd->reg08 != 0) { | ||
6110 | change = 3; | ||
6111 | sd->reg08--; | ||
6112 | } | ||
6113 | break; | ||
6114 | case 0x32: | ||
6115 | reg07 -= 4; | ||
6116 | break; | ||
6117 | default: | ||
6118 | reg07 -= 2; | ||
6119 | break; | ||
6120 | case 2: | ||
6121 | change = 0; /* already min */ | ||
6122 | break; | ||
6123 | } | ||
6124 | good = 0; | ||
6125 | } else { /* no overflow */ | ||
6126 | if (reg07 != 0) { /* if not max */ | ||
6127 | good++; | ||
6128 | if (good >= 10) { | ||
6129 | good = 0; | ||
6130 | change = 1; | ||
6131 | reg07 += 2; | ||
6132 | switch (reg07) { | ||
6133 | case 0x30: | ||
6134 | if (sd->sensor == SENSOR_PAS202B) | ||
6135 | reg07 += 2; | ||
6136 | break; | ||
6137 | case 0x32: | ||
6138 | case 0x34: | ||
6139 | reg07 = 0; | ||
6140 | break; | ||
6141 | } | ||
6142 | } | ||
6143 | } else { /* reg07 max */ | ||
6144 | if (sd->reg08 < sizeof jpeg_qual - 1) { | ||
6145 | good++; | ||
6146 | if (good > 10) { | ||
6147 | sd->reg08++; | ||
6148 | change = 2; | ||
6149 | } | ||
6150 | } | ||
6151 | } | ||
6152 | } | ||
6153 | if (change) { | ||
6154 | if (change & 1) { | ||
6155 | reg_w(gspca_dev, reg07, 0x0007); | ||
6156 | if (gspca_dev->usb_err < 0 | ||
6157 | || !gspca_dev->present | ||
6158 | || !gspca_dev->streaming) | ||
6159 | goto err; | ||
6160 | } | ||
6161 | if (change & 2) { | ||
6162 | reg_w(gspca_dev, sd->reg08, | ||
6163 | ZC3XX_R008_CLOCKSETTING); | ||
6164 | if (gspca_dev->usb_err < 0 | ||
6165 | || !gspca_dev->present | ||
6166 | || !gspca_dev->streaming) | ||
6167 | goto err; | ||
6168 | sd->ctrls[QUALITY].val = jpeg_qual[sd->reg08]; | ||
6169 | jpeg_set_qual(sd->jpeg_hdr, | ||
6170 | jpeg_qual[sd->reg08]); | ||
6171 | } | ||
6172 | } | ||
6173 | mutex_unlock(&gspca_dev->usb_lock); | ||
6174 | } | ||
6175 | return; | ||
6176 | err: | ||
6177 | mutex_unlock(&gspca_dev->usb_lock); | ||
6178 | } | ||
6179 | |||
6087 | static void send_unknown(struct gspca_dev *gspca_dev, int sensor) | 6180 | static void send_unknown(struct gspca_dev *gspca_dev, int sensor) |
6088 | { | 6181 | { |
6089 | reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */ | 6182 | reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */ |
@@ -6411,7 +6504,9 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6411 | sd->sensor = id->driver_info; | 6504 | sd->sensor = id->driver_info; |
6412 | 6505 | ||
6413 | gspca_dev->cam.ctrls = sd->ctrls; | 6506 | gspca_dev->cam.ctrls = sd->ctrls; |
6414 | sd->quality = QUALITY_DEF; | 6507 | sd->reg08 = REG08_DEF; |
6508 | |||
6509 | INIT_WORK(&sd->work, transfer_update); | ||
6415 | 6510 | ||
6416 | return 0; | 6511 | return 0; |
6417 | } | 6512 | } |
@@ -6464,6 +6559,27 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
6464 | [SENSOR_PO2030] = 1, | 6559 | [SENSOR_PO2030] = 1, |
6465 | [SENSOR_TAS5130C] = 1, | 6560 | [SENSOR_TAS5130C] = 1, |
6466 | }; | 6561 | }; |
6562 | static const u8 reg08_tb[SENSOR_MAX] = { | ||
6563 | [SENSOR_ADCM2700] = 1, | ||
6564 | [SENSOR_CS2102] = 3, | ||
6565 | [SENSOR_CS2102K] = 3, | ||
6566 | [SENSOR_GC0303] = 2, | ||
6567 | [SENSOR_GC0305] = 3, | ||
6568 | [SENSOR_HDCS2020] = 1, | ||
6569 | [SENSOR_HV7131B] = 3, | ||
6570 | [SENSOR_HV7131R] = 3, | ||
6571 | [SENSOR_ICM105A] = 3, | ||
6572 | [SENSOR_MC501CB] = 3, | ||
6573 | [SENSOR_MT9V111_1] = 3, | ||
6574 | [SENSOR_MT9V111_3] = 3, | ||
6575 | [SENSOR_OV7620] = 1, | ||
6576 | [SENSOR_OV7630C] = 3, | ||
6577 | [SENSOR_PAS106] = 3, | ||
6578 | [SENSOR_PAS202B] = 3, | ||
6579 | [SENSOR_PB0330] = 3, | ||
6580 | [SENSOR_PO2030] = 2, | ||
6581 | [SENSOR_TAS5130C] = 3, | ||
6582 | }; | ||
6467 | 6583 | ||
6468 | sensor = zcxx_probeSensor(gspca_dev); | 6584 | sensor = zcxx_probeSensor(gspca_dev); |
6469 | if (sensor >= 0) | 6585 | if (sensor >= 0) |
@@ -6528,7 +6644,6 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
6528 | case 0x0e: | 6644 | case 0x0e: |
6529 | PDEBUG(D_PROBE, "Find Sensor PAS202B"); | 6645 | PDEBUG(D_PROBE, "Find Sensor PAS202B"); |
6530 | sd->sensor = SENSOR_PAS202B; | 6646 | sd->sensor = SENSOR_PAS202B; |
6531 | /* sd->sharpness = 1; */ | ||
6532 | break; | 6647 | break; |
6533 | case 0x0f: | 6648 | case 0x0f: |
6534 | PDEBUG(D_PROBE, "Find Sensor PAS106"); | 6649 | PDEBUG(D_PROBE, "Find Sensor PAS106"); |
@@ -6616,13 +6731,21 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
6616 | } | 6731 | } |
6617 | 6732 | ||
6618 | sd->ctrls[GAMMA].def = gamma[sd->sensor]; | 6733 | sd->ctrls[GAMMA].def = gamma[sd->sensor]; |
6734 | sd->reg08 = reg08_tb[sd->sensor]; | ||
6735 | sd->ctrls[QUALITY].def = jpeg_qual[sd->reg08]; | ||
6736 | sd->ctrls[QUALITY].min = jpeg_qual[0]; | ||
6737 | sd->ctrls[QUALITY].max = jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1]; | ||
6619 | 6738 | ||
6620 | switch (sd->sensor) { | 6739 | switch (sd->sensor) { |
6621 | case SENSOR_HV7131R: | 6740 | case SENSOR_HV7131R: |
6741 | gspca_dev->ctrl_dis = (1 << QUALITY); | ||
6622 | break; | 6742 | break; |
6623 | case SENSOR_OV7630C: | 6743 | case SENSOR_OV7630C: |
6624 | gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE); | 6744 | gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE); |
6625 | break; | 6745 | break; |
6746 | case SENSOR_PAS202B: | ||
6747 | gspca_dev->ctrl_dis = (1 << QUALITY) | (1 << EXPOSURE); | ||
6748 | break; | ||
6626 | default: | 6749 | default: |
6627 | gspca_dev->ctrl_dis = (1 << EXPOSURE); | 6750 | gspca_dev->ctrl_dis = (1 << EXPOSURE); |
6628 | break; | 6751 | break; |
@@ -6685,7 +6808,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6685 | /* create the JPEG header */ | 6808 | /* create the JPEG header */ |
6686 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 6809 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
6687 | 0x21); /* JPEG 422 */ | 6810 | 0x21); /* JPEG 422 */ |
6688 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
6689 | 6811 | ||
6690 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | 6812 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
6691 | switch (sd->sensor) { | 6813 | switch (sd->sensor) { |
@@ -6761,10 +6883,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6761 | reg_r(gspca_dev, 0x0180); /* from win */ | 6883 | reg_r(gspca_dev, 0x0180); /* from win */ |
6762 | reg_w(gspca_dev, 0x00, 0x0180); | 6884 | reg_w(gspca_dev, 0x00, 0x0180); |
6763 | break; | 6885 | break; |
6764 | default: | ||
6765 | setquality(gspca_dev); | ||
6766 | break; | ||
6767 | } | 6886 | } |
6887 | setquality(gspca_dev); | ||
6888 | jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08]); | ||
6768 | setlightfreq(gspca_dev); | 6889 | setlightfreq(gspca_dev); |
6769 | 6890 | ||
6770 | switch (sd->sensor) { | 6891 | switch (sd->sensor) { |
@@ -6776,8 +6897,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6776 | reg_w(gspca_dev, 0x40, 0x0117); | 6897 | reg_w(gspca_dev, 0x40, 0x0117); |
6777 | break; | 6898 | break; |
6778 | case SENSOR_HV7131R: | 6899 | case SENSOR_HV7131R: |
6779 | if (!sd->ctrls[AUTOGAIN].val) | 6900 | setexposure(gspca_dev); |
6780 | setexposure(gspca_dev); | ||
6781 | reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); | 6901 | reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); |
6782 | break; | 6902 | break; |
6783 | case SENSOR_GC0305: | 6903 | case SENSOR_GC0305: |
@@ -6802,13 +6922,19 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6802 | } | 6922 | } |
6803 | 6923 | ||
6804 | setautogain(gspca_dev); | 6924 | setautogain(gspca_dev); |
6805 | switch (sd->sensor) { | 6925 | |
6806 | case SENSOR_PO2030: | 6926 | /* start the transfer update thread if needed */ |
6807 | msleep(50); | 6927 | if (gspca_dev->usb_err >= 0) { |
6808 | reg_w(gspca_dev, 0x00, 0x0007); /* (from win traces) */ | 6928 | switch (sd->sensor) { |
6809 | reg_w(gspca_dev, 0x02, ZC3XX_R008_CLOCKSETTING); | 6929 | case SENSOR_HV7131R: |
6810 | break; | 6930 | case SENSOR_PAS202B: |
6931 | sd->work_thread = | ||
6932 | create_singlethread_workqueue(KBUILD_MODNAME); | ||
6933 | queue_work(sd->work_thread, &sd->work); | ||
6934 | break; | ||
6935 | } | ||
6811 | } | 6936 | } |
6937 | |||
6812 | return gspca_dev->usb_err; | 6938 | return gspca_dev->usb_err; |
6813 | } | 6939 | } |
6814 | 6940 | ||
@@ -6817,6 +6943,12 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
6817 | { | 6943 | { |
6818 | struct sd *sd = (struct sd *) gspca_dev; | 6944 | struct sd *sd = (struct sd *) gspca_dev; |
6819 | 6945 | ||
6946 | if (sd->work_thread != NULL) { | ||
6947 | mutex_unlock(&gspca_dev->usb_lock); | ||
6948 | destroy_workqueue(sd->work_thread); | ||
6949 | mutex_lock(&gspca_dev->usb_lock); | ||
6950 | sd->work_thread = NULL; | ||
6951 | } | ||
6820 | if (!gspca_dev->present) | 6952 | if (!gspca_dev->present) |
6821 | return; | 6953 | return; |
6822 | send_unknown(gspca_dev, sd->sensor); | 6954 | send_unknown(gspca_dev, sd->sensor); |
@@ -6893,19 +7025,33 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, | |||
6893 | return -EINVAL; | 7025 | return -EINVAL; |
6894 | } | 7026 | } |
6895 | 7027 | ||
7028 | static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val) | ||
7029 | { | ||
7030 | struct sd *sd = (struct sd *) gspca_dev; | ||
7031 | int i; | ||
7032 | |||
7033 | for (i = 0; i < ARRAY_SIZE(jpeg_qual) - 1; i++) { | ||
7034 | if (val <= jpeg_qual[i]) | ||
7035 | break; | ||
7036 | } | ||
7037 | if (i > 0 | ||
7038 | && i == sd->reg08 | ||
7039 | && val < jpeg_qual[sd->reg08]) | ||
7040 | i--; | ||
7041 | sd->reg08 = i; | ||
7042 | sd->ctrls[QUALITY].val = jpeg_qual[i]; | ||
7043 | if (gspca_dev->streaming) | ||
7044 | jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); | ||
7045 | return gspca_dev->usb_err; | ||
7046 | } | ||
7047 | |||
6896 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, | 7048 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, |
6897 | struct v4l2_jpegcompression *jcomp) | 7049 | struct v4l2_jpegcompression *jcomp) |
6898 | { | 7050 | { |
6899 | struct sd *sd = (struct sd *) gspca_dev; | 7051 | struct sd *sd = (struct sd *) gspca_dev; |
6900 | 7052 | ||
6901 | if (jcomp->quality < QUALITY_MIN) | 7053 | sd_setquality(gspca_dev, jcomp->quality); |
6902 | sd->quality = QUALITY_MIN; | 7054 | jcomp->quality = sd->ctrls[QUALITY].val; |
6903 | else if (jcomp->quality > QUALITY_MAX) | ||
6904 | sd->quality = QUALITY_MAX; | ||
6905 | else | ||
6906 | sd->quality = jcomp->quality; | ||
6907 | if (gspca_dev->streaming) | ||
6908 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
6909 | return gspca_dev->usb_err; | 7055 | return gspca_dev->usb_err; |
6910 | } | 7056 | } |
6911 | 7057 | ||
@@ -6915,7 +7061,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, | |||
6915 | struct sd *sd = (struct sd *) gspca_dev; | 7061 | struct sd *sd = (struct sd *) gspca_dev; |
6916 | 7062 | ||
6917 | memset(jcomp, 0, sizeof *jcomp); | 7063 | memset(jcomp, 0, sizeof *jcomp); |
6918 | jcomp->quality = sd->quality; | 7064 | jcomp->quality = sd->ctrls[QUALITY].val; |
6919 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | 7065 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT |
6920 | | V4L2_JPEG_MARKER_DQT; | 7066 | | V4L2_JPEG_MARKER_DQT; |
6921 | return 0; | 7067 | return 0; |
@@ -6938,7 +7084,7 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | |||
6938 | #endif | 7084 | #endif |
6939 | 7085 | ||
6940 | static const struct sd_desc sd_desc = { | 7086 | static const struct sd_desc sd_desc = { |
6941 | .name = MODULE_NAME, | 7087 | .name = KBUILD_MODNAME, |
6942 | .ctrls = sd_ctrls, | 7088 | .ctrls = sd_ctrls, |
6943 | .nctrls = ARRAY_SIZE(sd_ctrls), | 7089 | .nctrls = ARRAY_SIZE(sd_ctrls), |
6944 | .config = sd_config, | 7090 | .config = sd_config, |
@@ -7023,7 +7169,7 @@ static int sd_probe(struct usb_interface *intf, | |||
7023 | 7169 | ||
7024 | /* USB driver */ | 7170 | /* USB driver */ |
7025 | static struct usb_driver sd_driver = { | 7171 | static struct usb_driver sd_driver = { |
7026 | .name = MODULE_NAME, | 7172 | .name = KBUILD_MODNAME, |
7027 | .id_table = device_table, | 7173 | .id_table = device_table, |
7028 | .probe = sd_probe, | 7174 | .probe = sd_probe, |
7029 | .disconnect = gspca_disconnect, | 7175 | .disconnect = gspca_disconnect, |