diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-05-06 08:28:28 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-14 08:36:05 -0400 |
commit | c06ba2804a50076cc0c5a4d65466a37b8eaa4455 (patch) | |
tree | 985d80aa5a50ba98e6e75b16c19b069d6f4268ee | |
parent | 1b3bbcf5ab7250527a629ec1ffc36c8d1ea12681 (diff) |
[media] gspca_zc3xx: Convert to the control framework
The initial version was done by HV, corrections were made by HdG, and some
final small changes again by HV.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/gspca/zc3xx.c | 438 |
1 files changed, 170 insertions, 268 deletions
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 998017eacc1f..a8839fb3c1d6 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -35,26 +35,23 @@ static int force_sensor = -1; | |||
35 | #define REG08_DEF 3 /* default JPEG compression (75%) */ | 35 | #define REG08_DEF 3 /* default JPEG compression (75%) */ |
36 | #include "zc3xx-reg.h" | 36 | #include "zc3xx-reg.h" |
37 | 37 | ||
38 | /* controls */ | ||
39 | enum e_ctrl { | ||
40 | BRIGHTNESS, | ||
41 | CONTRAST, | ||
42 | EXPOSURE, | ||
43 | GAMMA, | ||
44 | AUTOGAIN, | ||
45 | LIGHTFREQ, | ||
46 | SHARPNESS, | ||
47 | QUALITY, | ||
48 | NCTRLS /* number of controls */ | ||
49 | }; | ||
50 | |||
51 | #define AUTOGAIN_DEF 1 | ||
52 | |||
53 | /* specific webcam descriptor */ | 38 | /* specific webcam descriptor */ |
54 | struct sd { | 39 | struct sd { |
55 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 40 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
56 | 41 | ||
57 | struct gspca_ctrl ctrls[NCTRLS]; | 42 | struct v4l2_ctrl_handler ctrl_handler; |
43 | struct { /* gamma/brightness/contrast control cluster */ | ||
44 | struct v4l2_ctrl *gamma; | ||
45 | struct v4l2_ctrl *brightness; | ||
46 | struct v4l2_ctrl *contrast; | ||
47 | }; | ||
48 | struct { /* autogain/exposure control cluster */ | ||
49 | struct v4l2_ctrl *autogain; | ||
50 | struct v4l2_ctrl *exposure; | ||
51 | }; | ||
52 | struct v4l2_ctrl *plfreq; | ||
53 | struct v4l2_ctrl *sharpness; | ||
54 | struct v4l2_ctrl *jpegqual; | ||
58 | 55 | ||
59 | struct work_struct work; | 56 | struct work_struct work; |
60 | struct workqueue_struct *work_thread; | 57 | struct workqueue_struct *work_thread; |
@@ -94,114 +91,6 @@ enum sensors { | |||
94 | SENSOR_MAX | 91 | SENSOR_MAX |
95 | }; | 92 | }; |
96 | 93 | ||
97 | /* V4L2 controls supported by the driver */ | ||
98 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
99 | static void setexposure(struct gspca_dev *gspca_dev); | ||
100 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
101 | static void setlightfreq(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 | |||
105 | static const struct ctrl sd_ctrls[NCTRLS] = { | ||
106 | [BRIGHTNESS] = { | ||
107 | { | ||
108 | .id = V4L2_CID_BRIGHTNESS, | ||
109 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
110 | .name = "Brightness", | ||
111 | .minimum = 0, | ||
112 | .maximum = 255, | ||
113 | .step = 1, | ||
114 | .default_value = 128, | ||
115 | }, | ||
116 | .set_control = setcontrast | ||
117 | }, | ||
118 | [CONTRAST] = { | ||
119 | { | ||
120 | .id = V4L2_CID_CONTRAST, | ||
121 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
122 | .name = "Contrast", | ||
123 | .minimum = 0, | ||
124 | .maximum = 255, | ||
125 | .step = 1, | ||
126 | .default_value = 128, | ||
127 | }, | ||
128 | .set_control = setcontrast | ||
129 | }, | ||
130 | [EXPOSURE] = { | ||
131 | { | ||
132 | .id = V4L2_CID_EXPOSURE, | ||
133 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
134 | .name = "Exposure", | ||
135 | .minimum = 0x30d, | ||
136 | .maximum = 0x493e, | ||
137 | .step = 1, | ||
138 | .default_value = 0x927 | ||
139 | }, | ||
140 | .set_control = setexposure | ||
141 | }, | ||
142 | [GAMMA] = { | ||
143 | { | ||
144 | .id = V4L2_CID_GAMMA, | ||
145 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
146 | .name = "Gamma", | ||
147 | .minimum = 1, | ||
148 | .maximum = 6, | ||
149 | .step = 1, | ||
150 | .default_value = 4, | ||
151 | }, | ||
152 | .set_control = setcontrast | ||
153 | }, | ||
154 | [AUTOGAIN] = { | ||
155 | { | ||
156 | .id = V4L2_CID_AUTOGAIN, | ||
157 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
158 | .name = "Auto Gain", | ||
159 | .minimum = 0, | ||
160 | .maximum = 1, | ||
161 | .step = 1, | ||
162 | .default_value = AUTOGAIN_DEF, | ||
163 | .flags = V4L2_CTRL_FLAG_UPDATE | ||
164 | }, | ||
165 | .set = sd_setautogain | ||
166 | }, | ||
167 | [LIGHTFREQ] = { | ||
168 | { | ||
169 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
170 | .type = V4L2_CTRL_TYPE_MENU, | ||
171 | .name = "Light frequency filter", | ||
172 | .minimum = 0, | ||
173 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
174 | .step = 1, | ||
175 | .default_value = 0, | ||
176 | }, | ||
177 | .set_control = setlightfreq | ||
178 | }, | ||
179 | [SHARPNESS] = { | ||
180 | { | ||
181 | .id = V4L2_CID_SHARPNESS, | ||
182 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
183 | .name = "Sharpness", | ||
184 | .minimum = 0, | ||
185 | .maximum = 3, | ||
186 | .step = 1, | ||
187 | .default_value = 2, | ||
188 | }, | ||
189 | .set_control = setsharpness | ||
190 | }, | ||
191 | [QUALITY] = { | ||
192 | { | ||
193 | .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, | ||
194 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
195 | .name = "Compression Quality", | ||
196 | .minimum = 50, | ||
197 | .maximum = 87, | ||
198 | .step = 1, | ||
199 | .default_value = 75, | ||
200 | }, | ||
201 | .set = sd_setquality | ||
202 | }, | ||
203 | }; | ||
204 | |||
205 | static const struct v4l2_pix_format vga_mode[] = { | 94 | static const struct v4l2_pix_format vga_mode[] = { |
206 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 95 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
207 | .bytesperline = 320, | 96 | .bytesperline = 320, |
@@ -5821,10 +5710,8 @@ static void setmatrix(struct gspca_dev *gspca_dev) | |||
5821 | reg_w(gspca_dev, matrix[i], 0x010a + i); | 5710 | reg_w(gspca_dev, matrix[i], 0x010a + i); |
5822 | } | 5711 | } |
5823 | 5712 | ||
5824 | static void setsharpness(struct gspca_dev *gspca_dev) | 5713 | static void setsharpness(struct gspca_dev *gspca_dev, s32 val) |
5825 | { | 5714 | { |
5826 | struct sd *sd = (struct sd *) gspca_dev; | ||
5827 | int sharpness; | ||
5828 | static const u8 sharpness_tb[][2] = { | 5715 | static const u8 sharpness_tb[][2] = { |
5829 | {0x02, 0x03}, | 5716 | {0x02, 0x03}, |
5830 | {0x04, 0x07}, | 5717 | {0x04, 0x07}, |
@@ -5832,19 +5719,18 @@ static void setsharpness(struct gspca_dev *gspca_dev) | |||
5832 | {0x10, 0x1e} | 5719 | {0x10, 0x1e} |
5833 | }; | 5720 | }; |
5834 | 5721 | ||
5835 | sharpness = sd->ctrls[SHARPNESS].val; | 5722 | reg_w(gspca_dev, sharpness_tb[val][0], 0x01c6); |
5836 | reg_w(gspca_dev, sharpness_tb[sharpness][0], 0x01c6); | ||
5837 | reg_r(gspca_dev, 0x01c8); | 5723 | reg_r(gspca_dev, 0x01c8); |
5838 | reg_r(gspca_dev, 0x01c9); | 5724 | reg_r(gspca_dev, 0x01c9); |
5839 | reg_r(gspca_dev, 0x01ca); | 5725 | reg_r(gspca_dev, 0x01ca); |
5840 | reg_w(gspca_dev, sharpness_tb[sharpness][1], 0x01cb); | 5726 | reg_w(gspca_dev, sharpness_tb[val][1], 0x01cb); |
5841 | } | 5727 | } |
5842 | 5728 | ||
5843 | static void setcontrast(struct gspca_dev *gspca_dev) | 5729 | static void setcontrast(struct gspca_dev *gspca_dev, |
5730 | s32 gamma, s32 brightness, s32 contrast) | ||
5844 | { | 5731 | { |
5845 | struct sd *sd = (struct sd *) gspca_dev; | ||
5846 | const u8 *Tgamma; | 5732 | const u8 *Tgamma; |
5847 | int g, i, brightness, contrast, adj, gp1, gp2; | 5733 | int g, i, adj, gp1, gp2; |
5848 | u8 gr[16]; | 5734 | u8 gr[16]; |
5849 | static const u8 delta_b[16] = /* delta for brightness */ | 5735 | static const u8 delta_b[16] = /* delta for brightness */ |
5850 | {0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d, | 5736 | {0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d, |
@@ -5867,10 +5753,10 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
5867 | 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff}, | 5753 | 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff}, |
5868 | }; | 5754 | }; |
5869 | 5755 | ||
5870 | Tgamma = gamma_tb[sd->ctrls[GAMMA].val - 1]; | 5756 | Tgamma = gamma_tb[gamma - 1]; |
5871 | 5757 | ||
5872 | contrast = ((int) sd->ctrls[CONTRAST].val - 128); /* -128 / 127 */ | 5758 | contrast -= 128; /* -128 / 127 */ |
5873 | brightness = ((int) sd->ctrls[BRIGHTNESS].val - 128); /* -128 / 92 */ | 5759 | brightness -= 128; /* -128 / 92 */ |
5874 | adj = 0; | 5760 | adj = 0; |
5875 | gp1 = gp2 = 0; | 5761 | gp1 = gp2 = 0; |
5876 | for (i = 0; i < 16; i++) { | 5762 | for (i = 0; i < 16; i++) { |
@@ -5897,25 +5783,15 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
5897 | reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */ | 5783 | reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */ |
5898 | } | 5784 | } |
5899 | 5785 | ||
5900 | static void getexposure(struct gspca_dev *gspca_dev) | 5786 | static s32 getexposure(struct gspca_dev *gspca_dev) |
5901 | { | 5787 | { |
5902 | struct sd *sd = (struct sd *) gspca_dev; | 5788 | return (i2c_read(gspca_dev, 0x25) << 9) |
5903 | |||
5904 | if (sd->sensor != SENSOR_HV7131R) | ||
5905 | return; | ||
5906 | sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9) | ||
5907 | | (i2c_read(gspca_dev, 0x26) << 1) | 5789 | | (i2c_read(gspca_dev, 0x26) << 1) |
5908 | | (i2c_read(gspca_dev, 0x27) >> 7); | 5790 | | (i2c_read(gspca_dev, 0x27) >> 7); |
5909 | } | 5791 | } |
5910 | 5792 | ||
5911 | static void setexposure(struct gspca_dev *gspca_dev) | 5793 | static void setexposure(struct gspca_dev *gspca_dev, s32 val) |
5912 | { | 5794 | { |
5913 | struct sd *sd = (struct sd *) gspca_dev; | ||
5914 | int val; | ||
5915 | |||
5916 | if (sd->sensor != SENSOR_HV7131R) | ||
5917 | return; | ||
5918 | val = sd->ctrls[EXPOSURE].val; | ||
5919 | i2c_write(gspca_dev, 0x25, val >> 9, 0x00); | 5795 | i2c_write(gspca_dev, 0x25, val >> 9, 0x00); |
5920 | i2c_write(gspca_dev, 0x26, val >> 1, 0x00); | 5796 | i2c_write(gspca_dev, 0x26, val >> 1, 0x00); |
5921 | i2c_write(gspca_dev, 0x27, val << 7, 0x00); | 5797 | i2c_write(gspca_dev, 0x27, val << 7, 0x00); |
@@ -5934,7 +5810,7 @@ static void setquality(struct gspca_dev *gspca_dev) | |||
5934 | * 60Hz, for American lighting | 5810 | * 60Hz, for American lighting |
5935 | * 0 = No Fliker (for outdoore usage) | 5811 | * 0 = No Fliker (for outdoore usage) |
5936 | */ | 5812 | */ |
5937 | static void setlightfreq(struct gspca_dev *gspca_dev) | 5813 | static void setlightfreq(struct gspca_dev *gspca_dev, s32 val) |
5938 | { | 5814 | { |
5939 | struct sd *sd = (struct sd *) gspca_dev; | 5815 | struct sd *sd = (struct sd *) gspca_dev; |
5940 | int i, mode; | 5816 | int i, mode; |
@@ -6018,7 +5894,7 @@ static void setlightfreq(struct gspca_dev *gspca_dev) | |||
6018 | tas5130c_60HZ, tas5130c_60HZScale}, | 5894 | tas5130c_60HZ, tas5130c_60HZScale}, |
6019 | }; | 5895 | }; |
6020 | 5896 | ||
6021 | i = sd->ctrls[LIGHTFREQ].val * 2; | 5897 | i = val * 2; |
6022 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | 5898 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
6023 | if (mode) | 5899 | if (mode) |
6024 | i++; /* 320x240 */ | 5900 | i++; /* 320x240 */ |
@@ -6028,14 +5904,14 @@ static void setlightfreq(struct gspca_dev *gspca_dev) | |||
6028 | usb_exchange(gspca_dev, zc3_freq); | 5904 | usb_exchange(gspca_dev, zc3_freq); |
6029 | switch (sd->sensor) { | 5905 | switch (sd->sensor) { |
6030 | case SENSOR_GC0305: | 5906 | case SENSOR_GC0305: |
6031 | if (mode /* if 320x240 */ | 5907 | if (mode /* if 320x240 */ |
6032 | && sd->ctrls[LIGHTFREQ].val == 1) /* and 50Hz */ | 5908 | && val == 1) /* and 50Hz */ |
6033 | reg_w(gspca_dev, 0x85, 0x018d); | 5909 | reg_w(gspca_dev, 0x85, 0x018d); |
6034 | /* win: 0x80, 0x018d */ | 5910 | /* win: 0x80, 0x018d */ |
6035 | break; | 5911 | break; |
6036 | case SENSOR_OV7620: | 5912 | case SENSOR_OV7620: |
6037 | if (!mode) { /* if 640x480 */ | 5913 | if (!mode) { /* if 640x480 */ |
6038 | if (sd->ctrls[LIGHTFREQ].val != 0) /* and filter */ | 5914 | if (val != 0) /* and filter */ |
6039 | reg_w(gspca_dev, 0x40, 0x0002); | 5915 | reg_w(gspca_dev, 0x40, 0x0002); |
6040 | else | 5916 | else |
6041 | reg_w(gspca_dev, 0x44, 0x0002); | 5917 | reg_w(gspca_dev, 0x44, 0x0002); |
@@ -6047,16 +5923,9 @@ static void setlightfreq(struct gspca_dev *gspca_dev) | |||
6047 | } | 5923 | } |
6048 | } | 5924 | } |
6049 | 5925 | ||
6050 | static void setautogain(struct gspca_dev *gspca_dev) | 5926 | static void setautogain(struct gspca_dev *gspca_dev, s32 val) |
6051 | { | 5927 | { |
6052 | struct sd *sd = (struct sd *) gspca_dev; | 5928 | reg_w(gspca_dev, val ? 0x42 : 0x02, 0x0180); |
6053 | u8 autoval; | ||
6054 | |||
6055 | if (sd->ctrls[AUTOGAIN].val) | ||
6056 | autoval = 0x42; | ||
6057 | else | ||
6058 | autoval = 0x02; | ||
6059 | reg_w(gspca_dev, autoval, 0x0180); | ||
6060 | } | 5929 | } |
6061 | 5930 | ||
6062 | /* | 5931 | /* |
@@ -6450,7 +6319,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6450 | /* define some sensors from the vendor/product */ | 6319 | /* define some sensors from the vendor/product */ |
6451 | sd->sensor = id->driver_info; | 6320 | sd->sensor = id->driver_info; |
6452 | 6321 | ||
6453 | gspca_dev->cam.ctrls = sd->ctrls; | ||
6454 | sd->reg08 = REG08_DEF; | 6322 | sd->reg08 = REG08_DEF; |
6455 | 6323 | ||
6456 | INIT_WORK(&sd->work, transfer_update); | 6324 | INIT_WORK(&sd->work, transfer_update); |
@@ -6458,12 +6326,85 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6458 | return 0; | 6326 | return 0; |
6459 | } | 6327 | } |
6460 | 6328 | ||
6461 | /* this function is called at probe and resume time */ | 6329 | static int zcxx_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
6462 | static int sd_init(struct gspca_dev *gspca_dev) | ||
6463 | { | 6330 | { |
6464 | struct sd *sd = (struct sd *) gspca_dev; | 6331 | struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler); |
6465 | struct cam *cam; | 6332 | struct gspca_dev *gspca_dev = &sd->gspca_dev; |
6466 | int sensor; | 6333 | |
6334 | switch (ctrl->id) { | ||
6335 | case V4L2_CID_AUTOGAIN: | ||
6336 | gspca_dev->usb_err = 0; | ||
6337 | if (ctrl->val && sd->exposure && gspca_dev->streaming) | ||
6338 | sd->exposure->val = getexposure(gspca_dev); | ||
6339 | return gspca_dev->usb_err; | ||
6340 | } | ||
6341 | return -EINVAL; | ||
6342 | } | ||
6343 | |||
6344 | static int zcxx_s_ctrl(struct v4l2_ctrl *ctrl) | ||
6345 | { | ||
6346 | struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler); | ||
6347 | struct gspca_dev *gspca_dev = &sd->gspca_dev; | ||
6348 | int i, qual; | ||
6349 | |||
6350 | gspca_dev->usb_err = 0; | ||
6351 | |||
6352 | if (ctrl->id == V4L2_CID_JPEG_COMPRESSION_QUALITY) { | ||
6353 | qual = sd->reg08 >> 1; | ||
6354 | |||
6355 | for (i = 0; i < ARRAY_SIZE(jpeg_qual); i++) { | ||
6356 | if (ctrl->val <= jpeg_qual[i]) | ||
6357 | break; | ||
6358 | } | ||
6359 | if (i > 0 && i == qual && ctrl->val < jpeg_qual[i]) | ||
6360 | i--; | ||
6361 | |||
6362 | /* With high quality settings we need max bandwidth */ | ||
6363 | if (i >= 2 && gspca_dev->streaming && | ||
6364 | !gspca_dev->cam.needs_full_bandwidth) | ||
6365 | return -EBUSY; | ||
6366 | |||
6367 | sd->reg08 = (i << 1) | 1; | ||
6368 | ctrl->val = jpeg_qual[i]; | ||
6369 | } | ||
6370 | |||
6371 | if (!gspca_dev->streaming) | ||
6372 | return 0; | ||
6373 | |||
6374 | switch (ctrl->id) { | ||
6375 | /* gamma/brightness/contrast cluster */ | ||
6376 | case V4L2_CID_GAMMA: | ||
6377 | setcontrast(gspca_dev, sd->gamma->val, | ||
6378 | sd->brightness->val, sd->contrast->val); | ||
6379 | break; | ||
6380 | /* autogain/exposure cluster */ | ||
6381 | case V4L2_CID_AUTOGAIN: | ||
6382 | setautogain(gspca_dev, ctrl->val); | ||
6383 | if (!gspca_dev->usb_err && !ctrl->val && sd->exposure) | ||
6384 | setexposure(gspca_dev, sd->exposure->val); | ||
6385 | break; | ||
6386 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
6387 | setlightfreq(gspca_dev, ctrl->val); | ||
6388 | break; | ||
6389 | case V4L2_CID_SHARPNESS: | ||
6390 | setsharpness(gspca_dev, ctrl->val); | ||
6391 | break; | ||
6392 | case V4L2_CID_JPEG_COMPRESSION_QUALITY: | ||
6393 | setquality(gspca_dev); | ||
6394 | break; | ||
6395 | } | ||
6396 | return gspca_dev->usb_err; | ||
6397 | } | ||
6398 | |||
6399 | static const struct v4l2_ctrl_ops zcxx_ctrl_ops = { | ||
6400 | .g_volatile_ctrl = zcxx_g_volatile_ctrl, | ||
6401 | .s_ctrl = zcxx_s_ctrl, | ||
6402 | }; | ||
6403 | |||
6404 | static int sd_init_controls(struct gspca_dev *gspca_dev) | ||
6405 | { | ||
6406 | struct sd *sd = (struct sd *)gspca_dev; | ||
6407 | struct v4l2_ctrl_handler *hdl = &sd->ctrl_handler; | ||
6467 | static const u8 gamma[SENSOR_MAX] = { | 6408 | static const u8 gamma[SENSOR_MAX] = { |
6468 | [SENSOR_ADCM2700] = 4, | 6409 | [SENSOR_ADCM2700] = 4, |
6469 | [SENSOR_CS2102] = 4, | 6410 | [SENSOR_CS2102] = 4, |
@@ -6485,6 +6426,48 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
6485 | [SENSOR_PO2030] = 4, | 6426 | [SENSOR_PO2030] = 4, |
6486 | [SENSOR_TAS5130C] = 3, | 6427 | [SENSOR_TAS5130C] = 3, |
6487 | }; | 6428 | }; |
6429 | |||
6430 | gspca_dev->vdev.ctrl_handler = hdl; | ||
6431 | v4l2_ctrl_handler_init(hdl, 8); | ||
6432 | sd->brightness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, | ||
6433 | V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); | ||
6434 | sd->contrast = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, | ||
6435 | V4L2_CID_CONTRAST, 0, 255, 1, 128); | ||
6436 | sd->gamma = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, | ||
6437 | V4L2_CID_GAMMA, 1, 6, 1, gamma[sd->sensor]); | ||
6438 | if (sd->sensor == SENSOR_HV7131R) | ||
6439 | sd->exposure = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, | ||
6440 | V4L2_CID_EXPOSURE, 0x30d, 0x493e, 1, 0x927); | ||
6441 | sd->autogain = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, | ||
6442 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | ||
6443 | if (sd->sensor != SENSOR_OV7630C) | ||
6444 | sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &zcxx_ctrl_ops, | ||
6445 | V4L2_CID_POWER_LINE_FREQUENCY, | ||
6446 | V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, | ||
6447 | V4L2_CID_POWER_LINE_FREQUENCY_DISABLED); | ||
6448 | sd->sharpness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, | ||
6449 | V4L2_CID_SHARPNESS, 0, 3, 1, | ||
6450 | sd->sensor == SENSOR_PO2030 ? 0 : 2); | ||
6451 | sd->jpegqual = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops, | ||
6452 | V4L2_CID_JPEG_COMPRESSION_QUALITY, | ||
6453 | jpeg_qual[0], jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1], 1, | ||
6454 | jpeg_qual[REG08_DEF >> 1]); | ||
6455 | if (hdl->error) { | ||
6456 | pr_err("Could not initialize controls\n"); | ||
6457 | return hdl->error; | ||
6458 | } | ||
6459 | v4l2_ctrl_cluster(3, &sd->gamma); | ||
6460 | if (sd->sensor == SENSOR_HV7131R) | ||
6461 | v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true); | ||
6462 | return 0; | ||
6463 | } | ||
6464 | |||
6465 | /* this function is called at probe and resume time */ | ||
6466 | static int sd_init(struct gspca_dev *gspca_dev) | ||
6467 | { | ||
6468 | struct sd *sd = (struct sd *) gspca_dev; | ||
6469 | struct cam *cam; | ||
6470 | int sensor; | ||
6488 | static const u8 mode_tb[SENSOR_MAX] = { | 6471 | static const u8 mode_tb[SENSOR_MAX] = { |
6489 | [SENSOR_ADCM2700] = 2, | 6472 | [SENSOR_ADCM2700] = 2, |
6490 | [SENSOR_CS2102] = 1, | 6473 | [SENSOR_CS2102] = 1, |
@@ -6614,7 +6597,6 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
6614 | case 0x2030: | 6597 | case 0x2030: |
6615 | PDEBUG(D_PROBE, "Find Sensor PO2030"); | 6598 | PDEBUG(D_PROBE, "Find Sensor PO2030"); |
6616 | sd->sensor = SENSOR_PO2030; | 6599 | sd->sensor = SENSOR_PO2030; |
6617 | sd->ctrls[SHARPNESS].def = 0; /* from win traces */ | ||
6618 | break; | 6600 | break; |
6619 | case 0x7620: | 6601 | case 0x7620: |
6620 | PDEBUG(D_PROBE, "Find Sensor OV7620"); | 6602 | PDEBUG(D_PROBE, "Find Sensor OV7620"); |
@@ -6656,26 +6638,6 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
6656 | break; | 6638 | break; |
6657 | } | 6639 | } |
6658 | 6640 | ||
6659 | sd->ctrls[GAMMA].def = gamma[sd->sensor]; | ||
6660 | sd->ctrls[QUALITY].def = jpeg_qual[sd->reg08 >> 1]; | ||
6661 | sd->ctrls[QUALITY].min = jpeg_qual[0]; | ||
6662 | sd->ctrls[QUALITY].max = jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1]; | ||
6663 | |||
6664 | switch (sd->sensor) { | ||
6665 | case SENSOR_HV7131R: | ||
6666 | break; | ||
6667 | case SENSOR_OV7630C: | ||
6668 | gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE); | ||
6669 | break; | ||
6670 | default: | ||
6671 | gspca_dev->ctrl_dis = (1 << EXPOSURE); | ||
6672 | break; | ||
6673 | } | ||
6674 | #if AUTOGAIN_DEF | ||
6675 | if (sd->ctrls[AUTOGAIN].val) | ||
6676 | gspca_dev->ctrl_inac = (1 << EXPOSURE); | ||
6677 | #endif | ||
6678 | |||
6679 | /* switch off the led */ | 6641 | /* switch off the led */ |
6680 | reg_w(gspca_dev, 0x01, 0x0000); | 6642 | reg_w(gspca_dev, 0x01, 0x0000); |
6681 | return gspca_dev->usb_err; | 6643 | return gspca_dev->usb_err; |
@@ -6792,7 +6754,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6792 | reg_w(gspca_dev, 0x03, 0x0008); | 6754 | reg_w(gspca_dev, 0x03, 0x0008); |
6793 | break; | 6755 | break; |
6794 | } | 6756 | } |
6795 | setsharpness(gspca_dev); | 6757 | setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness)); |
6796 | 6758 | ||
6797 | /* set the gamma tables when not set */ | 6759 | /* set the gamma tables when not set */ |
6798 | switch (sd->sensor) { | 6760 | switch (sd->sensor) { |
@@ -6801,7 +6763,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6801 | case SENSOR_OV7630C: | 6763 | case SENSOR_OV7630C: |
6802 | break; | 6764 | break; |
6803 | default: | 6765 | default: |
6804 | setcontrast(gspca_dev); | 6766 | setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma), |
6767 | v4l2_ctrl_g_ctrl(sd->brightness), | ||
6768 | v4l2_ctrl_g_ctrl(sd->contrast)); | ||
6805 | break; | 6769 | break; |
6806 | } | 6770 | } |
6807 | setmatrix(gspca_dev); /* one more time? */ | 6771 | setmatrix(gspca_dev); /* one more time? */ |
@@ -6815,7 +6779,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6815 | setquality(gspca_dev); | 6779 | setquality(gspca_dev); |
6816 | /* Start with BRC disabled, transfer_update will enable it if needed */ | 6780 | /* Start with BRC disabled, transfer_update will enable it if needed */ |
6817 | reg_w(gspca_dev, 0x00, 0x0007); | 6781 | reg_w(gspca_dev, 0x00, 0x0007); |
6818 | setlightfreq(gspca_dev); | 6782 | if (sd->plfreq) |
6783 | setlightfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->plfreq)); | ||
6819 | 6784 | ||
6820 | switch (sd->sensor) { | 6785 | switch (sd->sensor) { |
6821 | case SENSOR_ADCM2700: | 6786 | case SENSOR_ADCM2700: |
@@ -6826,7 +6791,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6826 | reg_w(gspca_dev, 0x40, 0x0117); | 6791 | reg_w(gspca_dev, 0x40, 0x0117); |
6827 | break; | 6792 | break; |
6828 | case SENSOR_HV7131R: | 6793 | case SENSOR_HV7131R: |
6829 | setexposure(gspca_dev); | 6794 | setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure)); |
6830 | reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); | 6795 | reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); |
6831 | break; | 6796 | break; |
6832 | case SENSOR_GC0305: | 6797 | case SENSOR_GC0305: |
@@ -6850,7 +6815,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6850 | break; | 6815 | break; |
6851 | } | 6816 | } |
6852 | 6817 | ||
6853 | setautogain(gspca_dev); | 6818 | setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain)); |
6854 | 6819 | ||
6855 | if (gspca_dev->usb_err < 0) | 6820 | if (gspca_dev->usb_err < 0) |
6856 | return gspca_dev->usb_err; | 6821 | return gspca_dev->usb_err; |
@@ -6911,79 +6876,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
6911 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 6876 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
6912 | } | 6877 | } |
6913 | 6878 | ||
6914 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
6915 | { | ||
6916 | struct sd *sd = (struct sd *) gspca_dev; | ||
6917 | |||
6918 | sd->ctrls[AUTOGAIN].val = val; | ||
6919 | if (val) { | ||
6920 | gspca_dev->ctrl_inac |= (1 << EXPOSURE); | ||
6921 | } else { | ||
6922 | gspca_dev->ctrl_inac &= ~(1 << EXPOSURE); | ||
6923 | if (gspca_dev->streaming) | ||
6924 | getexposure(gspca_dev); | ||
6925 | } | ||
6926 | if (gspca_dev->streaming) | ||
6927 | setautogain(gspca_dev); | ||
6928 | return gspca_dev->usb_err; | ||
6929 | } | ||
6930 | |||
6931 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
6932 | struct v4l2_querymenu *menu) | ||
6933 | { | ||
6934 | switch (menu->id) { | ||
6935 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
6936 | switch (menu->index) { | ||
6937 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
6938 | strcpy((char *) menu->name, "NoFliker"); | ||
6939 | return 0; | ||
6940 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
6941 | strcpy((char *) menu->name, "50 Hz"); | ||
6942 | return 0; | ||
6943 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
6944 | strcpy((char *) menu->name, "60 Hz"); | ||
6945 | return 0; | ||
6946 | } | ||
6947 | break; | ||
6948 | } | ||
6949 | return -EINVAL; | ||
6950 | } | ||
6951 | |||
6952 | static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val) | ||
6953 | { | ||
6954 | struct sd *sd = (struct sd *) gspca_dev; | ||
6955 | int i, qual = sd->reg08 >> 1; | ||
6956 | |||
6957 | for (i = 0; i < ARRAY_SIZE(jpeg_qual); i++) { | ||
6958 | if (val <= jpeg_qual[i]) | ||
6959 | break; | ||
6960 | } | ||
6961 | if (i > 0 | ||
6962 | && i == qual | ||
6963 | && val < jpeg_qual[i]) | ||
6964 | i--; | ||
6965 | |||
6966 | /* With high quality settings we need max bandwidth */ | ||
6967 | if (i >= 2 && gspca_dev->streaming && | ||
6968 | !gspca_dev->cam.needs_full_bandwidth) | ||
6969 | return -EBUSY; | ||
6970 | |||
6971 | sd->reg08 = (i << 1) | 1; | ||
6972 | sd->ctrls[QUALITY].val = jpeg_qual[i]; | ||
6973 | |||
6974 | if (gspca_dev->streaming) | ||
6975 | setquality(gspca_dev); | ||
6976 | return gspca_dev->usb_err; | ||
6977 | } | ||
6978 | |||
6979 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, | 6879 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, |
6980 | struct v4l2_jpegcompression *jcomp) | 6880 | struct v4l2_jpegcompression *jcomp) |
6981 | { | 6881 | { |
6982 | struct sd *sd = (struct sd *) gspca_dev; | 6882 | struct sd *sd = (struct sd *) gspca_dev; |
6883 | int ret; | ||
6983 | 6884 | ||
6984 | sd_setquality(gspca_dev, jcomp->quality); | 6885 | ret = v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality); |
6985 | jcomp->quality = sd->ctrls[QUALITY].val; | 6886 | if (ret) |
6986 | return gspca_dev->usb_err; | 6887 | return ret; |
6888 | jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual); | ||
6889 | return 0; | ||
6987 | } | 6890 | } |
6988 | 6891 | ||
6989 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, | 6892 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, |
@@ -6992,7 +6895,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, | |||
6992 | struct sd *sd = (struct sd *) gspca_dev; | 6895 | struct sd *sd = (struct sd *) gspca_dev; |
6993 | 6896 | ||
6994 | memset(jcomp, 0, sizeof *jcomp); | 6897 | memset(jcomp, 0, sizeof *jcomp); |
6995 | jcomp->quality = sd->ctrls[QUALITY].val; | 6898 | jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual); |
6996 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | 6899 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT |
6997 | | V4L2_JPEG_MARKER_DQT; | 6900 | | V4L2_JPEG_MARKER_DQT; |
6998 | return 0; | 6901 | return 0; |
@@ -7016,15 +6919,13 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | |||
7016 | 6919 | ||
7017 | static const struct sd_desc sd_desc = { | 6920 | static const struct sd_desc sd_desc = { |
7018 | .name = KBUILD_MODNAME, | 6921 | .name = KBUILD_MODNAME, |
7019 | .ctrls = sd_ctrls, | ||
7020 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
7021 | .config = sd_config, | 6922 | .config = sd_config, |
7022 | .init = sd_init, | 6923 | .init = sd_init, |
6924 | .init_controls = sd_init_controls, | ||
7023 | .isoc_init = sd_pre_start, | 6925 | .isoc_init = sd_pre_start, |
7024 | .start = sd_start, | 6926 | .start = sd_start, |
7025 | .stop0 = sd_stop0, | 6927 | .stop0 = sd_stop0, |
7026 | .pkt_scan = sd_pkt_scan, | 6928 | .pkt_scan = sd_pkt_scan, |
7027 | .querymenu = sd_querymenu, | ||
7028 | .get_jcomp = sd_get_jcomp, | 6929 | .get_jcomp = sd_get_jcomp, |
7029 | .set_jcomp = sd_set_jcomp, | 6930 | .set_jcomp = sd_set_jcomp, |
7030 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 6931 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
@@ -7108,6 +7009,7 @@ static struct usb_driver sd_driver = { | |||
7108 | #ifdef CONFIG_PM | 7009 | #ifdef CONFIG_PM |
7109 | .suspend = gspca_suspend, | 7010 | .suspend = gspca_suspend, |
7110 | .resume = gspca_resume, | 7011 | .resume = gspca_resume, |
7012 | .reset_resume = gspca_resume, | ||
7111 | #endif | 7013 | #endif |
7112 | }; | 7014 | }; |
7113 | 7015 | ||