diff options
Diffstat (limited to 'drivers/media/video/gspca/m5602/m5602_ov9650.c')
-rw-r--r-- | drivers/media/video/gspca/m5602/m5602_ov9650.c | 570 |
1 files changed, 403 insertions, 167 deletions
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c index c908a8d6970a..fc4548fd441d 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c | |||
@@ -65,14 +65,177 @@ static | |||
65 | DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700") | 65 | DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700") |
66 | } | 66 | } |
67 | }, | 67 | }, |
68 | { } | 68 | {} |
69 | }; | ||
70 | |||
71 | const static struct ctrl ov9650_ctrls[] = { | ||
72 | #define EXPOSURE_IDX 0 | ||
73 | { | ||
74 | { | ||
75 | .id = V4L2_CID_EXPOSURE, | ||
76 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
77 | .name = "exposure", | ||
78 | .minimum = 0x00, | ||
79 | .maximum = 0x1ff, | ||
80 | .step = 0x4, | ||
81 | .default_value = EXPOSURE_DEFAULT, | ||
82 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
83 | }, | ||
84 | .set = ov9650_set_exposure, | ||
85 | .get = ov9650_get_exposure | ||
86 | }, | ||
87 | #define GAIN_IDX 1 | ||
88 | { | ||
89 | { | ||
90 | .id = V4L2_CID_GAIN, | ||
91 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
92 | .name = "gain", | ||
93 | .minimum = 0x00, | ||
94 | .maximum = 0x3ff, | ||
95 | .step = 0x1, | ||
96 | .default_value = GAIN_DEFAULT, | ||
97 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
98 | }, | ||
99 | .set = ov9650_set_gain, | ||
100 | .get = ov9650_get_gain | ||
101 | }, | ||
102 | #define RED_BALANCE_IDX 2 | ||
103 | { | ||
104 | { | ||
105 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
106 | .name = "red balance", | ||
107 | .minimum = 0x00, | ||
108 | .maximum = 0xff, | ||
109 | .step = 0x1, | ||
110 | .default_value = RED_GAIN_DEFAULT, | ||
111 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
112 | }, | ||
113 | .set = ov9650_set_red_balance, | ||
114 | .get = ov9650_get_red_balance | ||
115 | }, | ||
116 | #define BLUE_BALANCE_IDX 3 | ||
117 | { | ||
118 | { | ||
119 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
120 | .name = "blue balance", | ||
121 | .minimum = 0x00, | ||
122 | .maximum = 0xff, | ||
123 | .step = 0x1, | ||
124 | .default_value = BLUE_GAIN_DEFAULT, | ||
125 | .flags = V4L2_CTRL_FLAG_SLIDER | ||
126 | }, | ||
127 | .set = ov9650_set_blue_balance, | ||
128 | .get = ov9650_get_blue_balance | ||
129 | }, | ||
130 | #define HFLIP_IDX 4 | ||
131 | { | ||
132 | { | ||
133 | .id = V4L2_CID_HFLIP, | ||
134 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
135 | .name = "horizontal flip", | ||
136 | .minimum = 0, | ||
137 | .maximum = 1, | ||
138 | .step = 1, | ||
139 | .default_value = 0 | ||
140 | }, | ||
141 | .set = ov9650_set_hflip, | ||
142 | .get = ov9650_get_hflip | ||
143 | }, | ||
144 | #define VFLIP_IDX 5 | ||
145 | { | ||
146 | { | ||
147 | .id = V4L2_CID_VFLIP, | ||
148 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
149 | .name = "vertical flip", | ||
150 | .minimum = 0, | ||
151 | .maximum = 1, | ||
152 | .step = 1, | ||
153 | .default_value = 0 | ||
154 | }, | ||
155 | .set = ov9650_set_vflip, | ||
156 | .get = ov9650_get_vflip | ||
157 | }, | ||
158 | #define AUTO_WHITE_BALANCE_IDX 6 | ||
159 | { | ||
160 | { | ||
161 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
162 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
163 | .name = "auto white balance", | ||
164 | .minimum = 0, | ||
165 | .maximum = 1, | ||
166 | .step = 1, | ||
167 | .default_value = 1 | ||
168 | }, | ||
169 | .set = ov9650_set_auto_white_balance, | ||
170 | .get = ov9650_get_auto_white_balance | ||
171 | }, | ||
172 | #define AUTO_GAIN_CTRL_IDX 7 | ||
173 | { | ||
174 | { | ||
175 | .id = V4L2_CID_AUTOGAIN, | ||
176 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
177 | .name = "auto gain control", | ||
178 | .minimum = 0, | ||
179 | .maximum = 1, | ||
180 | .step = 1, | ||
181 | .default_value = 1 | ||
182 | }, | ||
183 | .set = ov9650_set_auto_gain, | ||
184 | .get = ov9650_get_auto_gain | ||
185 | } | ||
186 | }; | ||
187 | |||
188 | static struct v4l2_pix_format ov9650_modes[] = { | ||
189 | { | ||
190 | 176, | ||
191 | 144, | ||
192 | V4L2_PIX_FMT_SBGGR8, | ||
193 | V4L2_FIELD_NONE, | ||
194 | .sizeimage = | ||
195 | 176 * 144, | ||
196 | .bytesperline = 176, | ||
197 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
198 | .priv = 9 | ||
199 | }, { | ||
200 | 320, | ||
201 | 240, | ||
202 | V4L2_PIX_FMT_SBGGR8, | ||
203 | V4L2_FIELD_NONE, | ||
204 | .sizeimage = | ||
205 | 320 * 240, | ||
206 | .bytesperline = 320, | ||
207 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
208 | .priv = 8 | ||
209 | }, { | ||
210 | 352, | ||
211 | 288, | ||
212 | V4L2_PIX_FMT_SBGGR8, | ||
213 | V4L2_FIELD_NONE, | ||
214 | .sizeimage = | ||
215 | 352 * 288, | ||
216 | .bytesperline = 352, | ||
217 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
218 | .priv = 9 | ||
219 | }, { | ||
220 | 640, | ||
221 | 480, | ||
222 | V4L2_PIX_FMT_SBGGR8, | ||
223 | V4L2_FIELD_NONE, | ||
224 | .sizeimage = | ||
225 | 640 * 480, | ||
226 | .bytesperline = 640, | ||
227 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
228 | .priv = 9 | ||
229 | } | ||
69 | }; | 230 | }; |
70 | 231 | ||
71 | static void ov9650_dump_registers(struct sd *sd); | 232 | static void ov9650_dump_registers(struct sd *sd); |
72 | 233 | ||
73 | int ov9650_probe(struct sd *sd) | 234 | int ov9650_probe(struct sd *sd) |
74 | { | 235 | { |
236 | int err = 0; | ||
75 | u8 prod_id = 0, ver_id = 0, i; | 237 | u8 prod_id = 0, ver_id = 0, i; |
238 | s32 *sensor_settings; | ||
76 | 239 | ||
77 | if (force_sensor) { | 240 | if (force_sensor) { |
78 | if (force_sensor == OV9650_SENSOR) { | 241 | if (force_sensor == OV9650_SENSOR) { |
@@ -86,16 +249,20 @@ int ov9650_probe(struct sd *sd) | |||
86 | 249 | ||
87 | info("Probing for an ov9650 sensor"); | 250 | info("Probing for an ov9650 sensor"); |
88 | 251 | ||
89 | /* Run the pre-init to actually probe the unit */ | 252 | /* Run the pre-init before probing the sensor */ |
90 | for (i = 0; i < ARRAY_SIZE(preinit_ov9650); i++) { | 253 | for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) { |
91 | u8 data = preinit_ov9650[i][2]; | 254 | u8 data = preinit_ov9650[i][2]; |
92 | if (preinit_ov9650[i][0] == SENSOR) | 255 | if (preinit_ov9650[i][0] == SENSOR) |
93 | m5602_write_sensor(sd, | 256 | err = m5602_write_sensor(sd, |
94 | preinit_ov9650[i][1], &data, 1); | 257 | preinit_ov9650[i][1], &data, 1); |
95 | else | 258 | else |
96 | m5602_write_bridge(sd, preinit_ov9650[i][1], data); | 259 | err = m5602_write_bridge(sd, |
260 | preinit_ov9650[i][1], data); | ||
97 | } | 261 | } |
98 | 262 | ||
263 | if (err < 0) | ||
264 | return err; | ||
265 | |||
99 | if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1)) | 266 | if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1)) |
100 | return -ENODEV; | 267 | return -ENODEV; |
101 | 268 | ||
@@ -106,14 +273,28 @@ int ov9650_probe(struct sd *sd) | |||
106 | info("Detected an ov9650 sensor"); | 273 | info("Detected an ov9650 sensor"); |
107 | goto sensor_found; | 274 | goto sensor_found; |
108 | } | 275 | } |
109 | |||
110 | return -ENODEV; | 276 | return -ENODEV; |
111 | 277 | ||
112 | sensor_found: | 278 | sensor_found: |
113 | sd->gspca_dev.cam.cam_mode = ov9650.modes; | 279 | sensor_settings = kmalloc( |
114 | sd->gspca_dev.cam.nmodes = ov9650.nmodes; | 280 | ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL); |
115 | sd->desc->ctrls = ov9650.ctrls; | 281 | if (!sensor_settings) |
116 | sd->desc->nctrls = ov9650.nctrls; | 282 | return -ENOMEM; |
283 | |||
284 | sd->gspca_dev.cam.cam_mode = ov9650_modes; | ||
285 | sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes); | ||
286 | sd->desc->ctrls = ov9650_ctrls; | ||
287 | sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls); | ||
288 | |||
289 | for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++) | ||
290 | sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value; | ||
291 | sd->sensor_priv = sensor_settings; | ||
292 | |||
293 | if (dmi_check_system(ov9650_flip_dmi_table) && !err) { | ||
294 | info("vflip quirk active"); | ||
295 | sensor_settings[VFLIP_IDX] = 1; | ||
296 | } | ||
297 | |||
117 | return 0; | 298 | return 0; |
118 | } | 299 | } |
119 | 300 | ||
@@ -121,6 +302,7 @@ int ov9650_init(struct sd *sd) | |||
121 | { | 302 | { |
122 | int i, err = 0; | 303 | int i, err = 0; |
123 | u8 data; | 304 | u8 data; |
305 | s32 *sensor_settings = sd->sensor_priv; | ||
124 | 306 | ||
125 | if (dump_sensor) | 307 | if (dump_sensor) |
126 | ov9650_dump_registers(sd); | 308 | ov9650_dump_registers(sd); |
@@ -134,70 +316,157 @@ int ov9650_init(struct sd *sd) | |||
134 | err = m5602_write_bridge(sd, init_ov9650[i][1], data); | 316 | err = m5602_write_bridge(sd, init_ov9650[i][1], data); |
135 | } | 317 | } |
136 | 318 | ||
137 | if (dmi_check_system(ov9650_flip_dmi_table) && !err) { | 319 | err = ov9650_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]); |
138 | info("vflip quirk active"); | 320 | if (err < 0) |
139 | data = 0x30; | 321 | return err; |
140 | err = m5602_write_sensor(sd, OV9650_MVFP, &data, 1); | 322 | |
141 | } | 323 | err = ov9650_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); |
324 | if (err < 0) | ||
325 | return err; | ||
326 | |||
327 | err = ov9650_set_red_balance(&sd->gspca_dev, sensor_settings[RED_BALANCE_IDX]); | ||
328 | if (err < 0) | ||
329 | return err; | ||
330 | |||
331 | err = ov9650_set_blue_balance(&sd->gspca_dev, sensor_settings[BLUE_BALANCE_IDX]); | ||
332 | if (err < 0) | ||
333 | return err; | ||
334 | |||
335 | err = ov9650_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); | ||
336 | if (err < 0) | ||
337 | return err; | ||
338 | |||
339 | err = ov9650_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); | ||
340 | if (err < 0) | ||
341 | return err; | ||
342 | |||
343 | err = ov9650_set_auto_white_balance(&sd->gspca_dev, sensor_settings[AUTO_WHITE_BALANCE_IDX]); | ||
344 | if (err < 0) | ||
345 | return err; | ||
346 | |||
347 | err = ov9650_set_auto_gain(&sd->gspca_dev, sensor_settings[AUTO_GAIN_CTRL_IDX]); | ||
142 | return err; | 348 | return err; |
143 | } | 349 | } |
144 | 350 | ||
145 | int ov9650_start(struct sd *sd) | 351 | int ov9650_start(struct sd *sd) |
146 | { | 352 | { |
353 | u8 data; | ||
147 | int i, err = 0; | 354 | int i, err = 0; |
148 | struct cam *cam = &sd->gspca_dev.cam; | 355 | struct cam *cam = &sd->gspca_dev.cam; |
356 | s32 *sensor_settings = sd->sensor_priv; | ||
357 | |||
358 | int width = cam->cam_mode[sd->gspca_dev.curr_mode].width; | ||
359 | int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; | ||
360 | int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv; | ||
361 | int hor_offs = OV9650_LEFT_OFFSET; | ||
362 | |||
363 | if (sensor_settings[VFLIP_IDX]) | ||
364 | ver_offs--; | ||
149 | 365 | ||
366 | if (width <= 320) | ||
367 | hor_offs /= 2; | ||
368 | |||
369 | /* Synthesize the vsync/hsync setup */ | ||
150 | for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { | 370 | for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) { |
151 | u8 data = res_init_ov9650[i][1]; | 371 | if (res_init_ov9650[i][0] == BRIDGE) |
152 | err = m5602_write_bridge(sd, res_init_ov9650[i][0], data); | 372 | err = m5602_write_bridge(sd, res_init_ov9650[i][1], |
373 | res_init_ov9650[i][2]); | ||
374 | else if (res_init_ov9650[i][0] == SENSOR) { | ||
375 | u8 data = res_init_ov9650[i][2]; | ||
376 | err = m5602_write_sensor(sd, | ||
377 | res_init_ov9650[i][1], &data, 1); | ||
378 | } | ||
153 | } | 379 | } |
154 | if (err < 0) | 380 | if (err < 0) |
155 | return err; | 381 | return err; |
156 | 382 | ||
157 | switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) | 383 | err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, |
158 | { | 384 | ((ver_offs >> 8) & 0xff)); |
385 | if (err < 0) | ||
386 | return err; | ||
387 | |||
388 | err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff)); | ||
389 | if (err < 0) | ||
390 | return err; | ||
391 | |||
392 | err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); | ||
393 | if (err < 0) | ||
394 | return err; | ||
395 | |||
396 | err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff); | ||
397 | if (err < 0) | ||
398 | return err; | ||
399 | |||
400 | err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff)); | ||
401 | if (err < 0) | ||
402 | return err; | ||
403 | |||
404 | for (i = 0; i < 2 && !err; i++) | ||
405 | err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0); | ||
406 | if (err < 0) | ||
407 | return err; | ||
408 | |||
409 | err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, | ||
410 | (hor_offs >> 8) & 0xff); | ||
411 | if (err < 0) | ||
412 | return err; | ||
413 | |||
414 | err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff); | ||
415 | if (err < 0) | ||
416 | return err; | ||
417 | |||
418 | err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, | ||
419 | ((width + hor_offs) >> 8) & 0xff); | ||
420 | if (err < 0) | ||
421 | return err; | ||
422 | |||
423 | err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, | ||
424 | ((width + hor_offs) & 0xff)); | ||
425 | if (err < 0) | ||
426 | return err; | ||
427 | |||
428 | switch (width) { | ||
159 | case 640: | 429 | case 640: |
160 | PDEBUG(D_V4L2, "Configuring camera for VGA mode"); | 430 | PDEBUG(D_V4L2, "Configuring camera for VGA mode"); |
161 | 431 | ||
162 | for (i = 0; i < ARRAY_SIZE(VGA_ov9650) && !err; i++) { | 432 | data = OV9650_VGA_SELECT | OV9650_RGB_SELECT | |
163 | u8 data = VGA_ov9650[i][2]; | 433 | OV9650_RAW_RGB_SELECT; |
164 | if (VGA_ov9650[i][0] == SENSOR) | 434 | err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); |
165 | err = m5602_write_sensor(sd, | ||
166 | VGA_ov9650[i][1], &data, 1); | ||
167 | else | ||
168 | err = m5602_write_bridge(sd, VGA_ov9650[i][1], data); | ||
169 | } | ||
170 | break; | 435 | break; |
171 | 436 | ||
172 | case 352: | 437 | case 352: |
173 | PDEBUG(D_V4L2, "Configuring camera for CIF mode"); | 438 | PDEBUG(D_V4L2, "Configuring camera for CIF mode"); |
174 | 439 | ||
175 | for (i = 0; i < ARRAY_SIZE(CIF_ov9650) && !err; i++) { | 440 | data = OV9650_CIF_SELECT | OV9650_RGB_SELECT | |
176 | u8 data = CIF_ov9650[i][2]; | 441 | OV9650_RAW_RGB_SELECT; |
177 | if (CIF_ov9650[i][0] == SENSOR) | 442 | err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); |
178 | err = m5602_write_sensor(sd, | ||
179 | CIF_ov9650[i][1], &data, 1); | ||
180 | else | ||
181 | err = m5602_write_bridge(sd, CIF_ov9650[i][1], data); | ||
182 | } | ||
183 | break; | 443 | break; |
184 | 444 | ||
185 | case 320: | 445 | case 320: |
186 | PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); | 446 | PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); |
187 | 447 | ||
188 | for (i = 0; i < ARRAY_SIZE(QVGA_ov9650) && !err; i++) { | 448 | data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT | |
189 | u8 data = QVGA_ov9650[i][2]; | 449 | OV9650_RAW_RGB_SELECT; |
190 | if (QVGA_ov9650[i][0] == SENSOR) | 450 | err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); |
191 | err = m5602_write_sensor(sd, | 451 | break; |
192 | QVGA_ov9650[i][1], &data, 1); | 452 | |
193 | else | 453 | case 176: |
194 | err = m5602_write_bridge(sd, QVGA_ov9650[i][1], data); | 454 | PDEBUG(D_V4L2, "Configuring camera for QCIF mode"); |
195 | } | 455 | |
456 | data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT | | ||
457 | OV9650_RAW_RGB_SELECT; | ||
458 | err = m5602_write_sensor(sd, OV9650_COM7, &data, 1); | ||
196 | break; | 459 | break; |
197 | } | 460 | } |
198 | return err; | 461 | return err; |
199 | } | 462 | } |
200 | 463 | ||
464 | int ov9650_stop(struct sd *sd) | ||
465 | { | ||
466 | u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X; | ||
467 | return m5602_write_sensor(sd, OV9650_COM2, &data, 1); | ||
468 | } | ||
469 | |||
201 | int ov9650_power_down(struct sd *sd) | 470 | int ov9650_power_down(struct sd *sd) |
202 | { | 471 | { |
203 | int i, err = 0; | 472 | int i, err = 0; |
@@ -214,76 +483,63 @@ int ov9650_power_down(struct sd *sd) | |||
214 | return err; | 483 | return err; |
215 | } | 484 | } |
216 | 485 | ||
217 | int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) | 486 | void ov9650_disconnect(struct sd *sd) |
218 | { | 487 | { |
219 | struct sd *sd = (struct sd *) gspca_dev; | 488 | ov9650_stop(sd); |
220 | u8 i2c_data; | 489 | ov9650_power_down(sd); |
221 | int err; | ||
222 | |||
223 | err = m5602_read_sensor(sd, OV9650_COM1, &i2c_data, 1); | ||
224 | if (err < 0) | ||
225 | goto out; | ||
226 | *val = i2c_data & 0x03; | ||
227 | 490 | ||
228 | err = m5602_read_sensor(sd, OV9650_AECH, &i2c_data, 1); | 491 | sd->sensor = NULL; |
229 | if (err < 0) | 492 | kfree(sd->sensor_priv); |
230 | goto out; | 493 | } |
231 | *val |= (i2c_data << 2); | ||
232 | 494 | ||
233 | err = m5602_read_sensor(sd, OV9650_AECHM, &i2c_data, 1); | 495 | int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) |
234 | if (err < 0) | 496 | { |
235 | goto out; | 497 | struct sd *sd = (struct sd *) gspca_dev; |
236 | *val |= (i2c_data & 0x3f) << 10; | 498 | s32 *sensor_settings = sd->sensor_priv; |
237 | 499 | ||
500 | *val = sensor_settings[EXPOSURE_IDX]; | ||
238 | PDEBUG(D_V4L2, "Read exposure %d", *val); | 501 | PDEBUG(D_V4L2, "Read exposure %d", *val); |
239 | out: | 502 | return 0; |
240 | return err; | ||
241 | } | 503 | } |
242 | 504 | ||
243 | int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | 505 | int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) |
244 | { | 506 | { |
245 | struct sd *sd = (struct sd *) gspca_dev; | 507 | struct sd *sd = (struct sd *) gspca_dev; |
508 | s32 *sensor_settings = sd->sensor_priv; | ||
246 | u8 i2c_data; | 509 | u8 i2c_data; |
247 | int err; | 510 | int err; |
248 | 511 | ||
249 | PDEBUG(D_V4L2, "Set exposure to %d", | 512 | PDEBUG(D_V4L2, "Set exposure to %d", val); |
250 | val & 0xffff); | ||
251 | 513 | ||
514 | sensor_settings[EXPOSURE_IDX] = val; | ||
252 | /* The 6 MSBs */ | 515 | /* The 6 MSBs */ |
253 | i2c_data = (val >> 10) & 0x3f; | 516 | i2c_data = (val >> 10) & 0x3f; |
254 | err = m5602_write_sensor(sd, OV9650_AECHM, | 517 | err = m5602_write_sensor(sd, OV9650_AECHM, |
255 | &i2c_data, 1); | 518 | &i2c_data, 1); |
256 | if (err < 0) | 519 | if (err < 0) |
257 | goto out; | 520 | return err; |
258 | 521 | ||
259 | /* The 8 middle bits */ | 522 | /* The 8 middle bits */ |
260 | i2c_data = (val >> 2) & 0xff; | 523 | i2c_data = (val >> 2) & 0xff; |
261 | err = m5602_write_sensor(sd, OV9650_AECH, | 524 | err = m5602_write_sensor(sd, OV9650_AECH, |
262 | &i2c_data, 1); | 525 | &i2c_data, 1); |
263 | if (err < 0) | 526 | if (err < 0) |
264 | goto out; | 527 | return err; |
265 | 528 | ||
266 | /* The 2 LSBs */ | 529 | /* The 2 LSBs */ |
267 | i2c_data = val & 0x03; | 530 | i2c_data = val & 0x03; |
268 | err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1); | 531 | err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1); |
269 | |||
270 | out: | ||
271 | return err; | 532 | return err; |
272 | } | 533 | } |
273 | 534 | ||
274 | int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | 535 | int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) |
275 | { | 536 | { |
276 | int err; | ||
277 | u8 i2c_data; | ||
278 | struct sd *sd = (struct sd *) gspca_dev; | 537 | struct sd *sd = (struct sd *) gspca_dev; |
538 | s32 *sensor_settings = sd->sensor_priv; | ||
279 | 539 | ||
280 | m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | 540 | *val = sensor_settings[GAIN_IDX]; |
281 | *val = (i2c_data & 0x03) << 8; | ||
282 | |||
283 | err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); | ||
284 | *val |= i2c_data; | ||
285 | PDEBUG(D_V4L2, "Read gain %d", *val); | 541 | PDEBUG(D_V4L2, "Read gain %d", *val); |
286 | return err; | 542 | return 0; |
287 | } | 543 | } |
288 | 544 | ||
289 | int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) | 545 | int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) |
@@ -291,15 +547,25 @@ int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) | |||
291 | int err; | 547 | int err; |
292 | u8 i2c_data; | 548 | u8 i2c_data; |
293 | struct sd *sd = (struct sd *) gspca_dev; | 549 | struct sd *sd = (struct sd *) gspca_dev; |
550 | s32 *sensor_settings = sd->sensor_priv; | ||
551 | |||
552 | PDEBUG(D_V4L2, "Setting gain to %d", val); | ||
553 | |||
554 | sensor_settings[GAIN_IDX] = val; | ||
294 | 555 | ||
295 | /* The 2 MSB */ | 556 | /* The 2 MSB */ |
296 | /* Read the OV9650_VREF register first to avoid | 557 | /* Read the OV9650_VREF register first to avoid |
297 | corrupting the VREF high and low bits */ | 558 | corrupting the VREF high and low bits */ |
298 | m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | 559 | err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); |
560 | if (err < 0) | ||
561 | return err; | ||
562 | |||
299 | /* Mask away all uninteresting bits */ | 563 | /* Mask away all uninteresting bits */ |
300 | i2c_data = ((val & 0x0300) >> 2) | | 564 | i2c_data = ((val & 0x0300) >> 2) | |
301 | (i2c_data & 0x3F); | 565 | (i2c_data & 0x3F); |
302 | err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); | 566 | err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); |
567 | if (err < 0) | ||
568 | return err; | ||
303 | 569 | ||
304 | /* The 8 LSBs */ | 570 | /* The 8 LSBs */ |
305 | i2c_data = val & 0xff; | 571 | i2c_data = val & 0xff; |
@@ -309,16 +575,12 @@ int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) | |||
309 | 575 | ||
310 | int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) | 576 | int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) |
311 | { | 577 | { |
312 | int err; | ||
313 | u8 i2c_data; | ||
314 | struct sd *sd = (struct sd *) gspca_dev; | 578 | struct sd *sd = (struct sd *) gspca_dev; |
579 | s32 *sensor_settings = sd->sensor_priv; | ||
315 | 580 | ||
316 | err = m5602_read_sensor(sd, OV9650_RED, &i2c_data, 1); | 581 | *val = sensor_settings[RED_BALANCE_IDX]; |
317 | *val = i2c_data; | ||
318 | |||
319 | PDEBUG(D_V4L2, "Read red gain %d", *val); | 582 | PDEBUG(D_V4L2, "Read red gain %d", *val); |
320 | 583 | return 0; | |
321 | return err; | ||
322 | } | 584 | } |
323 | 585 | ||
324 | int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) | 586 | int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) |
@@ -326,28 +588,26 @@ int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) | |||
326 | int err; | 588 | int err; |
327 | u8 i2c_data; | 589 | u8 i2c_data; |
328 | struct sd *sd = (struct sd *) gspca_dev; | 590 | struct sd *sd = (struct sd *) gspca_dev; |
591 | s32 *sensor_settings = sd->sensor_priv; | ||
329 | 592 | ||
330 | PDEBUG(D_V4L2, "Set red gain to %d", | 593 | PDEBUG(D_V4L2, "Set red gain to %d", val); |
331 | val & 0xff); | 594 | |
595 | sensor_settings[RED_BALANCE_IDX] = val; | ||
332 | 596 | ||
333 | i2c_data = val & 0xff; | 597 | i2c_data = val & 0xff; |
334 | err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1); | 598 | err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1); |
335 | |||
336 | return err; | 599 | return err; |
337 | } | 600 | } |
338 | 601 | ||
339 | int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) | 602 | int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) |
340 | { | 603 | { |
341 | int err; | ||
342 | u8 i2c_data; | ||
343 | struct sd *sd = (struct sd *) gspca_dev; | 604 | struct sd *sd = (struct sd *) gspca_dev; |
605 | s32 *sensor_settings = sd->sensor_priv; | ||
344 | 606 | ||
345 | err = m5602_read_sensor(sd, OV9650_BLUE, &i2c_data, 1); | 607 | *val = sensor_settings[BLUE_BALANCE_IDX]; |
346 | *val = i2c_data; | ||
347 | |||
348 | PDEBUG(D_V4L2, "Read blue gain %d", *val); | 608 | PDEBUG(D_V4L2, "Read blue gain %d", *val); |
349 | 609 | ||
350 | return err; | 610 | return 0; |
351 | } | 611 | } |
352 | 612 | ||
353 | int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) | 613 | int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) |
@@ -355,30 +615,25 @@ int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) | |||
355 | int err; | 615 | int err; |
356 | u8 i2c_data; | 616 | u8 i2c_data; |
357 | struct sd *sd = (struct sd *) gspca_dev; | 617 | struct sd *sd = (struct sd *) gspca_dev; |
618 | s32 *sensor_settings = sd->sensor_priv; | ||
619 | |||
620 | PDEBUG(D_V4L2, "Set blue gain to %d", val); | ||
358 | 621 | ||
359 | PDEBUG(D_V4L2, "Set blue gain to %d", | 622 | sensor_settings[BLUE_BALANCE_IDX] = val; |
360 | val & 0xff); | ||
361 | 623 | ||
362 | i2c_data = val & 0xff; | 624 | i2c_data = val & 0xff; |
363 | err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); | 625 | err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); |
364 | |||
365 | return err; | 626 | return err; |
366 | } | 627 | } |
367 | 628 | ||
368 | int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | 629 | int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) |
369 | { | 630 | { |
370 | int err; | ||
371 | u8 i2c_data; | ||
372 | struct sd *sd = (struct sd *) gspca_dev; | 631 | struct sd *sd = (struct sd *) gspca_dev; |
632 | s32 *sensor_settings = sd->sensor_priv; | ||
373 | 633 | ||
374 | err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | 634 | *val = sensor_settings[HFLIP_IDX]; |
375 | if (dmi_check_system(ov9650_flip_dmi_table)) | ||
376 | *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1; | ||
377 | else | ||
378 | *val = (i2c_data & OV9650_HFLIP) >> 5; | ||
379 | PDEBUG(D_V4L2, "Read horizontal flip %d", *val); | 635 | PDEBUG(D_V4L2, "Read horizontal flip %d", *val); |
380 | 636 | return 0; | |
381 | return err; | ||
382 | } | 637 | } |
383 | 638 | ||
384 | int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | 639 | int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) |
@@ -386,38 +641,26 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | |||
386 | int err; | 641 | int err; |
387 | u8 i2c_data; | 642 | u8 i2c_data; |
388 | struct sd *sd = (struct sd *) gspca_dev; | 643 | struct sd *sd = (struct sd *) gspca_dev; |
644 | s32 *sensor_settings = sd->sensor_priv; | ||
389 | 645 | ||
390 | PDEBUG(D_V4L2, "Set horizontal flip to %d", val); | 646 | PDEBUG(D_V4L2, "Set horizontal flip to %d", val); |
391 | err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
392 | if (err < 0) | ||
393 | goto out; | ||
394 | |||
395 | if (dmi_check_system(ov9650_flip_dmi_table)) | ||
396 | i2c_data = ((i2c_data & 0xdf) | | ||
397 | (((val ? 0 : 1) & 0x01) << 5)); | ||
398 | else | ||
399 | i2c_data = ((i2c_data & 0xdf) | | ||
400 | ((val & 0x01) << 5)); | ||
401 | 647 | ||
648 | sensor_settings[HFLIP_IDX] = val; | ||
649 | i2c_data = ((val & 0x01) << 5) | (sensor_settings[VFLIP_IDX] << 4); | ||
402 | err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); | 650 | err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); |
403 | out: | 651 | |
404 | return err; | 652 | return err; |
405 | } | 653 | } |
406 | 654 | ||
407 | int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) | 655 | int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) |
408 | { | 656 | { |
409 | int err; | ||
410 | u8 i2c_data; | ||
411 | struct sd *sd = (struct sd *) gspca_dev; | 657 | struct sd *sd = (struct sd *) gspca_dev; |
658 | s32 *sensor_settings = sd->sensor_priv; | ||
412 | 659 | ||
413 | err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | 660 | *val = sensor_settings[VFLIP_IDX]; |
414 | if (dmi_check_system(ov9650_flip_dmi_table)) | ||
415 | *val = ((i2c_data & 0x10) >> 4) ? 0 : 1; | ||
416 | else | ||
417 | *val = (i2c_data & 0x10) >> 4; | ||
418 | PDEBUG(D_V4L2, "Read vertical flip %d", *val); | 661 | PDEBUG(D_V4L2, "Read vertical flip %d", *val); |
419 | 662 | ||
420 | return err; | 663 | return 0; |
421 | } | 664 | } |
422 | 665 | ||
423 | int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | 666 | int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) |
@@ -425,40 +668,32 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | |||
425 | int err; | 668 | int err; |
426 | u8 i2c_data; | 669 | u8 i2c_data; |
427 | struct sd *sd = (struct sd *) gspca_dev; | 670 | struct sd *sd = (struct sd *) gspca_dev; |
671 | s32 *sensor_settings = sd->sensor_priv; | ||
428 | 672 | ||
429 | PDEBUG(D_V4L2, "Set vertical flip to %d", val); | 673 | PDEBUG(D_V4L2, "Set vertical flip to %d", val); |
430 | err = m5602_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); | 674 | sensor_settings[VFLIP_IDX] = val; |
675 | |||
676 | i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5); | ||
677 | err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
431 | if (err < 0) | 678 | if (err < 0) |
432 | goto out; | 679 | return err; |
433 | 680 | ||
434 | if (dmi_check_system(ov9650_flip_dmi_table)) | 681 | /* When vflip is toggled we need to readjust the bridge hsync/vsync */ |
435 | i2c_data = ((i2c_data & 0xef) | | 682 | if (gspca_dev->streaming) |
436 | (((val ? 0 : 1) & 0x01) << 4)); | 683 | err = ov9650_start(sd); |
437 | else | ||
438 | i2c_data = ((i2c_data & 0xef) | | ||
439 | ((val & 0x01) << 4)); | ||
440 | 684 | ||
441 | err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); | ||
442 | out: | ||
443 | return err; | 685 | return err; |
444 | } | 686 | } |
445 | 687 | ||
446 | int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) | 688 | int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) |
447 | { | 689 | { |
448 | int err; | ||
449 | u8 i2c_data; | ||
450 | struct sd *sd = (struct sd *) gspca_dev; | 690 | struct sd *sd = (struct sd *) gspca_dev; |
691 | s32 *sensor_settings = sd->sensor_priv; | ||
451 | 692 | ||
452 | err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | 693 | *val = sensor_settings[GAIN_IDX]; |
453 | if (err < 0) | ||
454 | goto out; | ||
455 | *val = (i2c_data & 0x03) << 8; | ||
456 | |||
457 | err = m5602_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); | ||
458 | *val |= i2c_data; | ||
459 | PDEBUG(D_V4L2, "Read gain %d", *val); | 694 | PDEBUG(D_V4L2, "Read gain %d", *val); |
460 | out: | 695 | |
461 | return err; | 696 | return 0; |
462 | } | 697 | } |
463 | 698 | ||
464 | int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) | 699 | int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) |
@@ -466,40 +701,38 @@ int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) | |||
466 | int err; | 701 | int err; |
467 | u8 i2c_data; | 702 | u8 i2c_data; |
468 | struct sd *sd = (struct sd *) gspca_dev; | 703 | struct sd *sd = (struct sd *) gspca_dev; |
704 | s32 *sensor_settings = sd->sensor_priv; | ||
469 | 705 | ||
470 | PDEBUG(D_V4L2, "Set gain to %d", val & 0x3ff); | 706 | PDEBUG(D_V4L2, "Set gain to %d", val); |
707 | |||
708 | sensor_settings[GAIN_IDX] = val; | ||
471 | 709 | ||
472 | /* Read the OV9650_VREF register first to avoid | 710 | /* Read the OV9650_VREF register first to avoid |
473 | corrupting the VREF high and low bits */ | 711 | corrupting the VREF high and low bits */ |
474 | err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); | 712 | err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1); |
475 | if (err < 0) | 713 | if (err < 0) |
476 | goto out; | 714 | return err; |
477 | 715 | ||
478 | /* Mask away all uninteresting bits */ | 716 | /* Mask away all uninteresting bits */ |
479 | i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F); | 717 | i2c_data = ((val & 0x0300) >> 2) | (i2c_data & 0x3F); |
480 | err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); | 718 | err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1); |
481 | if (err < 0) | 719 | if (err < 0) |
482 | goto out; | 720 | return err; |
483 | 721 | ||
484 | /* The 8 LSBs */ | 722 | /* The 8 LSBs */ |
485 | i2c_data = val & 0xff; | 723 | i2c_data = val & 0xff; |
486 | err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); | 724 | err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1); |
487 | 725 | ||
488 | out: | ||
489 | return err; | 726 | return err; |
490 | } | 727 | } |
491 | 728 | ||
492 | int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) | 729 | int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) |
493 | { | 730 | { |
494 | int err; | ||
495 | u8 i2c_data; | ||
496 | struct sd *sd = (struct sd *) gspca_dev; | 731 | struct sd *sd = (struct sd *) gspca_dev; |
732 | s32 *sensor_settings = sd->sensor_priv; | ||
497 | 733 | ||
498 | err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | 734 | *val = sensor_settings[AUTO_WHITE_BALANCE_IDX]; |
499 | *val = (i2c_data & OV9650_AWB_EN) >> 1; | 735 | return 0; |
500 | PDEBUG(D_V4L2, "Read auto white balance %d", *val); | ||
501 | |||
502 | return err; | ||
503 | } | 736 | } |
504 | 737 | ||
505 | int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) | 738 | int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) |
@@ -507,29 +740,29 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) | |||
507 | int err; | 740 | int err; |
508 | u8 i2c_data; | 741 | u8 i2c_data; |
509 | struct sd *sd = (struct sd *) gspca_dev; | 742 | struct sd *sd = (struct sd *) gspca_dev; |
743 | s32 *sensor_settings = sd->sensor_priv; | ||
510 | 744 | ||
511 | PDEBUG(D_V4L2, "Set auto white balance to %d", val); | 745 | PDEBUG(D_V4L2, "Set auto white balance to %d", val); |
746 | |||
747 | sensor_settings[AUTO_WHITE_BALANCE_IDX] = val; | ||
512 | err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | 748 | err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); |
513 | if (err < 0) | 749 | if (err < 0) |
514 | goto out; | 750 | return err; |
515 | 751 | ||
516 | i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); | 752 | i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1)); |
517 | err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); | 753 | err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); |
518 | out: | 754 | |
519 | return err; | 755 | return err; |
520 | } | 756 | } |
521 | 757 | ||
522 | int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) | 758 | int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) |
523 | { | 759 | { |
524 | int err; | ||
525 | u8 i2c_data; | ||
526 | struct sd *sd = (struct sd *) gspca_dev; | 760 | struct sd *sd = (struct sd *) gspca_dev; |
761 | s32 *sensor_settings = sd->sensor_priv; | ||
527 | 762 | ||
528 | err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | 763 | *val = sensor_settings[AUTO_GAIN_CTRL_IDX]; |
529 | *val = (i2c_data & OV9650_AGC_EN) >> 2; | ||
530 | PDEBUG(D_V4L2, "Read auto gain control %d", *val); | 764 | PDEBUG(D_V4L2, "Read auto gain control %d", *val); |
531 | 765 | return 0; | |
532 | return err; | ||
533 | } | 766 | } |
534 | 767 | ||
535 | int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) | 768 | int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) |
@@ -537,15 +770,18 @@ int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) | |||
537 | int err; | 770 | int err; |
538 | u8 i2c_data; | 771 | u8 i2c_data; |
539 | struct sd *sd = (struct sd *) gspca_dev; | 772 | struct sd *sd = (struct sd *) gspca_dev; |
773 | s32 *sensor_settings = sd->sensor_priv; | ||
540 | 774 | ||
541 | PDEBUG(D_V4L2, "Set auto gain control to %d", val); | 775 | PDEBUG(D_V4L2, "Set auto gain control to %d", val); |
776 | |||
777 | sensor_settings[AUTO_GAIN_CTRL_IDX] = val; | ||
542 | err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); | 778 | err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); |
543 | if (err < 0) | 779 | if (err < 0) |
544 | goto out; | 780 | return err; |
545 | 781 | ||
546 | i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); | 782 | i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2)); |
547 | err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); | 783 | err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); |
548 | out: | 784 | |
549 | return err; | 785 | return err; |
550 | } | 786 | } |
551 | 787 | ||