aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_bridge.h27
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_core.c16
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_mt9m111.c388
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_mt9m111.h2
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_ov7660.c300
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_ov7660.h3
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_ov9650.c445
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_ov9650.h2
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_po1030.c452
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_po1030.h2
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_s5k4aa.c338
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_s5k4aa.h2
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_s5k83a.c290
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_s5k83a.h9
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_sensor.h3
15 files changed, 569 insertions, 1710 deletions
diff --git a/drivers/media/usb/gspca/m5602/m5602_bridge.h b/drivers/media/usb/gspca/m5602/m5602_bridge.h
index 51af3ee3ab85..19eb1a64f9d6 100644
--- a/drivers/media/usb/gspca/m5602/m5602_bridge.h
+++ b/drivers/media/usb/gspca/m5602/m5602_bridge.h
@@ -136,16 +136,33 @@ struct sd {
136 /* A pointer to the currently connected sensor */ 136 /* A pointer to the currently connected sensor */
137 const struct m5602_sensor *sensor; 137 const struct m5602_sensor *sensor;
138 138
139 struct sd_desc *desc;
140
141 /* Sensor private data */
142 void *sensor_priv;
143
144 /* The current frame's id, used to detect frame boundaries */ 139 /* The current frame's id, used to detect frame boundaries */
145 u8 frame_id; 140 u8 frame_id;
146 141
147 /* The current frame count */ 142 /* The current frame count */
148 u32 frame_count; 143 u32 frame_count;
144
145 /* Camera rotation polling thread for "flipable" cams */
146 struct task_struct *rotation_thread;
147
148 struct { /* auto-white-bal + green/red/blue balance control cluster */
149 struct v4l2_ctrl *auto_white_bal;
150 struct v4l2_ctrl *red_bal;
151 struct v4l2_ctrl *blue_bal;
152 struct v4l2_ctrl *green_bal;
153 };
154 struct { /* autoexpo / expo cluster */
155 struct v4l2_ctrl *autoexpo;
156 struct v4l2_ctrl *expo;
157 };
158 struct { /* autogain / gain cluster */
159 struct v4l2_ctrl *autogain;
160 struct v4l2_ctrl *gain;
161 };
162 struct { /* hflip/vflip cluster */
163 struct v4l2_ctrl *hflip;
164 struct v4l2_ctrl *vflip;
165 };
149}; 166};
150 167
151int m5602_read_bridge( 168int m5602_read_bridge(
diff --git a/drivers/media/usb/gspca/m5602/m5602_core.c b/drivers/media/usb/gspca/m5602/m5602_core.c
index ed22638978ce..907a968f474d 100644
--- a/drivers/media/usb/gspca/m5602/m5602_core.c
+++ b/drivers/media/usb/gspca/m5602/m5602_core.c
@@ -252,6 +252,16 @@ static int m5602_init(struct gspca_dev *gspca_dev)
252 return err; 252 return err;
253} 253}
254 254
255static int m5602_init_controls(struct gspca_dev *gspca_dev)
256{
257 struct sd *sd = (struct sd *) gspca_dev;
258
259 if (!sd->sensor->init_controls)
260 return 0;
261
262 return sd->sensor->init_controls(sd);
263}
264
255static int m5602_start_transfer(struct gspca_dev *gspca_dev) 265static int m5602_start_transfer(struct gspca_dev *gspca_dev)
256{ 266{
257 struct sd *sd = (struct sd *) gspca_dev; 267 struct sd *sd = (struct sd *) gspca_dev;
@@ -336,11 +346,12 @@ static void m5602_stop_transfer(struct gspca_dev *gspca_dev)
336 sd->sensor->stop(sd); 346 sd->sensor->stop(sd);
337} 347}
338 348
339/* sub-driver description, the ctrl and nctrl is filled at probe time */ 349/* sub-driver description */
340static struct sd_desc sd_desc = { 350static const struct sd_desc sd_desc = {
341 .name = MODULE_NAME, 351 .name = MODULE_NAME,
342 .config = m5602_configure, 352 .config = m5602_configure,
343 .init = m5602_init, 353 .init = m5602_init,
354 .init_controls = m5602_init_controls,
344 .start = m5602_start_transfer, 355 .start = m5602_start_transfer,
345 .stopN = m5602_stop_transfer, 356 .stopN = m5602_stop_transfer,
346 .pkt_scan = m5602_urb_complete 357 .pkt_scan = m5602_urb_complete
@@ -355,7 +366,6 @@ static int m5602_configure(struct gspca_dev *gspca_dev,
355 int err; 366 int err;
356 367
357 cam = &gspca_dev->cam; 368 cam = &gspca_dev->cam;
358 sd->desc = &sd_desc;
359 369
360 if (dump_bridge) 370 if (dump_bridge)
361 m5602_dump_bridge(sd); 371 m5602_dump_bridge(sd);
diff --git a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
index 6268aa24ec5d..b5f66921b3eb 100644
--- a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
+++ b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
@@ -20,22 +20,8 @@
20 20
21#include "m5602_mt9m111.h" 21#include "m5602_mt9m111.h"
22 22
23static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); 23static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl);
24static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); 24static void mt9m111_dump_registers(struct sd *sd);
25static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
26static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
27static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
28static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
29static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
30 __s32 val);
31static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
32 __s32 *val);
33static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
34static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
35static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
36static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
37static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
38static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
39 25
40static struct v4l2_pix_format mt9m111_modes[] = { 26static struct v4l2_pix_format mt9m111_modes[] = {
41 { 27 {
@@ -50,118 +36,26 @@ static struct v4l2_pix_format mt9m111_modes[] = {
50 } 36 }
51}; 37};
52 38
53static const struct ctrl mt9m111_ctrls[] = { 39static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = {
54#define VFLIP_IDX 0 40 .s_ctrl = mt9m111_s_ctrl,
55 {
56 {
57 .id = V4L2_CID_VFLIP,
58 .type = V4L2_CTRL_TYPE_BOOLEAN,
59 .name = "vertical flip",
60 .minimum = 0,
61 .maximum = 1,
62 .step = 1,
63 .default_value = 0
64 },
65 .set = mt9m111_set_vflip,
66 .get = mt9m111_get_vflip
67 },
68#define HFLIP_IDX 1
69 {
70 {
71 .id = V4L2_CID_HFLIP,
72 .type = V4L2_CTRL_TYPE_BOOLEAN,
73 .name = "horizontal flip",
74 .minimum = 0,
75 .maximum = 1,
76 .step = 1,
77 .default_value = 0
78 },
79 .set = mt9m111_set_hflip,
80 .get = mt9m111_get_hflip
81 },
82#define GAIN_IDX 2
83 {
84 {
85 .id = V4L2_CID_GAIN,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "gain",
88 .minimum = 0,
89 .maximum = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
90 .step = 1,
91 .default_value = MT9M111_DEFAULT_GAIN,
92 .flags = V4L2_CTRL_FLAG_SLIDER
93 },
94 .set = mt9m111_set_gain,
95 .get = mt9m111_get_gain
96 },
97#define AUTO_WHITE_BALANCE_IDX 3
98 {
99 {
100 .id = V4L2_CID_AUTO_WHITE_BALANCE,
101 .type = V4L2_CTRL_TYPE_BOOLEAN,
102 .name = "auto white balance",
103 .minimum = 0,
104 .maximum = 1,
105 .step = 1,
106 .default_value = 0,
107 },
108 .set = mt9m111_set_auto_white_balance,
109 .get = mt9m111_get_auto_white_balance
110 },
111#define GREEN_BALANCE_IDX 4
112 {
113 {
114 .id = M5602_V4L2_CID_GREEN_BALANCE,
115 .type = V4L2_CTRL_TYPE_INTEGER,
116 .name = "green balance",
117 .minimum = 0x00,
118 .maximum = 0x7ff,
119 .step = 0x1,
120 .default_value = MT9M111_GREEN_GAIN_DEFAULT,
121 .flags = V4L2_CTRL_FLAG_SLIDER
122 },
123 .set = mt9m111_set_green_balance,
124 .get = mt9m111_get_green_balance
125 },
126#define BLUE_BALANCE_IDX 5
127 {
128 {
129 .id = V4L2_CID_BLUE_BALANCE,
130 .type = V4L2_CTRL_TYPE_INTEGER,
131 .name = "blue balance",
132 .minimum = 0x00,
133 .maximum = 0x7ff,
134 .step = 0x1,
135 .default_value = MT9M111_BLUE_GAIN_DEFAULT,
136 .flags = V4L2_CTRL_FLAG_SLIDER
137 },
138 .set = mt9m111_set_blue_balance,
139 .get = mt9m111_get_blue_balance
140 },
141#define RED_BALANCE_IDX 5
142 {
143 {
144 .id = V4L2_CID_RED_BALANCE,
145 .type = V4L2_CTRL_TYPE_INTEGER,
146 .name = "red balance",
147 .minimum = 0x00,
148 .maximum = 0x7ff,
149 .step = 0x1,
150 .default_value = MT9M111_RED_GAIN_DEFAULT,
151 .flags = V4L2_CTRL_FLAG_SLIDER
152 },
153 .set = mt9m111_set_red_balance,
154 .get = mt9m111_get_red_balance
155 },
156}; 41};
157 42
158static void mt9m111_dump_registers(struct sd *sd); 43static const struct v4l2_ctrl_config mt9m111_greenbal_cfg = {
44 .ops = &mt9m111_ctrl_ops,
45 .id = M5602_V4L2_CID_GREEN_BALANCE,
46 .name = "Green Balance",
47 .type = V4L2_CTRL_TYPE_INTEGER,
48 .min = 0,
49 .max = 0x7ff,
50 .step = 1,
51 .def = MT9M111_GREEN_GAIN_DEFAULT,
52 .flags = V4L2_CTRL_FLAG_SLIDER,
53};
159 54
160int mt9m111_probe(struct sd *sd) 55int mt9m111_probe(struct sd *sd)
161{ 56{
162 u8 data[2] = {0x00, 0x00}; 57 u8 data[2] = {0x00, 0x00};
163 int i; 58 int i;
164 s32 *sensor_settings;
165 59
166 if (force_sensor) { 60 if (force_sensor) {
167 if (force_sensor == MT9M111_SENSOR) { 61 if (force_sensor == MT9M111_SENSOR) {
@@ -200,19 +94,8 @@ int mt9m111_probe(struct sd *sd)
200 return -ENODEV; 94 return -ENODEV;
201 95
202sensor_found: 96sensor_found:
203 sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32),
204 GFP_KERNEL);
205 if (!sensor_settings)
206 return -ENOMEM;
207
208 sd->gspca_dev.cam.cam_mode = mt9m111_modes; 97 sd->gspca_dev.cam.cam_mode = mt9m111_modes;
209 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes); 98 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
210 sd->desc->ctrls = mt9m111_ctrls;
211 sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
212
213 for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++)
214 sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value;
215 sd->sensor_priv = sensor_settings;
216 99
217 return 0; 100 return 0;
218} 101}
@@ -220,7 +103,6 @@ sensor_found:
220int mt9m111_init(struct sd *sd) 103int mt9m111_init(struct sd *sd)
221{ 104{
222 int i, err = 0; 105 int i, err = 0;
223 s32 *sensor_settings = sd->sensor_priv;
224 106
225 /* Init the sensor */ 107 /* Init the sensor */
226 for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) { 108 for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
@@ -241,30 +123,45 @@ int mt9m111_init(struct sd *sd)
241 if (dump_sensor) 123 if (dump_sensor)
242 mt9m111_dump_registers(sd); 124 mt9m111_dump_registers(sd);
243 125
244 err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); 126 return 0;
245 if (err < 0) 127}
246 return err;
247
248 err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
249 if (err < 0)
250 return err;
251
252 err = mt9m111_set_green_balance(&sd->gspca_dev,
253 sensor_settings[GREEN_BALANCE_IDX]);
254 if (err < 0)
255 return err;
256 128
257 err = mt9m111_set_blue_balance(&sd->gspca_dev, 129int mt9m111_init_controls(struct sd *sd)
258 sensor_settings[BLUE_BALANCE_IDX]); 130{
259 if (err < 0) 131 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
260 return err; 132
133 sd->gspca_dev.vdev.ctrl_handler = hdl;
134 v4l2_ctrl_handler_init(hdl, 7);
135
136 sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
137 V4L2_CID_AUTO_WHITE_BALANCE,
138 0, 1, 1, 0);
139 sd->green_bal = v4l2_ctrl_new_custom(hdl, &mt9m111_greenbal_cfg, NULL);
140 sd->red_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
141 V4L2_CID_RED_BALANCE, 0, 0x7ff, 1,
142 MT9M111_RED_GAIN_DEFAULT);
143 sd->blue_bal = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops,
144 V4L2_CID_BLUE_BALANCE, 0, 0x7ff, 1,
145 MT9M111_BLUE_GAIN_DEFAULT);
146
147 v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_GAIN, 0,
148 (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2, 1,
149 MT9M111_DEFAULT_GAIN);
150
151 sd->hflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_HFLIP,
152 0, 1, 1, 0);
153 sd->vflip = v4l2_ctrl_new_std(hdl, &mt9m111_ctrl_ops, V4L2_CID_VFLIP,
154 0, 1, 1, 0);
155
156 if (hdl->error) {
157 pr_err("Could not initialize controls\n");
158 return hdl->error;
159 }
261 160
262 err = mt9m111_set_red_balance(&sd->gspca_dev, 161 v4l2_ctrl_auto_cluster(4, &sd->auto_white_bal, 0, false);
263 sensor_settings[RED_BALANCE_IDX]); 162 v4l2_ctrl_cluster(2, &sd->hflip);
264 if (err < 0)
265 return err;
266 163
267 return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); 164 return 0;
268} 165}
269 166
270int mt9m111_start(struct sd *sd) 167int mt9m111_start(struct sd *sd)
@@ -272,7 +169,6 @@ int mt9m111_start(struct sd *sd)
272 int i, err = 0; 169 int i, err = 0;
273 u8 data[2]; 170 u8 data[2];
274 struct cam *cam = &sd->gspca_dev.cam; 171 struct cam *cam = &sd->gspca_dev.cam;
275 s32 *sensor_settings = sd->sensor_priv;
276 172
277 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1; 173 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
278 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; 174 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
@@ -334,25 +230,10 @@ int mt9m111_start(struct sd *sd)
334 switch (width) { 230 switch (width) {
335 case 640: 231 case 640:
336 PDEBUG(D_V4L2, "Configuring camera for VGA mode"); 232 PDEBUG(D_V4L2, "Configuring camera for VGA mode");
337 data[0] = MT9M111_RMB_OVER_SIZED;
338 data[1] = MT9M111_RMB_ROW_SKIP_2X |
339 MT9M111_RMB_COLUMN_SKIP_2X |
340 (sensor_settings[VFLIP_IDX] << 0) |
341 (sensor_settings[HFLIP_IDX] << 1);
342
343 err = m5602_write_sensor(sd,
344 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
345 break; 233 break;
346 234
347 case 320: 235 case 320:
348 PDEBUG(D_V4L2, "Configuring camera for QVGA mode"); 236 PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
349 data[0] = MT9M111_RMB_OVER_SIZED;
350 data[1] = MT9M111_RMB_ROW_SKIP_4X |
351 MT9M111_RMB_COLUMN_SKIP_4X |
352 (sensor_settings[VFLIP_IDX] << 0) |
353 (sensor_settings[HFLIP_IDX] << 1);
354 err = m5602_write_sensor(sd,
355 MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
356 break; 237 break;
357 } 238 }
358 return err; 239 return err;
@@ -361,105 +242,46 @@ int mt9m111_start(struct sd *sd)
361void mt9m111_disconnect(struct sd *sd) 242void mt9m111_disconnect(struct sd *sd)
362{ 243{
363 sd->sensor = NULL; 244 sd->sensor = NULL;
364 kfree(sd->sensor_priv);
365}
366
367static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
368{
369 struct sd *sd = (struct sd *) gspca_dev;
370 s32 *sensor_settings = sd->sensor_priv;
371
372 *val = sensor_settings[VFLIP_IDX];
373 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
374
375 return 0;
376}
377
378static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
379{
380 int err;
381 u8 data[2] = {0x00, 0x00};
382 struct sd *sd = (struct sd *) gspca_dev;
383 s32 *sensor_settings = sd->sensor_priv;
384
385 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
386
387 sensor_settings[VFLIP_IDX] = val;
388
389 /* The mt9m111 is flipped by default */
390 val = !val;
391
392 /* Set the correct page map */
393 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
394 if (err < 0)
395 return err;
396
397 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
398 if (err < 0)
399 return err;
400
401 data[1] = (data[1] & 0xfe) | val;
402 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
403 data, 2);
404 return err;
405}
406
407static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
408{
409 struct sd *sd = (struct sd *) gspca_dev;
410 s32 *sensor_settings = sd->sensor_priv;
411
412 *val = sensor_settings[HFLIP_IDX];
413 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
414
415 return 0;
416} 245}
417 246
418static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) 247static int mt9m111_set_hvflip(struct gspca_dev *gspca_dev)
419{ 248{
420 int err; 249 int err;
421 u8 data[2] = {0x00, 0x00}; 250 u8 data[2] = {0x00, 0x00};
422 struct sd *sd = (struct sd *) gspca_dev; 251 struct sd *sd = (struct sd *) gspca_dev;
423 s32 *sensor_settings = sd->sensor_priv; 252 int hflip;
253 int vflip;
424 254
425 PDEBUG(D_V4L2, "Set horizontal flip to %d", val); 255 PDEBUG(D_V4L2, "Set hvflip to %d %d", sd->hflip->val, sd->vflip->val);
426
427 sensor_settings[HFLIP_IDX] = val;
428 256
429 /* The mt9m111 is flipped by default */ 257 /* The mt9m111 is flipped by default */
430 val = !val; 258 hflip = !sd->hflip->val;
259 vflip = !sd->vflip->val;
431 260
432 /* Set the correct page map */ 261 /* Set the correct page map */
433 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); 262 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
434 if (err < 0) 263 if (err < 0)
435 return err; 264 return err;
436 265
437 err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); 266 data[0] = MT9M111_RMB_OVER_SIZED;
438 if (err < 0) 267 if (gspca_dev->width == 640) {
439 return err; 268 data[1] = MT9M111_RMB_ROW_SKIP_2X |
440 269 MT9M111_RMB_COLUMN_SKIP_2X |
441 data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02); 270 (hflip << 1) | vflip;
271 } else {
272 data[1] = MT9M111_RMB_ROW_SKIP_4X |
273 MT9M111_RMB_COLUMN_SKIP_4X |
274 (hflip << 1) | vflip;
275 }
442 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, 276 err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
443 data, 2); 277 data, 2);
444 return err; 278 return err;
445} 279}
446 280
447static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
448{
449 struct sd *sd = (struct sd *) gspca_dev;
450 s32 *sensor_settings = sd->sensor_priv;
451
452 *val = sensor_settings[GAIN_IDX];
453 PDEBUG(D_V4L2, "Read gain %d", *val);
454
455 return 0;
456}
457
458static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, 281static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
459 __s32 val) 282 __s32 val)
460{ 283{
461 struct sd *sd = (struct sd *) gspca_dev; 284 struct sd *sd = (struct sd *) gspca_dev;
462 s32 *sensor_settings = sd->sensor_priv;
463 int err; 285 int err;
464 u8 data[2]; 286 u8 data[2];
465 287
@@ -467,7 +289,6 @@ static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
467 if (err < 0) 289 if (err < 0)
468 return err; 290 return err;
469 291
470 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01;
471 data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1)); 292 data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
472 293
473 err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2); 294 err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
@@ -476,24 +297,11 @@ static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
476 return err; 297 return err;
477} 298}
478 299
479static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
480 __s32 *val) {
481 struct sd *sd = (struct sd *) gspca_dev;
482 s32 *sensor_settings = sd->sensor_priv;
483
484 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
485 PDEBUG(D_V4L2, "Read auto white balance %d", *val);
486 return 0;
487}
488
489static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) 300static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
490{ 301{
491 int err, tmp; 302 int err, tmp;
492 u8 data[2] = {0x00, 0x00}; 303 u8 data[2] = {0x00, 0x00};
493 struct sd *sd = (struct sd *) gspca_dev; 304 struct sd *sd = (struct sd *) gspca_dev;
494 s32 *sensor_settings = sd->sensor_priv;
495
496 sensor_settings[GAIN_IDX] = val;
497 305
498 /* Set the correct page map */ 306 /* Set the correct page map */
499 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); 307 err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
@@ -532,9 +340,7 @@ static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
532 int err; 340 int err;
533 u8 data[2]; 341 u8 data[2];
534 struct sd *sd = (struct sd *) gspca_dev; 342 struct sd *sd = (struct sd *) gspca_dev;
535 s32 *sensor_settings = sd->sensor_priv;
536 343
537 sensor_settings[GREEN_BALANCE_IDX] = val;
538 data[1] = (val & 0xff); 344 data[1] = (val & 0xff);
539 data[0] = (val & 0xff00) >> 8; 345 data[0] = (val & 0xff00) >> 8;
540 346
@@ -548,23 +354,11 @@ static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
548 data, 2); 354 data, 2);
549} 355}
550 356
551static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
552{
553 struct sd *sd = (struct sd *) gspca_dev;
554 s32 *sensor_settings = sd->sensor_priv;
555
556 *val = sensor_settings[GREEN_BALANCE_IDX];
557 PDEBUG(D_V4L2, "Read green balance %d", *val);
558 return 0;
559}
560
561static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) 357static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
562{ 358{
563 u8 data[2]; 359 u8 data[2];
564 struct sd *sd = (struct sd *) gspca_dev; 360 struct sd *sd = (struct sd *) gspca_dev;
565 s32 *sensor_settings = sd->sensor_priv;
566 361
567 sensor_settings[BLUE_BALANCE_IDX] = val;
568 data[1] = (val & 0xff); 362 data[1] = (val & 0xff);
569 data[0] = (val & 0xff00) >> 8; 363 data[0] = (val & 0xff00) >> 8;
570 364
@@ -574,23 +368,11 @@ static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
574 data, 2); 368 data, 2);
575} 369}
576 370
577static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
578{
579 struct sd *sd = (struct sd *) gspca_dev;
580 s32 *sensor_settings = sd->sensor_priv;
581
582 *val = sensor_settings[BLUE_BALANCE_IDX];
583 PDEBUG(D_V4L2, "Read blue balance %d", *val);
584 return 0;
585}
586
587static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) 371static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
588{ 372{
589 u8 data[2]; 373 u8 data[2];
590 struct sd *sd = (struct sd *) gspca_dev; 374 struct sd *sd = (struct sd *) gspca_dev;
591 s32 *sensor_settings = sd->sensor_priv;
592 375
593 sensor_settings[RED_BALANCE_IDX] = val;
594 data[1] = (val & 0xff); 376 data[1] = (val & 0xff);
595 data[0] = (val & 0xff00) >> 8; 377 data[0] = (val & 0xff00) >> 8;
596 378
@@ -600,14 +382,40 @@ static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
600 data, 2); 382 data, 2);
601} 383}
602 384
603static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) 385static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
604{ 386{
387 struct gspca_dev *gspca_dev =
388 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
605 struct sd *sd = (struct sd *) gspca_dev; 389 struct sd *sd = (struct sd *) gspca_dev;
606 s32 *sensor_settings = sd->sensor_priv; 390 int err;
607 391
608 *val = sensor_settings[RED_BALANCE_IDX]; 392 if (!gspca_dev->streaming)
609 PDEBUG(D_V4L2, "Read red balance %d", *val); 393 return 0;
610 return 0; 394
395 switch (ctrl->id) {
396 case V4L2_CID_AUTO_WHITE_BALANCE:
397 err = mt9m111_set_auto_white_balance(gspca_dev, ctrl->val);
398 if (err || ctrl->val)
399 return err;
400 err = mt9m111_set_green_balance(gspca_dev, sd->green_bal->val);
401 if (err)
402 return err;
403 err = mt9m111_set_red_balance(gspca_dev, sd->red_bal->val);
404 if (err)
405 return err;
406 err = mt9m111_set_blue_balance(gspca_dev, sd->blue_bal->val);
407 break;
408 case V4L2_CID_GAIN:
409 err = mt9m111_set_gain(gspca_dev, ctrl->val);
410 break;
411 case V4L2_CID_HFLIP:
412 err = mt9m111_set_hvflip(gspca_dev);
413 break;
414 default:
415 return -EINVAL;
416 }
417
418 return err;
611} 419}
612 420
613static void mt9m111_dump_registers(struct sd *sd) 421static void mt9m111_dump_registers(struct sd *sd)
diff --git a/drivers/media/usb/gspca/m5602/m5602_mt9m111.h b/drivers/media/usb/gspca/m5602/m5602_mt9m111.h
index 8c672b5c8c6a..07448d35e3cd 100644
--- a/drivers/media/usb/gspca/m5602/m5602_mt9m111.h
+++ b/drivers/media/usb/gspca/m5602/m5602_mt9m111.h
@@ -110,6 +110,7 @@ extern bool dump_sensor;
110 110
111int mt9m111_probe(struct sd *sd); 111int mt9m111_probe(struct sd *sd);
112int mt9m111_init(struct sd *sd); 112int mt9m111_init(struct sd *sd);
113int mt9m111_init_controls(struct sd *sd);
113int mt9m111_start(struct sd *sd); 114int mt9m111_start(struct sd *sd);
114void mt9m111_disconnect(struct sd *sd); 115void mt9m111_disconnect(struct sd *sd);
115 116
@@ -121,6 +122,7 @@ static const struct m5602_sensor mt9m111 = {
121 122
122 .probe = mt9m111_probe, 123 .probe = mt9m111_probe,
123 .init = mt9m111_init, 124 .init = mt9m111_init,
125 .init_controls = mt9m111_init_controls,
124 .disconnect = mt9m111_disconnect, 126 .disconnect = mt9m111_disconnect,
125 .start = mt9m111_start, 127 .start = mt9m111_start,
126}; 128};
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov7660.c b/drivers/media/usb/gspca/m5602/m5602_ov7660.c
index 9a14835c128f..3bbe3ad5d4a9 100644
--- a/drivers/media/usb/gspca/m5602/m5602_ov7660.c
+++ b/drivers/media/usb/gspca/m5602/m5602_ov7660.c
@@ -20,111 +20,8 @@
20 20
21#include "m5602_ov7660.h" 21#include "m5602_ov7660.h"
22 22
23static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 23static int ov7660_s_ctrl(struct v4l2_ctrl *ctrl);
24static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val); 24static void ov7660_dump_registers(struct sd *sd);
25static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
26 __s32 *val);
27static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
28 __s32 val);
29static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
30static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
31static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
32static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
33static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
34static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
35static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
36static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
37
38static const struct ctrl ov7660_ctrls[] = {
39#define GAIN_IDX 1
40 {
41 {
42 .id = V4L2_CID_GAIN,
43 .type = V4L2_CTRL_TYPE_INTEGER,
44 .name = "gain",
45 .minimum = 0x00,
46 .maximum = 0xff,
47 .step = 0x1,
48 .default_value = OV7660_DEFAULT_GAIN,
49 .flags = V4L2_CTRL_FLAG_SLIDER
50 },
51 .set = ov7660_set_gain,
52 .get = ov7660_get_gain
53 },
54#define BLUE_BALANCE_IDX 2
55#define RED_BALANCE_IDX 3
56#define AUTO_WHITE_BALANCE_IDX 4
57 {
58 {
59 .id = V4L2_CID_AUTO_WHITE_BALANCE,
60 .type = V4L2_CTRL_TYPE_BOOLEAN,
61 .name = "auto white balance",
62 .minimum = 0,
63 .maximum = 1,
64 .step = 1,
65 .default_value = 1
66 },
67 .set = ov7660_set_auto_white_balance,
68 .get = ov7660_get_auto_white_balance
69 },
70#define AUTO_GAIN_CTRL_IDX 5
71 {
72 {
73 .id = V4L2_CID_AUTOGAIN,
74 .type = V4L2_CTRL_TYPE_BOOLEAN,
75 .name = "auto gain control",
76 .minimum = 0,
77 .maximum = 1,
78 .step = 1,
79 .default_value = 1
80 },
81 .set = ov7660_set_auto_gain,
82 .get = ov7660_get_auto_gain
83 },
84#define AUTO_EXPOSURE_IDX 6
85 {
86 {
87 .id = V4L2_CID_EXPOSURE_AUTO,
88 .type = V4L2_CTRL_TYPE_BOOLEAN,
89 .name = "auto exposure",
90 .minimum = 0,
91 .maximum = 1,
92 .step = 1,
93 .default_value = 1
94 },
95 .set = ov7660_set_auto_exposure,
96 .get = ov7660_get_auto_exposure
97 },
98#define HFLIP_IDX 7
99 {
100 {
101 .id = V4L2_CID_HFLIP,
102 .type = V4L2_CTRL_TYPE_BOOLEAN,
103 .name = "horizontal flip",
104 .minimum = 0,
105 .maximum = 1,
106 .step = 1,
107 .default_value = 0
108 },
109 .set = ov7660_set_hflip,
110 .get = ov7660_get_hflip
111 },
112#define VFLIP_IDX 8
113 {
114 {
115 .id = V4L2_CID_VFLIP,
116 .type = V4L2_CTRL_TYPE_BOOLEAN,
117 .name = "vertical flip",
118 .minimum = 0,
119 .maximum = 1,
120 .step = 1,
121 .default_value = 0
122 },
123 .set = ov7660_set_vflip,
124 .get = ov7660_get_vflip
125 },
126
127};
128 25
129static struct v4l2_pix_format ov7660_modes[] = { 26static struct v4l2_pix_format ov7660_modes[] = {
130 { 27 {
@@ -140,15 +37,15 @@ static struct v4l2_pix_format ov7660_modes[] = {
140 } 37 }
141}; 38};
142 39
143static void ov7660_dump_registers(struct sd *sd); 40static const struct v4l2_ctrl_ops ov7660_ctrl_ops = {
41 .s_ctrl = ov7660_s_ctrl,
42};
144 43
145int ov7660_probe(struct sd *sd) 44int ov7660_probe(struct sd *sd)
146{ 45{
147 int err = 0, i; 46 int err = 0, i;
148 u8 prod_id = 0, ver_id = 0; 47 u8 prod_id = 0, ver_id = 0;
149 48
150 s32 *sensor_settings;
151
152 if (force_sensor) { 49 if (force_sensor) {
153 if (force_sensor == OV7660_SENSOR) { 50 if (force_sensor == OV7660_SENSOR) {
154 pr_info("Forcing an %s sensor\n", ov7660.name); 51 pr_info("Forcing an %s sensor\n", ov7660.name);
@@ -191,19 +88,8 @@ int ov7660_probe(struct sd *sd)
191 return -ENODEV; 88 return -ENODEV;
192 89
193sensor_found: 90sensor_found:
194 sensor_settings = kmalloc(
195 ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL);
196 if (!sensor_settings)
197 return -ENOMEM;
198
199 sd->gspca_dev.cam.cam_mode = ov7660_modes; 91 sd->gspca_dev.cam.cam_mode = ov7660_modes;
200 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes); 92 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
201 sd->desc->ctrls = ov7660_ctrls;
202 sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls);
203
204 for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++)
205 sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value;
206 sd->sensor_priv = sensor_settings;
207 93
208 return 0; 94 return 0;
209} 95}
@@ -211,7 +97,6 @@ sensor_found:
211int ov7660_init(struct sd *sd) 97int ov7660_init(struct sd *sd)
212{ 98{
213 int i, err = 0; 99 int i, err = 0;
214 s32 *sensor_settings = sd->sensor_priv;
215 100
216 /* Init the sensor */ 101 /* Init the sensor */
217 for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) { 102 for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
@@ -231,33 +116,40 @@ int ov7660_init(struct sd *sd)
231 if (dump_sensor) 116 if (dump_sensor)
232 ov7660_dump_registers(sd); 117 ov7660_dump_registers(sd);
233 118
234 err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); 119 return 0;
235 if (err < 0) 120}
236 return err;
237 121
238 err = ov7660_set_auto_white_balance(&sd->gspca_dev, 122int ov7660_init_controls(struct sd *sd)
239 sensor_settings[AUTO_WHITE_BALANCE_IDX]); 123{
240 if (err < 0) 124 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
241 return err;
242 125
243 err = ov7660_set_auto_gain(&sd->gspca_dev, 126 sd->gspca_dev.vdev.ctrl_handler = hdl;
244 sensor_settings[AUTO_GAIN_CTRL_IDX]); 127 v4l2_ctrl_handler_init(hdl, 6);
245 if (err < 0)
246 return err;
247 128
248 err = ov7660_set_auto_exposure(&sd->gspca_dev, 129 v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE,
249 sensor_settings[AUTO_EXPOSURE_IDX]); 130 0, 1, 1, 1);
250 if (err < 0) 131 v4l2_ctrl_new_std_menu(hdl, &ov7660_ctrl_ops,
251 return err; 132 V4L2_CID_EXPOSURE_AUTO, 1, 0, V4L2_EXPOSURE_AUTO);
252 err = ov7660_set_hflip(&sd->gspca_dev,
253 sensor_settings[HFLIP_IDX]);
254 if (err < 0)
255 return err;
256 133
257 err = ov7660_set_vflip(&sd->gspca_dev, 134 sd->autogain = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops,
258 sensor_settings[VFLIP_IDX]); 135 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
136 sd->gain = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_GAIN, 0,
137 255, 1, OV7660_DEFAULT_GAIN);
259 138
260 return err; 139 sd->hflip = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_HFLIP,
140 0, 1, 1, 0);
141 sd->vflip = v4l2_ctrl_new_std(hdl, &ov7660_ctrl_ops, V4L2_CID_VFLIP,
142 0, 1, 1, 0);
143
144 if (hdl->error) {
145 pr_err("Could not initialize controls\n");
146 return hdl->error;
147 }
148
149 v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
150 v4l2_ctrl_cluster(2, &sd->hflip);
151
152 return 0;
261} 153}
262 154
263int ov7660_start(struct sd *sd) 155int ov7660_start(struct sd *sd)
@@ -275,56 +167,29 @@ void ov7660_disconnect(struct sd *sd)
275 ov7660_stop(sd); 167 ov7660_stop(sd);
276 168
277 sd->sensor = NULL; 169 sd->sensor = NULL;
278 kfree(sd->sensor_priv);
279}
280
281static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
282{
283 struct sd *sd = (struct sd *) gspca_dev;
284 s32 *sensor_settings = sd->sensor_priv;
285
286 *val = sensor_settings[GAIN_IDX];
287 PDEBUG(D_V4L2, "Read gain %d", *val);
288 return 0;
289} 170}
290 171
291static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val) 172static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
292{ 173{
293 int err; 174 int err;
294 u8 i2c_data; 175 u8 i2c_data = val;
295 struct sd *sd = (struct sd *) gspca_dev; 176 struct sd *sd = (struct sd *) gspca_dev;
296 s32 *sensor_settings = sd->sensor_priv;
297 177
298 PDEBUG(D_V4L2, "Setting gain to %d", val); 178 PDEBUG(D_V4L2, "Setting gain to %d", val);
299 179
300 sensor_settings[GAIN_IDX] = val;
301
302 err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1); 180 err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
303 return err; 181 return err;
304} 182}
305 183
306
307static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
308 __s32 *val)
309{
310 struct sd *sd = (struct sd *) gspca_dev;
311 s32 *sensor_settings = sd->sensor_priv;
312
313 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
314 return 0;
315}
316
317static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev, 184static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
318 __s32 val) 185 __s32 val)
319{ 186{
320 int err; 187 int err;
321 u8 i2c_data; 188 u8 i2c_data;
322 struct sd *sd = (struct sd *) gspca_dev; 189 struct sd *sd = (struct sd *) gspca_dev;
323 s32 *sensor_settings = sd->sensor_priv;
324 190
325 PDEBUG(D_V4L2, "Set auto white balance to %d", val); 191 PDEBUG(D_V4L2, "Set auto white balance to %d", val);
326 192
327 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
328 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 193 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
329 if (err < 0) 194 if (err < 0)
330 return err; 195 return err;
@@ -335,26 +200,14 @@ static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
335 return err; 200 return err;
336} 201}
337 202
338static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
339{
340 struct sd *sd = (struct sd *) gspca_dev;
341 s32 *sensor_settings = sd->sensor_priv;
342
343 *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
344 PDEBUG(D_V4L2, "Read auto gain control %d", *val);
345 return 0;
346}
347
348static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) 203static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
349{ 204{
350 int err; 205 int err;
351 u8 i2c_data; 206 u8 i2c_data;
352 struct sd *sd = (struct sd *) gspca_dev; 207 struct sd *sd = (struct sd *) gspca_dev;
353 s32 *sensor_settings = sd->sensor_priv;
354 208
355 PDEBUG(D_V4L2, "Set auto gain control to %d", val); 209 PDEBUG(D_V4L2, "Set auto gain control to %d", val);
356 210
357 sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
358 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 211 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
359 if (err < 0) 212 if (err < 0)
360 return err; 213 return err;
@@ -364,94 +217,69 @@ static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
364 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); 217 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
365} 218}
366 219
367static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
368{
369 struct sd *sd = (struct sd *) gspca_dev;
370 s32 *sensor_settings = sd->sensor_priv;
371
372 *val = sensor_settings[AUTO_EXPOSURE_IDX];
373 PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
374 return 0;
375}
376
377static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, 220static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev,
378 __s32 val) 221 __s32 val)
379{ 222{
380 int err; 223 int err;
381 u8 i2c_data; 224 u8 i2c_data;
382 struct sd *sd = (struct sd *) gspca_dev; 225 struct sd *sd = (struct sd *) gspca_dev;
383 s32 *sensor_settings = sd->sensor_priv;
384 226
385 PDEBUG(D_V4L2, "Set auto exposure control to %d", val); 227 PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
386 228
387 sensor_settings[AUTO_EXPOSURE_IDX] = val;
388 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1); 229 err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
389 if (err < 0) 230 if (err < 0)
390 return err; 231 return err;
391 232
233 val = (val == V4L2_EXPOSURE_AUTO);
392 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0)); 234 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
393 235
394 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1); 236 return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
395} 237}
396 238
397static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) 239static int ov7660_set_hvflip(struct gspca_dev *gspca_dev)
398{
399 struct sd *sd = (struct sd *) gspca_dev;
400 s32 *sensor_settings = sd->sensor_priv;
401
402 *val = sensor_settings[HFLIP_IDX];
403 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
404 return 0;
405}
406
407static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
408{ 240{
409 int err; 241 int err;
410 u8 i2c_data; 242 u8 i2c_data;
411 struct sd *sd = (struct sd *) gspca_dev; 243 struct sd *sd = (struct sd *) gspca_dev;
412 s32 *sensor_settings = sd->sensor_priv;
413 244
414 PDEBUG(D_V4L2, "Set horizontal flip to %d", val); 245 PDEBUG(D_V4L2, "Set hvflip to %d, %d", sd->hflip->val, sd->vflip->val);
415 246
416 sensor_settings[HFLIP_IDX] = val; 247 i2c_data = (sd->hflip->val << 5) | (sd->vflip->val << 4);
417
418 i2c_data = ((val & 0x01) << 5) |
419 (sensor_settings[VFLIP_IDX] << 4);
420 248
421 err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1); 249 err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
422 250
423 return err; 251 return err;
424} 252}
425 253
426static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) 254static int ov7660_s_ctrl(struct v4l2_ctrl *ctrl)
427{ 255{
256 struct gspca_dev *gspca_dev =
257 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
428 struct sd *sd = (struct sd *) gspca_dev; 258 struct sd *sd = (struct sd *) gspca_dev;
429 s32 *sensor_settings = sd->sensor_priv;
430
431 *val = sensor_settings[VFLIP_IDX];
432 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
433
434 return 0;
435}
436
437static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
438{
439 int err; 259 int err;
440 u8 i2c_data;
441 struct sd *sd = (struct sd *) gspca_dev;
442 s32 *sensor_settings = sd->sensor_priv;
443
444 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
445 sensor_settings[VFLIP_IDX] = val;
446 260
447 i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5); 261 if (!gspca_dev->streaming)
448 err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1); 262 return 0;
449 if (err < 0) 263
450 return err; 264 switch (ctrl->id) {
451 265 case V4L2_CID_AUTO_WHITE_BALANCE:
452 /* When vflip is toggled we need to readjust the bridge hsync/vsync */ 266 err = ov7660_set_auto_white_balance(gspca_dev, ctrl->val);
453 if (gspca_dev->streaming) 267 break;
454 err = ov7660_start(sd); 268 case V4L2_CID_EXPOSURE_AUTO:
269 err = ov7660_set_auto_exposure(gspca_dev, ctrl->val);
270 break;
271 case V4L2_CID_AUTOGAIN:
272 err = ov7660_set_auto_gain(gspca_dev, ctrl->val);
273 if (err || ctrl->val)
274 return err;
275 err = ov7660_set_gain(gspca_dev, sd->gain->val);
276 break;
277 case V4L2_CID_HFLIP:
278 err = ov7660_set_hvflip(gspca_dev);
279 break;
280 default:
281 return -EINVAL;
282 }
455 283
456 return err; 284 return err;
457} 285}
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov7660.h b/drivers/media/usb/gspca/m5602/m5602_ov7660.h
index 2b6a13b508f7..6fece1ce1232 100644
--- a/drivers/media/usb/gspca/m5602/m5602_ov7660.h
+++ b/drivers/media/usb/gspca/m5602/m5602_ov7660.h
@@ -90,6 +90,8 @@ extern bool dump_sensor;
90 90
91int ov7660_probe(struct sd *sd); 91int ov7660_probe(struct sd *sd);
92int ov7660_init(struct sd *sd); 92int ov7660_init(struct sd *sd);
93int ov7660_init(struct sd *sd);
94int ov7660_init_controls(struct sd *sd);
93int ov7660_start(struct sd *sd); 95int ov7660_start(struct sd *sd);
94int ov7660_stop(struct sd *sd); 96int ov7660_stop(struct sd *sd);
95void ov7660_disconnect(struct sd *sd); 97void ov7660_disconnect(struct sd *sd);
@@ -100,6 +102,7 @@ static const struct m5602_sensor ov7660 = {
100 .i2c_regW = 1, 102 .i2c_regW = 1,
101 .probe = ov7660_probe, 103 .probe = ov7660_probe,
102 .init = ov7660_init, 104 .init = ov7660_init,
105 .init_controls = ov7660_init_controls,
103 .start = ov7660_start, 106 .start = ov7660_start,
104 .stop = ov7660_stop, 107 .stop = ov7660_stop,
105 .disconnect = ov7660_disconnect, 108 .disconnect = ov7660_disconnect,
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov9650.c b/drivers/media/usb/gspca/m5602/m5602_ov9650.c
index 2114a8b90ec9..e2fe2f942fe6 100644
--- a/drivers/media/usb/gspca/m5602/m5602_ov9650.c
+++ b/drivers/media/usb/gspca/m5602/m5602_ov9650.c
@@ -20,26 +20,8 @@
20 20
21#include "m5602_ov9650.h" 21#include "m5602_ov9650.h"
22 22
23static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); 23static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl);
24static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); 24static void ov9650_dump_registers(struct sd *sd);
25static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
26static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
27static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
28static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
29static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
30static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
31static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
32static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
33static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
34static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
35static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
36 __s32 *val);
37static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
38 __s32 val);
39static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
40static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
41static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
42static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
43 25
44/* Vertically and horizontally flips the image if matched, needed for machines 26/* Vertically and horizontally flips the image if matched, needed for machines
45 where the sensor is mounted upside down */ 27 where the sensor is mounted upside down */
@@ -113,140 +95,6 @@ static
113 {} 95 {}
114}; 96};
115 97
116static const struct ctrl ov9650_ctrls[] = {
117#define EXPOSURE_IDX 0
118 {
119 {
120 .id = V4L2_CID_EXPOSURE,
121 .type = V4L2_CTRL_TYPE_INTEGER,
122 .name = "exposure",
123 .minimum = 0x00,
124 .maximum = 0x1ff,
125 .step = 0x4,
126 .default_value = EXPOSURE_DEFAULT,
127 .flags = V4L2_CTRL_FLAG_SLIDER
128 },
129 .set = ov9650_set_exposure,
130 .get = ov9650_get_exposure
131 },
132#define GAIN_IDX 1
133 {
134 {
135 .id = V4L2_CID_GAIN,
136 .type = V4L2_CTRL_TYPE_INTEGER,
137 .name = "gain",
138 .minimum = 0x00,
139 .maximum = 0x3ff,
140 .step = 0x1,
141 .default_value = GAIN_DEFAULT,
142 .flags = V4L2_CTRL_FLAG_SLIDER
143 },
144 .set = ov9650_set_gain,
145 .get = ov9650_get_gain
146 },
147#define RED_BALANCE_IDX 2
148 {
149 {
150 .id = V4L2_CID_RED_BALANCE,
151 .type = V4L2_CTRL_TYPE_INTEGER,
152 .name = "red balance",
153 .minimum = 0x00,
154 .maximum = 0xff,
155 .step = 0x1,
156 .default_value = RED_GAIN_DEFAULT,
157 .flags = V4L2_CTRL_FLAG_SLIDER
158 },
159 .set = ov9650_set_red_balance,
160 .get = ov9650_get_red_balance
161 },
162#define BLUE_BALANCE_IDX 3
163 {
164 {
165 .id = V4L2_CID_BLUE_BALANCE,
166 .type = V4L2_CTRL_TYPE_INTEGER,
167 .name = "blue balance",
168 .minimum = 0x00,
169 .maximum = 0xff,
170 .step = 0x1,
171 .default_value = BLUE_GAIN_DEFAULT,
172 .flags = V4L2_CTRL_FLAG_SLIDER
173 },
174 .set = ov9650_set_blue_balance,
175 .get = ov9650_get_blue_balance
176 },
177#define HFLIP_IDX 4
178 {
179 {
180 .id = V4L2_CID_HFLIP,
181 .type = V4L2_CTRL_TYPE_BOOLEAN,
182 .name = "horizontal flip",
183 .minimum = 0,
184 .maximum = 1,
185 .step = 1,
186 .default_value = 0
187 },
188 .set = ov9650_set_hflip,
189 .get = ov9650_get_hflip
190 },
191#define VFLIP_IDX 5
192 {
193 {
194 .id = V4L2_CID_VFLIP,
195 .type = V4L2_CTRL_TYPE_BOOLEAN,
196 .name = "vertical flip",
197 .minimum = 0,
198 .maximum = 1,
199 .step = 1,
200 .default_value = 0
201 },
202 .set = ov9650_set_vflip,
203 .get = ov9650_get_vflip
204 },
205#define AUTO_WHITE_BALANCE_IDX 6
206 {
207 {
208 .id = V4L2_CID_AUTO_WHITE_BALANCE,
209 .type = V4L2_CTRL_TYPE_BOOLEAN,
210 .name = "auto white balance",
211 .minimum = 0,
212 .maximum = 1,
213 .step = 1,
214 .default_value = 1
215 },
216 .set = ov9650_set_auto_white_balance,
217 .get = ov9650_get_auto_white_balance
218 },
219#define AUTO_GAIN_CTRL_IDX 7
220 {
221 {
222 .id = V4L2_CID_AUTOGAIN,
223 .type = V4L2_CTRL_TYPE_BOOLEAN,
224 .name = "auto gain control",
225 .minimum = 0,
226 .maximum = 1,
227 .step = 1,
228 .default_value = 1
229 },
230 .set = ov9650_set_auto_gain,
231 .get = ov9650_get_auto_gain
232 },
233#define AUTO_EXPOSURE_IDX 8
234 {
235 {
236 .id = V4L2_CID_EXPOSURE_AUTO,
237 .type = V4L2_CTRL_TYPE_BOOLEAN,
238 .name = "auto exposure",
239 .minimum = 0,
240 .maximum = 1,
241 .step = 1,
242 .default_value = 1
243 },
244 .set = ov9650_set_auto_exposure,
245 .get = ov9650_get_auto_exposure
246 }
247
248};
249
250static struct v4l2_pix_format ov9650_modes[] = { 98static struct v4l2_pix_format ov9650_modes[] = {
251 { 99 {
252 176, 100 176,
@@ -291,13 +139,14 @@ static struct v4l2_pix_format ov9650_modes[] = {
291 } 139 }
292}; 140};
293 141
294static void ov9650_dump_registers(struct sd *sd); 142static const struct v4l2_ctrl_ops ov9650_ctrl_ops = {
143 .s_ctrl = ov9650_s_ctrl,
144};
295 145
296int ov9650_probe(struct sd *sd) 146int ov9650_probe(struct sd *sd)
297{ 147{
298 int err = 0; 148 int err = 0;
299 u8 prod_id = 0, ver_id = 0, i; 149 u8 prod_id = 0, ver_id = 0, i;
300 s32 *sensor_settings;
301 150
302 if (force_sensor) { 151 if (force_sensor) {
303 if (force_sensor == OV9650_SENSOR) { 152 if (force_sensor == OV9650_SENSOR) {
@@ -338,19 +187,9 @@ int ov9650_probe(struct sd *sd)
338 return -ENODEV; 187 return -ENODEV;
339 188
340sensor_found: 189sensor_found:
341 sensor_settings = kmalloc(
342 ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL);
343 if (!sensor_settings)
344 return -ENOMEM;
345
346 sd->gspca_dev.cam.cam_mode = ov9650_modes; 190 sd->gspca_dev.cam.cam_mode = ov9650_modes;
347 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes); 191 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
348 sd->desc->ctrls = ov9650_ctrls;
349 sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls);
350 192
351 for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++)
352 sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value;
353 sd->sensor_priv = sensor_settings;
354 return 0; 193 return 0;
355} 194}
356 195
@@ -358,7 +197,6 @@ int ov9650_init(struct sd *sd)
358{ 197{
359 int i, err = 0; 198 int i, err = 0;
360 u8 data; 199 u8 data;
361 s32 *sensor_settings = sd->sensor_priv;
362 200
363 if (dump_sensor) 201 if (dump_sensor)
364 ov9650_dump_registers(sd); 202 ov9650_dump_registers(sd);
@@ -372,46 +210,52 @@ int ov9650_init(struct sd *sd)
372 err = m5602_write_bridge(sd, init_ov9650[i][1], data); 210 err = m5602_write_bridge(sd, init_ov9650[i][1], data);
373 } 211 }
374 212
375 err = ov9650_set_exposure(&sd->gspca_dev, 213 return 0;
376 sensor_settings[EXPOSURE_IDX]); 214}
377 if (err < 0)
378 return err;
379
380 err = ov9650_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
381 if (err < 0)
382 return err;
383
384 err = ov9650_set_red_balance(&sd->gspca_dev,
385 sensor_settings[RED_BALANCE_IDX]);
386 if (err < 0)
387 return err;
388
389 err = ov9650_set_blue_balance(&sd->gspca_dev,
390 sensor_settings[BLUE_BALANCE_IDX]);
391 if (err < 0)
392 return err;
393
394 err = ov9650_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
395 if (err < 0)
396 return err;
397
398 err = ov9650_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
399 if (err < 0)
400 return err;
401 215
402 err = ov9650_set_auto_exposure(&sd->gspca_dev, 216int ov9650_init_controls(struct sd *sd)
403 sensor_settings[AUTO_EXPOSURE_IDX]); 217{
404 if (err < 0) 218 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
405 return err; 219
220 sd->gspca_dev.vdev.ctrl_handler = hdl;
221 v4l2_ctrl_handler_init(hdl, 9);
222
223 sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
224 V4L2_CID_AUTO_WHITE_BALANCE,
225 0, 1, 1, 1);
226 sd->red_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
227 V4L2_CID_RED_BALANCE, 0, 255, 1,
228 RED_GAIN_DEFAULT);
229 sd->blue_bal = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
230 V4L2_CID_BLUE_BALANCE, 0, 255, 1,
231 BLUE_GAIN_DEFAULT);
232
233 sd->autoexpo = v4l2_ctrl_new_std_menu(hdl, &ov9650_ctrl_ops,
234 V4L2_CID_EXPOSURE_AUTO, 1, 0, V4L2_EXPOSURE_AUTO);
235 sd->expo = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_EXPOSURE,
236 0, 0x1ff, 4, EXPOSURE_DEFAULT);
237
238 sd->autogain = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops,
239 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
240 sd->gain = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_GAIN, 0,
241 0x3ff, 1, GAIN_DEFAULT);
242
243 sd->hflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_HFLIP,
244 0, 1, 1, 0);
245 sd->vflip = v4l2_ctrl_new_std(hdl, &ov9650_ctrl_ops, V4L2_CID_VFLIP,
246 0, 1, 1, 0);
247
248 if (hdl->error) {
249 pr_err("Could not initialize controls\n");
250 return hdl->error;
251 }
406 252
407 err = ov9650_set_auto_white_balance(&sd->gspca_dev, 253 v4l2_ctrl_auto_cluster(3, &sd->auto_white_bal, 0, false);
408 sensor_settings[AUTO_WHITE_BALANCE_IDX]); 254 v4l2_ctrl_auto_cluster(2, &sd->autoexpo, 0, false);
409 if (err < 0) 255 v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
410 return err; 256 v4l2_ctrl_cluster(2, &sd->hflip);
411 257
412 err = ov9650_set_auto_gain(&sd->gspca_dev, 258 return 0;
413 sensor_settings[AUTO_GAIN_CTRL_IDX]);
414 return err;
415} 259}
416 260
417int ov9650_start(struct sd *sd) 261int ov9650_start(struct sd *sd)
@@ -419,7 +263,6 @@ int ov9650_start(struct sd *sd)
419 u8 data; 263 u8 data;
420 int i, err = 0; 264 int i, err = 0;
421 struct cam *cam = &sd->gspca_dev.cam; 265 struct cam *cam = &sd->gspca_dev.cam;
422 s32 *sensor_settings = sd->sensor_priv;
423 266
424 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width; 267 int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
425 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height; 268 int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
@@ -427,9 +270,9 @@ int ov9650_start(struct sd *sd)
427 int hor_offs = OV9650_LEFT_OFFSET; 270 int hor_offs = OV9650_LEFT_OFFSET;
428 271
429 if ((!dmi_check_system(ov9650_flip_dmi_table) && 272 if ((!dmi_check_system(ov9650_flip_dmi_table) &&
430 sensor_settings[VFLIP_IDX]) || 273 sd->vflip->val) ||
431 (dmi_check_system(ov9650_flip_dmi_table) && 274 (dmi_check_system(ov9650_flip_dmi_table) &&
432 !sensor_settings[VFLIP_IDX])) 275 !sd->vflip->val))
433 ver_offs--; 276 ver_offs--;
434 277
435 if (width <= 320) 278 if (width <= 320)
@@ -553,29 +396,16 @@ void ov9650_disconnect(struct sd *sd)
553 ov9650_stop(sd); 396 ov9650_stop(sd);
554 397
555 sd->sensor = NULL; 398 sd->sensor = NULL;
556 kfree(sd->sensor_priv);
557}
558
559static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
560{
561 struct sd *sd = (struct sd *) gspca_dev;
562 s32 *sensor_settings = sd->sensor_priv;
563
564 *val = sensor_settings[EXPOSURE_IDX];
565 PDEBUG(D_V4L2, "Read exposure %d", *val);
566 return 0;
567} 399}
568 400
569static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) 401static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
570{ 402{
571 struct sd *sd = (struct sd *) gspca_dev; 403 struct sd *sd = (struct sd *) gspca_dev;
572 s32 *sensor_settings = sd->sensor_priv;
573 u8 i2c_data; 404 u8 i2c_data;
574 int err; 405 int err;
575 406
576 PDEBUG(D_V4L2, "Set exposure to %d", val); 407 PDEBUG(D_V4L2, "Set exposure to %d", val);
577 408
578 sensor_settings[EXPOSURE_IDX] = val;
579 /* The 6 MSBs */ 409 /* The 6 MSBs */
580 i2c_data = (val >> 10) & 0x3f; 410 i2c_data = (val >> 10) & 0x3f;
581 err = m5602_write_sensor(sd, OV9650_AECHM, 411 err = m5602_write_sensor(sd, OV9650_AECHM,
@@ -596,27 +426,14 @@ static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
596 return err; 426 return err;
597} 427}
598 428
599static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
600{
601 struct sd *sd = (struct sd *) gspca_dev;
602 s32 *sensor_settings = sd->sensor_priv;
603
604 *val = sensor_settings[GAIN_IDX];
605 PDEBUG(D_V4L2, "Read gain %d", *val);
606 return 0;
607}
608
609static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) 429static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
610{ 430{
611 int err; 431 int err;
612 u8 i2c_data; 432 u8 i2c_data;
613 struct sd *sd = (struct sd *) gspca_dev; 433 struct sd *sd = (struct sd *) gspca_dev;
614 s32 *sensor_settings = sd->sensor_priv;
615 434
616 PDEBUG(D_V4L2, "Setting gain to %d", val); 435 PDEBUG(D_V4L2, "Setting gain to %d", val);
617 436
618 sensor_settings[GAIN_IDX] = val;
619
620 /* The 2 MSB */ 437 /* The 2 MSB */
621 /* Read the OV9650_VREF register first to avoid 438 /* Read the OV9650_VREF register first to avoid
622 corrupting the VREF high and low bits */ 439 corrupting the VREF high and low bits */
@@ -637,117 +454,46 @@ static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
637 return err; 454 return err;
638} 455}
639 456
640static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
641{
642 struct sd *sd = (struct sd *) gspca_dev;
643 s32 *sensor_settings = sd->sensor_priv;
644
645 *val = sensor_settings[RED_BALANCE_IDX];
646 PDEBUG(D_V4L2, "Read red gain %d", *val);
647 return 0;
648}
649
650static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) 457static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
651{ 458{
652 int err; 459 int err;
653 u8 i2c_data; 460 u8 i2c_data;
654 struct sd *sd = (struct sd *) gspca_dev; 461 struct sd *sd = (struct sd *) gspca_dev;
655 s32 *sensor_settings = sd->sensor_priv;
656 462
657 PDEBUG(D_V4L2, "Set red gain to %d", val); 463 PDEBUG(D_V4L2, "Set red gain to %d", val);
658 464
659 sensor_settings[RED_BALANCE_IDX] = val;
660
661 i2c_data = val & 0xff; 465 i2c_data = val & 0xff;
662 err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1); 466 err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
663 return err; 467 return err;
664} 468}
665 469
666static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
667{
668 struct sd *sd = (struct sd *) gspca_dev;
669 s32 *sensor_settings = sd->sensor_priv;
670
671 *val = sensor_settings[BLUE_BALANCE_IDX];
672 PDEBUG(D_V4L2, "Read blue gain %d", *val);
673
674 return 0;
675}
676
677static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) 470static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
678{ 471{
679 int err; 472 int err;
680 u8 i2c_data; 473 u8 i2c_data;
681 struct sd *sd = (struct sd *) gspca_dev; 474 struct sd *sd = (struct sd *) gspca_dev;
682 s32 *sensor_settings = sd->sensor_priv;
683 475
684 PDEBUG(D_V4L2, "Set blue gain to %d", val); 476 PDEBUG(D_V4L2, "Set blue gain to %d", val);
685 477
686 sensor_settings[BLUE_BALANCE_IDX] = val;
687
688 i2c_data = val & 0xff; 478 i2c_data = val & 0xff;
689 err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1); 479 err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
690 return err; 480 return err;
691} 481}
692 482
693static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) 483static int ov9650_set_hvflip(struct gspca_dev *gspca_dev)
694{
695 struct sd *sd = (struct sd *) gspca_dev;
696 s32 *sensor_settings = sd->sensor_priv;
697
698 *val = sensor_settings[HFLIP_IDX];
699 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
700 return 0;
701}
702
703static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
704{ 484{
705 int err; 485 int err;
706 u8 i2c_data; 486 u8 i2c_data;
707 struct sd *sd = (struct sd *) gspca_dev; 487 struct sd *sd = (struct sd *) gspca_dev;
708 s32 *sensor_settings = sd->sensor_priv; 488 int hflip = sd->hflip->val;
489 int vflip = sd->vflip->val;
709 490
710 PDEBUG(D_V4L2, "Set horizontal flip to %d", val); 491 PDEBUG(D_V4L2, "Set hvflip to %d %d", hflip, vflip);
711
712 sensor_settings[HFLIP_IDX] = val;
713
714 if (!dmi_check_system(ov9650_flip_dmi_table))
715 i2c_data = ((val & 0x01) << 5) |
716 (sensor_settings[VFLIP_IDX] << 4);
717 else
718 i2c_data = ((val & 0x01) << 5) |
719 (!sensor_settings[VFLIP_IDX] << 4);
720
721 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
722
723 return err;
724}
725
726static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
727{
728 struct sd *sd = (struct sd *) gspca_dev;
729 s32 *sensor_settings = sd->sensor_priv;
730
731 *val = sensor_settings[VFLIP_IDX];
732 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
733
734 return 0;
735}
736
737static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
738{
739 int err;
740 u8 i2c_data;
741 struct sd *sd = (struct sd *) gspca_dev;
742 s32 *sensor_settings = sd->sensor_priv;
743
744 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
745 sensor_settings[VFLIP_IDX] = val;
746 492
747 if (dmi_check_system(ov9650_flip_dmi_table)) 493 if (dmi_check_system(ov9650_flip_dmi_table))
748 val = !val; 494 vflip = !vflip;
749 495
750 i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5); 496 i2c_data = (hflip << 5) | (vflip << 4);
751 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1); 497 err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
752 if (err < 0) 498 if (err < 0)
753 return err; 499 return err;
@@ -759,57 +505,34 @@ static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
759 return err; 505 return err;
760} 506}
761 507
762static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
763{
764 struct sd *sd = (struct sd *) gspca_dev;
765 s32 *sensor_settings = sd->sensor_priv;
766
767 *val = sensor_settings[AUTO_EXPOSURE_IDX];
768 PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
769 return 0;
770}
771
772static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, 508static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
773 __s32 val) 509 __s32 val)
774{ 510{
775 int err; 511 int err;
776 u8 i2c_data; 512 u8 i2c_data;
777 struct sd *sd = (struct sd *) gspca_dev; 513 struct sd *sd = (struct sd *) gspca_dev;
778 s32 *sensor_settings = sd->sensor_priv;
779 514
780 PDEBUG(D_V4L2, "Set auto exposure control to %d", val); 515 PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
781 516
782 sensor_settings[AUTO_EXPOSURE_IDX] = val;
783 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); 517 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
784 if (err < 0) 518 if (err < 0)
785 return err; 519 return err;
786 520
521 val = (val == V4L2_EXPOSURE_AUTO);
787 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0)); 522 i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
788 523
789 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); 524 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
790} 525}
791 526
792static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
793 __s32 *val)
794{
795 struct sd *sd = (struct sd *) gspca_dev;
796 s32 *sensor_settings = sd->sensor_priv;
797
798 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
799 return 0;
800}
801
802static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, 527static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
803 __s32 val) 528 __s32 val)
804{ 529{
805 int err; 530 int err;
806 u8 i2c_data; 531 u8 i2c_data;
807 struct sd *sd = (struct sd *) gspca_dev; 532 struct sd *sd = (struct sd *) gspca_dev;
808 s32 *sensor_settings = sd->sensor_priv;
809 533
810 PDEBUG(D_V4L2, "Set auto white balance to %d", val); 534 PDEBUG(D_V4L2, "Set auto white balance to %d", val);
811 535
812 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
813 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); 536 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
814 if (err < 0) 537 if (err < 0)
815 return err; 538 return err;
@@ -820,26 +543,14 @@ static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
820 return err; 543 return err;
821} 544}
822 545
823static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
824{
825 struct sd *sd = (struct sd *) gspca_dev;
826 s32 *sensor_settings = sd->sensor_priv;
827
828 *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
829 PDEBUG(D_V4L2, "Read auto gain control %d", *val);
830 return 0;
831}
832
833static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) 546static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
834{ 547{
835 int err; 548 int err;
836 u8 i2c_data; 549 u8 i2c_data;
837 struct sd *sd = (struct sd *) gspca_dev; 550 struct sd *sd = (struct sd *) gspca_dev;
838 s32 *sensor_settings = sd->sensor_priv;
839 551
840 PDEBUG(D_V4L2, "Set auto gain control to %d", val); 552 PDEBUG(D_V4L2, "Set auto gain control to %d", val);
841 553
842 sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
843 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1); 554 err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
844 if (err < 0) 555 if (err < 0)
845 return err; 556 return err;
@@ -849,6 +560,48 @@ static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
849 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1); 560 return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
850} 561}
851 562
563static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl)
564{
565 struct gspca_dev *gspca_dev =
566 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
567 struct sd *sd = (struct sd *) gspca_dev;
568 int err;
569
570 if (!gspca_dev->streaming)
571 return 0;
572
573 switch (ctrl->id) {
574 case V4L2_CID_AUTO_WHITE_BALANCE:
575 err = ov9650_set_auto_white_balance(gspca_dev, ctrl->val);
576 if (err || ctrl->val)
577 return err;
578 err = ov9650_set_red_balance(gspca_dev, sd->red_bal->val);
579 if (err)
580 return err;
581 err = ov9650_set_blue_balance(gspca_dev, sd->blue_bal->val);
582 break;
583 case V4L2_CID_EXPOSURE_AUTO:
584 err = ov9650_set_auto_exposure(gspca_dev, ctrl->val);
585 if (err || ctrl->val == V4L2_EXPOSURE_AUTO)
586 return err;
587 err = ov9650_set_exposure(gspca_dev, sd->expo->val);
588 break;
589 case V4L2_CID_AUTOGAIN:
590 err = ov9650_set_auto_gain(gspca_dev, ctrl->val);
591 if (err || ctrl->val)
592 return err;
593 err = ov9650_set_gain(gspca_dev, sd->gain->val);
594 break;
595 case V4L2_CID_HFLIP:
596 err = ov9650_set_hvflip(gspca_dev);
597 break;
598 default:
599 return -EINVAL;
600 }
601
602 return err;
603}
604
852static void ov9650_dump_registers(struct sd *sd) 605static void ov9650_dump_registers(struct sd *sd)
853{ 606{
854 int address; 607 int address;
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov9650.h b/drivers/media/usb/gspca/m5602/m5602_ov9650.h
index f7aa5bf68983..f9f5870da60f 100644
--- a/drivers/media/usb/gspca/m5602/m5602_ov9650.h
+++ b/drivers/media/usb/gspca/m5602/m5602_ov9650.h
@@ -139,6 +139,7 @@ extern bool dump_sensor;
139 139
140int ov9650_probe(struct sd *sd); 140int ov9650_probe(struct sd *sd);
141int ov9650_init(struct sd *sd); 141int ov9650_init(struct sd *sd);
142int ov9650_init_controls(struct sd *sd);
142int ov9650_start(struct sd *sd); 143int ov9650_start(struct sd *sd);
143int ov9650_stop(struct sd *sd); 144int ov9650_stop(struct sd *sd);
144void ov9650_disconnect(struct sd *sd); 145void ov9650_disconnect(struct sd *sd);
@@ -149,6 +150,7 @@ static const struct m5602_sensor ov9650 = {
149 .i2c_regW = 1, 150 .i2c_regW = 1,
150 .probe = ov9650_probe, 151 .probe = ov9650_probe,
151 .init = ov9650_init, 152 .init = ov9650_init,
153 .init_controls = ov9650_init_controls,
152 .start = ov9650_start, 154 .start = ov9650_start,
153 .stop = ov9650_stop, 155 .stop = ov9650_stop,
154 .disconnect = ov9650_disconnect, 156 .disconnect = ov9650_disconnect,
diff --git a/drivers/media/usb/gspca/m5602/m5602_po1030.c b/drivers/media/usb/gspca/m5602/m5602_po1030.c
index b8771698cbcb..189086291303 100644
--- a/drivers/media/usb/gspca/m5602/m5602_po1030.c
+++ b/drivers/media/usb/gspca/m5602/m5602_po1030.c
@@ -20,28 +20,8 @@
20 20
21#include "m5602_po1030.h" 21#include "m5602_po1030.h"
22 22
23static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); 23static int po1030_s_ctrl(struct v4l2_ctrl *ctrl);
24static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); 24static void po1030_dump_registers(struct sd *sd);
25static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
26static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
27static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
28static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
29static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
30static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
31static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
32static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
33static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
34static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
35static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
36static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
37static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
38 __s32 val);
39static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
40 __s32 *val);
41static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
42 __s32 val);
43static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
44 __s32 *val);
45 25
46static struct v4l2_pix_format po1030_modes[] = { 26static struct v4l2_pix_format po1030_modes[] = {
47 { 27 {
@@ -56,146 +36,25 @@ static struct v4l2_pix_format po1030_modes[] = {
56 } 36 }
57}; 37};
58 38
59static const struct ctrl po1030_ctrls[] = { 39static const struct v4l2_ctrl_ops po1030_ctrl_ops = {
60#define GAIN_IDX 0 40 .s_ctrl = po1030_s_ctrl,
61 {
62 {
63 .id = V4L2_CID_GAIN,
64 .type = V4L2_CTRL_TYPE_INTEGER,
65 .name = "gain",
66 .minimum = 0x00,
67 .maximum = 0x4f,
68 .step = 0x1,
69 .default_value = PO1030_GLOBAL_GAIN_DEFAULT,
70 .flags = V4L2_CTRL_FLAG_SLIDER
71 },
72 .set = po1030_set_gain,
73 .get = po1030_get_gain
74 },
75#define EXPOSURE_IDX 1
76 {
77 {
78 .id = V4L2_CID_EXPOSURE,
79 .type = V4L2_CTRL_TYPE_INTEGER,
80 .name = "exposure",
81 .minimum = 0x00,
82 .maximum = 0x02ff,
83 .step = 0x1,
84 .default_value = PO1030_EXPOSURE_DEFAULT,
85 .flags = V4L2_CTRL_FLAG_SLIDER
86 },
87 .set = po1030_set_exposure,
88 .get = po1030_get_exposure
89 },
90#define RED_BALANCE_IDX 2
91 {
92 {
93 .id = V4L2_CID_RED_BALANCE,
94 .type = V4L2_CTRL_TYPE_INTEGER,
95 .name = "red balance",
96 .minimum = 0x00,
97 .maximum = 0xff,
98 .step = 0x1,
99 .default_value = PO1030_RED_GAIN_DEFAULT,
100 .flags = V4L2_CTRL_FLAG_SLIDER
101 },
102 .set = po1030_set_red_balance,
103 .get = po1030_get_red_balance
104 },
105#define BLUE_BALANCE_IDX 3
106 {
107 {
108 .id = V4L2_CID_BLUE_BALANCE,
109 .type = V4L2_CTRL_TYPE_INTEGER,
110 .name = "blue balance",
111 .minimum = 0x00,
112 .maximum = 0xff,
113 .step = 0x1,
114 .default_value = PO1030_BLUE_GAIN_DEFAULT,
115 .flags = V4L2_CTRL_FLAG_SLIDER
116 },
117 .set = po1030_set_blue_balance,
118 .get = po1030_get_blue_balance
119 },
120#define HFLIP_IDX 4
121 {
122 {
123 .id = V4L2_CID_HFLIP,
124 .type = V4L2_CTRL_TYPE_BOOLEAN,
125 .name = "horizontal flip",
126 .minimum = 0,
127 .maximum = 1,
128 .step = 1,
129 .default_value = 0,
130 },
131 .set = po1030_set_hflip,
132 .get = po1030_get_hflip
133 },
134#define VFLIP_IDX 5
135 {
136 {
137 .id = V4L2_CID_VFLIP,
138 .type = V4L2_CTRL_TYPE_BOOLEAN,
139 .name = "vertical flip",
140 .minimum = 0,
141 .maximum = 1,
142 .step = 1,
143 .default_value = 0,
144 },
145 .set = po1030_set_vflip,
146 .get = po1030_get_vflip
147 },
148#define AUTO_WHITE_BALANCE_IDX 6
149 {
150 {
151 .id = V4L2_CID_AUTO_WHITE_BALANCE,
152 .type = V4L2_CTRL_TYPE_BOOLEAN,
153 .name = "auto white balance",
154 .minimum = 0,
155 .maximum = 1,
156 .step = 1,
157 .default_value = 0,
158 },
159 .set = po1030_set_auto_white_balance,
160 .get = po1030_get_auto_white_balance
161 },
162#define AUTO_EXPOSURE_IDX 7
163 {
164 {
165 .id = V4L2_CID_EXPOSURE_AUTO,
166 .type = V4L2_CTRL_TYPE_BOOLEAN,
167 .name = "auto exposure",
168 .minimum = 0,
169 .maximum = 1,
170 .step = 1,
171 .default_value = 0,
172 },
173 .set = po1030_set_auto_exposure,
174 .get = po1030_get_auto_exposure
175 },
176#define GREEN_BALANCE_IDX 8
177 {
178 {
179 .id = M5602_V4L2_CID_GREEN_BALANCE,
180 .type = V4L2_CTRL_TYPE_INTEGER,
181 .name = "green balance",
182 .minimum = 0x00,
183 .maximum = 0xff,
184 .step = 0x1,
185 .default_value = PO1030_GREEN_GAIN_DEFAULT,
186 .flags = V4L2_CTRL_FLAG_SLIDER
187 },
188 .set = po1030_set_green_balance,
189 .get = po1030_get_green_balance
190 },
191}; 41};
192 42
193static void po1030_dump_registers(struct sd *sd); 43static const struct v4l2_ctrl_config po1030_greenbal_cfg = {
44 .ops = &po1030_ctrl_ops,
45 .id = M5602_V4L2_CID_GREEN_BALANCE,
46 .name = "Green Balance",
47 .type = V4L2_CTRL_TYPE_INTEGER,
48 .min = 0,
49 .max = 255,
50 .step = 1,
51 .def = PO1030_GREEN_GAIN_DEFAULT,
52 .flags = V4L2_CTRL_FLAG_SLIDER,
53};
194 54
195int po1030_probe(struct sd *sd) 55int po1030_probe(struct sd *sd)
196{ 56{
197 u8 dev_id_h = 0, i; 57 u8 dev_id_h = 0, i;
198 s32 *sensor_settings;
199 58
200 if (force_sensor) { 59 if (force_sensor) {
201 if (force_sensor == PO1030_SENSOR) { 60 if (force_sensor == PO1030_SENSOR) {
@@ -229,26 +88,14 @@ int po1030_probe(struct sd *sd)
229 return -ENODEV; 88 return -ENODEV;
230 89
231sensor_found: 90sensor_found:
232 sensor_settings = kmalloc(
233 ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
234 if (!sensor_settings)
235 return -ENOMEM;
236
237 sd->gspca_dev.cam.cam_mode = po1030_modes; 91 sd->gspca_dev.cam.cam_mode = po1030_modes;
238 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes); 92 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
239 sd->desc->ctrls = po1030_ctrls;
240 sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
241
242 for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
243 sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
244 sd->sensor_priv = sensor_settings;
245 93
246 return 0; 94 return 0;
247} 95}
248 96
249int po1030_init(struct sd *sd) 97int po1030_init(struct sd *sd)
250{ 98{
251 s32 *sensor_settings = sd->sensor_priv;
252 int i, err = 0; 99 int i, err = 0;
253 100
254 /* Init the sensor */ 101 /* Init the sensor */
@@ -279,46 +126,50 @@ int po1030_init(struct sd *sd)
279 if (dump_sensor) 126 if (dump_sensor)
280 po1030_dump_registers(sd); 127 po1030_dump_registers(sd);
281 128
282 err = po1030_set_exposure(&sd->gspca_dev, 129 return 0;
283 sensor_settings[EXPOSURE_IDX]); 130}
284 if (err < 0)
285 return err;
286
287 err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
288 if (err < 0)
289 return err;
290
291 err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
292 if (err < 0)
293 return err;
294
295 err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
296 if (err < 0)
297 return err;
298
299 err = po1030_set_red_balance(&sd->gspca_dev,
300 sensor_settings[RED_BALANCE_IDX]);
301 if (err < 0)
302 return err;
303
304 err = po1030_set_blue_balance(&sd->gspca_dev,
305 sensor_settings[BLUE_BALANCE_IDX]);
306 if (err < 0)
307 return err;
308 131
309 err = po1030_set_green_balance(&sd->gspca_dev, 132int po1030_init_controls(struct sd *sd)
310 sensor_settings[GREEN_BALANCE_IDX]); 133{
311 if (err < 0) 134 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
312 return err; 135
136 sd->gspca_dev.vdev.ctrl_handler = hdl;
137 v4l2_ctrl_handler_init(hdl, 9);
138
139 sd->auto_white_bal = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops,
140 V4L2_CID_AUTO_WHITE_BALANCE,
141 0, 1, 1, 0);
142 sd->green_bal = v4l2_ctrl_new_custom(hdl, &po1030_greenbal_cfg, NULL);
143 sd->red_bal = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops,
144 V4L2_CID_RED_BALANCE, 0, 255, 1,
145 PO1030_RED_GAIN_DEFAULT);
146 sd->blue_bal = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops,
147 V4L2_CID_BLUE_BALANCE, 0, 255, 1,
148 PO1030_BLUE_GAIN_DEFAULT);
149
150 sd->autoexpo = v4l2_ctrl_new_std_menu(hdl, &po1030_ctrl_ops,
151 V4L2_CID_EXPOSURE_AUTO, 1, 0, V4L2_EXPOSURE_MANUAL);
152 sd->expo = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops, V4L2_CID_EXPOSURE,
153 0, 0x2ff, 1, PO1030_EXPOSURE_DEFAULT);
154
155 sd->gain = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops, V4L2_CID_GAIN, 0,
156 0x4f, 1, PO1030_GLOBAL_GAIN_DEFAULT);
157
158 sd->hflip = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops, V4L2_CID_HFLIP,
159 0, 1, 1, 0);
160 sd->vflip = v4l2_ctrl_new_std(hdl, &po1030_ctrl_ops, V4L2_CID_VFLIP,
161 0, 1, 1, 0);
162
163 if (hdl->error) {
164 pr_err("Could not initialize controls\n");
165 return hdl->error;
166 }
313 167
314 err = po1030_set_auto_white_balance(&sd->gspca_dev, 168 v4l2_ctrl_auto_cluster(4, &sd->auto_white_bal, 0, false);
315 sensor_settings[AUTO_WHITE_BALANCE_IDX]); 169 v4l2_ctrl_auto_cluster(2, &sd->autoexpo, 0, false);
316 if (err < 0) 170 v4l2_ctrl_cluster(2, &sd->hflip);
317 return err;
318 171
319 err = po1030_set_auto_exposure(&sd->gspca_dev, 172 return 0;
320 sensor_settings[AUTO_EXPOSURE_IDX]);
321 return err;
322} 173}
323 174
324int po1030_start(struct sd *sd) 175int po1030_start(struct sd *sd)
@@ -448,24 +299,12 @@ int po1030_start(struct sd *sd)
448 return err; 299 return err;
449} 300}
450 301
451static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
452{
453 struct sd *sd = (struct sd *) gspca_dev;
454 s32 *sensor_settings = sd->sensor_priv;
455
456 *val = sensor_settings[EXPOSURE_IDX];
457 PDEBUG(D_V4L2, "Exposure read as %d", *val);
458 return 0;
459}
460
461static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) 302static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
462{ 303{
463 struct sd *sd = (struct sd *) gspca_dev; 304 struct sd *sd = (struct sd *) gspca_dev;
464 s32 *sensor_settings = sd->sensor_priv;
465 u8 i2c_data; 305 u8 i2c_data;
466 int err; 306 int err;
467 307
468 sensor_settings[EXPOSURE_IDX] = val;
469 PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff); 308 PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
470 309
471 i2c_data = ((val & 0xff00) >> 8); 310 i2c_data = ((val & 0xff00) >> 8);
@@ -486,25 +325,12 @@ static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
486 return err; 325 return err;
487} 326}
488 327
489static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
490{
491 struct sd *sd = (struct sd *) gspca_dev;
492 s32 *sensor_settings = sd->sensor_priv;
493
494 *val = sensor_settings[GAIN_IDX];
495 PDEBUG(D_V4L2, "Read global gain %d", *val);
496 return 0;
497}
498
499static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) 328static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
500{ 329{
501 struct sd *sd = (struct sd *) gspca_dev; 330 struct sd *sd = (struct sd *) gspca_dev;
502 s32 *sensor_settings = sd->sensor_priv;
503 u8 i2c_data; 331 u8 i2c_data;
504 int err; 332 int err;
505 333
506 sensor_settings[GAIN_IDX] = val;
507
508 i2c_data = val & 0xff; 334 i2c_data = val & 0xff;
509 PDEBUG(D_V4L2, "Set global gain to %d", i2c_data); 335 PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
510 err = m5602_write_sensor(sd, PO1030_GLOBALGAIN, 336 err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
@@ -512,65 +338,19 @@ static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
512 return err; 338 return err;
513} 339}
514 340
515static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) 341static int po1030_set_hvflip(struct gspca_dev *gspca_dev)
516{
517 struct sd *sd = (struct sd *) gspca_dev;
518 s32 *sensor_settings = sd->sensor_priv;
519
520 *val = sensor_settings[HFLIP_IDX];
521 PDEBUG(D_V4L2, "Read hflip %d", *val);
522
523 return 0;
524}
525
526static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
527{
528 struct sd *sd = (struct sd *) gspca_dev;
529 s32 *sensor_settings = sd->sensor_priv;
530 u8 i2c_data;
531 int err;
532
533 sensor_settings[HFLIP_IDX] = val;
534
535 PDEBUG(D_V4L2, "Set hflip %d", val);
536 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
537 if (err < 0)
538 return err;
539
540 i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
541
542 err = m5602_write_sensor(sd, PO1030_CONTROL2,
543 &i2c_data, 1);
544
545 return err;
546}
547
548static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
549{ 342{
550 struct sd *sd = (struct sd *) gspca_dev; 343 struct sd *sd = (struct sd *) gspca_dev;
551 s32 *sensor_settings = sd->sensor_priv;
552
553 *val = sensor_settings[VFLIP_IDX];
554 PDEBUG(D_V4L2, "Read vflip %d", *val);
555
556 return 0;
557}
558
559static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
560{
561 struct sd *sd = (struct sd *) gspca_dev;
562 s32 *sensor_settings = sd->sensor_priv;
563 u8 i2c_data; 344 u8 i2c_data;
564 int err; 345 int err;
565 346
566 sensor_settings[VFLIP_IDX] = val; 347 PDEBUG(D_V4L2, "Set hvflip %d %d", sd->hflip->val, sd->vflip->val);
567
568 PDEBUG(D_V4L2, "Set vflip %d", val);
569 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1); 348 err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
570 if (err < 0) 349 if (err < 0)
571 return err; 350 return err;
572 351
573 i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6); 352 i2c_data = (0x3f & i2c_data) | (sd->hflip->val << 7) |
353 (sd->vflip->val << 6);
574 354
575 err = m5602_write_sensor(sd, PO1030_CONTROL2, 355 err = m5602_write_sensor(sd, PO1030_CONTROL2,
576 &i2c_data, 1); 356 &i2c_data, 1);
@@ -578,25 +358,12 @@ static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
578 return err; 358 return err;
579} 359}
580 360
581static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
582{
583 struct sd *sd = (struct sd *) gspca_dev;
584 s32 *sensor_settings = sd->sensor_priv;
585
586 *val = sensor_settings[RED_BALANCE_IDX];
587 PDEBUG(D_V4L2, "Read red gain %d", *val);
588 return 0;
589}
590
591static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) 361static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
592{ 362{
593 struct sd *sd = (struct sd *) gspca_dev; 363 struct sd *sd = (struct sd *) gspca_dev;
594 s32 *sensor_settings = sd->sensor_priv;
595 u8 i2c_data; 364 u8 i2c_data;
596 int err; 365 int err;
597 366
598 sensor_settings[RED_BALANCE_IDX] = val;
599
600 i2c_data = val & 0xff; 367 i2c_data = val & 0xff;
601 PDEBUG(D_V4L2, "Set red gain to %d", i2c_data); 368 PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
602 err = m5602_write_sensor(sd, PO1030_RED_GAIN, 369 err = m5602_write_sensor(sd, PO1030_RED_GAIN,
@@ -604,26 +371,12 @@ static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
604 return err; 371 return err;
605} 372}
606 373
607static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
608{
609 struct sd *sd = (struct sd *) gspca_dev;
610 s32 *sensor_settings = sd->sensor_priv;
611
612 *val = sensor_settings[BLUE_BALANCE_IDX];
613 PDEBUG(D_V4L2, "Read blue gain %d", *val);
614
615 return 0;
616}
617
618static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) 374static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
619{ 375{
620 struct sd *sd = (struct sd *) gspca_dev; 376 struct sd *sd = (struct sd *) gspca_dev;
621 s32 *sensor_settings = sd->sensor_priv;
622 u8 i2c_data; 377 u8 i2c_data;
623 int err; 378 int err;
624 379
625 sensor_settings[BLUE_BALANCE_IDX] = val;
626
627 i2c_data = val & 0xff; 380 i2c_data = val & 0xff;
628 PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data); 381 PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
629 err = m5602_write_sensor(sd, PO1030_BLUE_GAIN, 382 err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
@@ -632,25 +385,12 @@ static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
632 return err; 385 return err;
633} 386}
634 387
635static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
636{
637 struct sd *sd = (struct sd *) gspca_dev;
638 s32 *sensor_settings = sd->sensor_priv;
639
640 *val = sensor_settings[GREEN_BALANCE_IDX];
641 PDEBUG(D_V4L2, "Read green gain %d", *val);
642
643 return 0;
644}
645
646static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val) 388static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
647{ 389{
648 struct sd *sd = (struct sd *) gspca_dev; 390 struct sd *sd = (struct sd *) gspca_dev;
649 s32 *sensor_settings = sd->sensor_priv;
650 u8 i2c_data; 391 u8 i2c_data;
651 int err; 392 int err;
652 393
653 sensor_settings[GREEN_BALANCE_IDX] = val;
654 i2c_data = val & 0xff; 394 i2c_data = val & 0xff;
655 PDEBUG(D_V4L2, "Set green gain to %d", i2c_data); 395 PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
656 396
@@ -663,28 +403,13 @@ static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
663 &i2c_data, 1); 403 &i2c_data, 1);
664} 404}
665 405
666static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
667 __s32 *val)
668{
669 struct sd *sd = (struct sd *) gspca_dev;
670 s32 *sensor_settings = sd->sensor_priv;
671
672 *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
673 PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
674
675 return 0;
676}
677
678static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, 406static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
679 __s32 val) 407 __s32 val)
680{ 408{
681 struct sd *sd = (struct sd *) gspca_dev; 409 struct sd *sd = (struct sd *) gspca_dev;
682 s32 *sensor_settings = sd->sensor_priv;
683 u8 i2c_data; 410 u8 i2c_data;
684 int err; 411 int err;
685 412
686 sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
687
688 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); 413 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
689 if (err < 0) 414 if (err < 0)
690 return err; 415 return err;
@@ -695,31 +420,19 @@ static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
695 return err; 420 return err;
696} 421}
697 422
698static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
699 __s32 *val)
700{
701 struct sd *sd = (struct sd *) gspca_dev;
702 s32 *sensor_settings = sd->sensor_priv;
703
704 *val = sensor_settings[AUTO_EXPOSURE_IDX];
705 PDEBUG(D_V4L2, "Auto exposure is %d", *val);
706 return 0;
707}
708
709static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev, 423static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
710 __s32 val) 424 __s32 val)
711{ 425{
712 struct sd *sd = (struct sd *) gspca_dev; 426 struct sd *sd = (struct sd *) gspca_dev;
713 s32 *sensor_settings = sd->sensor_priv;
714 u8 i2c_data; 427 u8 i2c_data;
715 int err; 428 int err;
716 429
717 sensor_settings[AUTO_EXPOSURE_IDX] = val;
718 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); 430 err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
719 if (err < 0) 431 if (err < 0)
720 return err; 432 return err;
721 433
722 PDEBUG(D_V4L2, "Set auto exposure to %d", val); 434 PDEBUG(D_V4L2, "Set auto exposure to %d", val);
435 val = (val == V4L2_EXPOSURE_AUTO);
723 i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1); 436 i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
724 return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1); 437 return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
725} 438}
@@ -727,7 +440,48 @@ static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
727void po1030_disconnect(struct sd *sd) 440void po1030_disconnect(struct sd *sd)
728{ 441{
729 sd->sensor = NULL; 442 sd->sensor = NULL;
730 kfree(sd->sensor_priv); 443}
444
445static int po1030_s_ctrl(struct v4l2_ctrl *ctrl)
446{
447 struct gspca_dev *gspca_dev =
448 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
449 struct sd *sd = (struct sd *) gspca_dev;
450 int err;
451
452 if (!gspca_dev->streaming)
453 return 0;
454
455 switch (ctrl->id) {
456 case V4L2_CID_AUTO_WHITE_BALANCE:
457 err = po1030_set_auto_white_balance(gspca_dev, ctrl->val);
458 if (err || ctrl->val)
459 return err;
460 err = po1030_set_green_balance(gspca_dev, sd->green_bal->val);
461 if (err)
462 return err;
463 err = po1030_set_red_balance(gspca_dev, sd->red_bal->val);
464 if (err)
465 return err;
466 err = po1030_set_blue_balance(gspca_dev, sd->blue_bal->val);
467 break;
468 case V4L2_CID_EXPOSURE_AUTO:
469 err = po1030_set_auto_exposure(gspca_dev, ctrl->val);
470 if (err || ctrl->val == V4L2_EXPOSURE_AUTO)
471 return err;
472 err = po1030_set_exposure(gspca_dev, sd->expo->val);
473 break;
474 case V4L2_CID_GAIN:
475 err = po1030_set_gain(gspca_dev, ctrl->val);
476 break;
477 case V4L2_CID_HFLIP:
478 err = po1030_set_hvflip(gspca_dev);
479 break;
480 default:
481 return -EINVAL;
482 }
483
484 return err;
731} 485}
732 486
733static void po1030_dump_registers(struct sd *sd) 487static void po1030_dump_registers(struct sd *sd)
diff --git a/drivers/media/usb/gspca/m5602/m5602_po1030.h b/drivers/media/usb/gspca/m5602/m5602_po1030.h
index 81a2bcb88fe3..a6ab76149bd0 100644
--- a/drivers/media/usb/gspca/m5602/m5602_po1030.h
+++ b/drivers/media/usb/gspca/m5602/m5602_po1030.h
@@ -151,6 +151,7 @@ extern bool dump_sensor;
151 151
152int po1030_probe(struct sd *sd); 152int po1030_probe(struct sd *sd);
153int po1030_init(struct sd *sd); 153int po1030_init(struct sd *sd);
154int po1030_init_controls(struct sd *sd);
154int po1030_start(struct sd *sd); 155int po1030_start(struct sd *sd);
155void po1030_disconnect(struct sd *sd); 156void po1030_disconnect(struct sd *sd);
156 157
@@ -162,6 +163,7 @@ static const struct m5602_sensor po1030 = {
162 163
163 .probe = po1030_probe, 164 .probe = po1030_probe,
164 .init = po1030_init, 165 .init = po1030_init,
166 .init_controls = po1030_init_controls,
165 .start = po1030_start, 167 .start = po1030_start,
166 .disconnect = po1030_disconnect, 168 .disconnect = po1030_disconnect,
167}; 169};
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
index c8e1572eb502..42ffaf04771c 100644
--- a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
@@ -20,18 +20,12 @@
20 20
21#include "m5602_s5k4aa.h" 21#include "m5602_s5k4aa.h"
22 22
23static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); 23static int s5k4aa_s_ctrl(struct v4l2_ctrl *ctrl);
24static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); 24static void s5k4aa_dump_registers(struct sd *sd);
25static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); 25
26static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val); 26static const struct v4l2_ctrl_ops s5k4aa_ctrl_ops = {
27static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); 27 .s_ctrl = s5k4aa_s_ctrl,
28static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); 28};
29static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
30static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
31static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val);
32static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val);
33static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
34static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
35 29
36static 30static
37 const 31 const
@@ -147,104 +141,11 @@ static struct v4l2_pix_format s5k4aa_modes[] = {
147 } 141 }
148}; 142};
149 143
150static const struct ctrl s5k4aa_ctrls[] = {
151#define VFLIP_IDX 0
152 {
153 {
154 .id = V4L2_CID_VFLIP,
155 .type = V4L2_CTRL_TYPE_BOOLEAN,
156 .name = "vertical flip",
157 .minimum = 0,
158 .maximum = 1,
159 .step = 1,
160 .default_value = 0
161 },
162 .set = s5k4aa_set_vflip,
163 .get = s5k4aa_get_vflip
164 },
165#define HFLIP_IDX 1
166 {
167 {
168 .id = V4L2_CID_HFLIP,
169 .type = V4L2_CTRL_TYPE_BOOLEAN,
170 .name = "horizontal flip",
171 .minimum = 0,
172 .maximum = 1,
173 .step = 1,
174 .default_value = 0
175 },
176 .set = s5k4aa_set_hflip,
177 .get = s5k4aa_get_hflip
178 },
179#define GAIN_IDX 2
180 {
181 {
182 .id = V4L2_CID_GAIN,
183 .type = V4L2_CTRL_TYPE_INTEGER,
184 .name = "Gain",
185 .minimum = 0,
186 .maximum = 127,
187 .step = 1,
188 .default_value = S5K4AA_DEFAULT_GAIN,
189 .flags = V4L2_CTRL_FLAG_SLIDER
190 },
191 .set = s5k4aa_set_gain,
192 .get = s5k4aa_get_gain
193 },
194#define EXPOSURE_IDX 3
195 {
196 {
197 .id = V4L2_CID_EXPOSURE,
198 .type = V4L2_CTRL_TYPE_INTEGER,
199 .name = "Exposure",
200 .minimum = 13,
201 .maximum = 0xfff,
202 .step = 1,
203 .default_value = 0x100,
204 .flags = V4L2_CTRL_FLAG_SLIDER
205 },
206 .set = s5k4aa_set_exposure,
207 .get = s5k4aa_get_exposure
208 },
209#define NOISE_SUPP_IDX 4
210 {
211 {
212 .id = V4L2_CID_PRIVATE_BASE,
213 .type = V4L2_CTRL_TYPE_BOOLEAN,
214 .name = "Noise suppression (smoothing)",
215 .minimum = 0,
216 .maximum = 1,
217 .step = 1,
218 .default_value = 1,
219 },
220 .set = s5k4aa_set_noise,
221 .get = s5k4aa_get_noise
222 },
223#define BRIGHTNESS_IDX 5
224 {
225 {
226 .id = V4L2_CID_BRIGHTNESS,
227 .type = V4L2_CTRL_TYPE_INTEGER,
228 .name = "Brightness",
229 .minimum = 0,
230 .maximum = 0x1f,
231 .step = 1,
232 .default_value = S5K4AA_DEFAULT_BRIGHTNESS,
233 },
234 .set = s5k4aa_set_brightness,
235 .get = s5k4aa_get_brightness
236 },
237
238};
239
240static void s5k4aa_dump_registers(struct sd *sd);
241
242int s5k4aa_probe(struct sd *sd) 144int s5k4aa_probe(struct sd *sd)
243{ 145{
244 u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 146 u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
245 const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75}; 147 const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
246 int i, err = 0; 148 int i, err = 0;
247 s32 *sensor_settings;
248 149
249 if (force_sensor) { 150 if (force_sensor) {
250 if (force_sensor == S5K4AA_SENSOR) { 151 if (force_sensor == S5K4AA_SENSOR) {
@@ -303,19 +204,8 @@ int s5k4aa_probe(struct sd *sd)
303 pr_info("Detected a s5k4aa sensor\n"); 204 pr_info("Detected a s5k4aa sensor\n");
304 205
305sensor_found: 206sensor_found:
306 sensor_settings = kmalloc(
307 ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
308 if (!sensor_settings)
309 return -ENOMEM;
310
311 sd->gspca_dev.cam.cam_mode = s5k4aa_modes; 207 sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
312 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes); 208 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
313 sd->desc->ctrls = s5k4aa_ctrls;
314 sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
315
316 for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
317 sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
318 sd->sensor_priv = sensor_settings;
319 209
320 return 0; 210 return 0;
321} 211}
@@ -325,7 +215,6 @@ int s5k4aa_start(struct sd *sd)
325 int i, err = 0; 215 int i, err = 0;
326 u8 data[2]; 216 u8 data[2];
327 struct cam *cam = &sd->gspca_dev.cam; 217 struct cam *cam = &sd->gspca_dev.cam;
328 s32 *sensor_settings = sd->sensor_priv;
329 218
330 switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) { 219 switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
331 case 1280: 220 case 1280:
@@ -359,9 +248,6 @@ int s5k4aa_start(struct sd *sd)
359 return -EINVAL; 248 return -EINVAL;
360 } 249 }
361 } 250 }
362 err = s5k4aa_set_noise(&sd->gspca_dev, 0);
363 if (err < 0)
364 return err;
365 break; 251 break;
366 252
367 case 640: 253 case 640:
@@ -395,37 +281,12 @@ int s5k4aa_start(struct sd *sd)
395 return -EINVAL; 281 return -EINVAL;
396 } 282 }
397 } 283 }
398 err = s5k4aa_set_noise(&sd->gspca_dev, 1);
399 if (err < 0)
400 return err;
401 break; 284 break;
402 } 285 }
403 if (err < 0) 286 if (err < 0)
404 return err; 287 return err;
405 288
406 err = s5k4aa_set_exposure(&sd->gspca_dev, 289 return 0;
407 sensor_settings[EXPOSURE_IDX]);
408 if (err < 0)
409 return err;
410
411 err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
412 if (err < 0)
413 return err;
414
415 err = s5k4aa_set_brightness(&sd->gspca_dev,
416 sensor_settings[BRIGHTNESS_IDX]);
417 if (err < 0)
418 return err;
419
420 err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
421 if (err < 0)
422 return err;
423
424 err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
425 if (err < 0)
426 return err;
427
428 return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
429} 290}
430 291
431int s5k4aa_init(struct sd *sd) 292int s5k4aa_init(struct sd *sd)
@@ -466,13 +327,36 @@ int s5k4aa_init(struct sd *sd)
466 return err; 327 return err;
467} 328}
468 329
469static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) 330int s5k4aa_init_controls(struct sd *sd)
470{ 331{
471 struct sd *sd = (struct sd *) gspca_dev; 332 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
472 s32 *sensor_settings = sd->sensor_priv; 333
334 sd->gspca_dev.vdev.ctrl_handler = hdl;
335 v4l2_ctrl_handler_init(hdl, 6);
473 336
474 *val = sensor_settings[EXPOSURE_IDX]; 337 v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_BRIGHTNESS,
475 PDEBUG(D_V4L2, "Read exposure %d", *val); 338 0, 0x1f, 1, S5K4AA_DEFAULT_BRIGHTNESS);
339
340 v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_EXPOSURE,
341 13, 0xfff, 1, 0x100);
342
343 v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_GAIN,
344 0, 127, 1, S5K4AA_DEFAULT_GAIN);
345
346 v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_SHARPNESS,
347 0, 1, 1, 1);
348
349 sd->hflip = v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_HFLIP,
350 0, 1, 1, 0);
351 sd->vflip = v4l2_ctrl_new_std(hdl, &s5k4aa_ctrl_ops, V4L2_CID_VFLIP,
352 0, 1, 1, 0);
353
354 if (hdl->error) {
355 pr_err("Could not initialize controls\n");
356 return hdl->error;
357 }
358
359 v4l2_ctrl_cluster(2, &sd->hflip);
476 360
477 return 0; 361 return 0;
478} 362}
@@ -480,11 +364,9 @@ static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
480static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) 364static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
481{ 365{
482 struct sd *sd = (struct sd *) gspca_dev; 366 struct sd *sd = (struct sd *) gspca_dev;
483 s32 *sensor_settings = sd->sensor_priv;
484 u8 data = S5K4AA_PAGE_MAP_2; 367 u8 data = S5K4AA_PAGE_MAP_2;
485 int err; 368 int err;
486 369
487 sensor_settings[EXPOSURE_IDX] = val;
488 PDEBUG(D_V4L2, "Set exposure to %d", val); 370 PDEBUG(D_V4L2, "Set exposure to %d", val);
489 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 371 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
490 if (err < 0) 372 if (err < 0)
@@ -499,27 +381,15 @@ static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
499 return err; 381 return err;
500} 382}
501 383
502static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) 384static int s5k4aa_set_hvflip(struct gspca_dev *gspca_dev)
503{ 385{
504 struct sd *sd = (struct sd *) gspca_dev; 386 struct sd *sd = (struct sd *) gspca_dev;
505 s32 *sensor_settings = sd->sensor_priv;
506
507 *val = sensor_settings[VFLIP_IDX];
508 PDEBUG(D_V4L2, "Read vertical flip %d", *val);
509
510 return 0;
511}
512
513static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
514{
515 struct sd *sd = (struct sd *) gspca_dev;
516 s32 *sensor_settings = sd->sensor_priv;
517 u8 data = S5K4AA_PAGE_MAP_2; 387 u8 data = S5K4AA_PAGE_MAP_2;
518 int err; 388 int err;
389 int hflip = sd->hflip->val;
390 int vflip = sd->vflip->val;
519 391
520 sensor_settings[VFLIP_IDX] = val; 392 PDEBUG(D_V4L2, "Set hvflip %d %d", hflip, vflip);
521
522 PDEBUG(D_V4L2, "Set vertical flip to %d", val);
523 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 393 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
524 if (err < 0) 394 if (err < 0)
525 return err; 395 return err;
@@ -528,92 +398,47 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
528 if (err < 0) 398 if (err < 0)
529 return err; 399 return err;
530 400
531 if (dmi_check_system(s5k4aa_vflip_dmi_table)) 401 if (dmi_check_system(s5k4aa_vflip_dmi_table)) {
532 val = !val; 402 hflip = !hflip;
403 vflip = !vflip;
404 }
533 405
534 data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7)); 406 data = (data & 0x7f) | (vflip << 7) | (hflip << 6);
535 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1); 407 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
536 if (err < 0) 408 if (err < 0)
537 return err; 409 return err;
538 410
539 err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); 411 err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
540 if (err < 0) 412 if (err < 0)
541 return err; 413 return err;
542 if (val) 414 if (hflip)
543 data &= 0xfe; 415 data &= 0xfe;
544 else 416 else
545 data |= 0x01; 417 data |= 0x01;
546 err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); 418 err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
547 return err;
548}
549
550static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
551{
552 struct sd *sd = (struct sd *) gspca_dev;
553 s32 *sensor_settings = sd->sensor_priv;
554
555 *val = sensor_settings[HFLIP_IDX];
556 PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
557
558 return 0;
559}
560
561static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
562{
563 struct sd *sd = (struct sd *) gspca_dev;
564 s32 *sensor_settings = sd->sensor_priv;
565 u8 data = S5K4AA_PAGE_MAP_2;
566 int err;
567
568 sensor_settings[HFLIP_IDX] = val;
569
570 PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
571 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
572 if (err < 0)
573 return err;
574
575 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
576 if (err < 0)
577 return err;
578
579 if (dmi_check_system(s5k4aa_vflip_dmi_table))
580 val = !val;
581
582 data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
583 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
584 if (err < 0) 419 if (err < 0)
585 return err; 420 return err;
586 421
587 err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); 422 err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
588 if (err < 0) 423 if (err < 0)
589 return err; 424 return err;
590 if (val) 425 if (vflip)
591 data &= 0xfe; 426 data &= 0xfe;
592 else 427 else
593 data |= 0x01; 428 data |= 0x01;
594 err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); 429 err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
595 return err; 430 if (err < 0)
596} 431 return err;
597
598static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
599{
600 struct sd *sd = (struct sd *) gspca_dev;
601 s32 *sensor_settings = sd->sensor_priv;
602 432
603 *val = sensor_settings[GAIN_IDX];
604 PDEBUG(D_V4L2, "Read gain %d", *val);
605 return 0; 433 return 0;
606} 434}
607 435
608static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) 436static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
609{ 437{
610 struct sd *sd = (struct sd *) gspca_dev; 438 struct sd *sd = (struct sd *) gspca_dev;
611 s32 *sensor_settings = sd->sensor_priv;
612 u8 data = S5K4AA_PAGE_MAP_2; 439 u8 data = S5K4AA_PAGE_MAP_2;
613 int err; 440 int err;
614 441
615 sensor_settings[GAIN_IDX] = val;
616
617 PDEBUG(D_V4L2, "Set gain to %d", val); 442 PDEBUG(D_V4L2, "Set gain to %d", val);
618 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 443 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
619 if (err < 0) 444 if (err < 0)
@@ -625,25 +450,12 @@ static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
625 return err; 450 return err;
626} 451}
627 452
628static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
629{
630 struct sd *sd = (struct sd *) gspca_dev;
631 s32 *sensor_settings = sd->sensor_priv;
632
633 *val = sensor_settings[BRIGHTNESS_IDX];
634 PDEBUG(D_V4L2, "Read brightness %d", *val);
635 return 0;
636}
637
638static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val) 453static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
639{ 454{
640 struct sd *sd = (struct sd *) gspca_dev; 455 struct sd *sd = (struct sd *) gspca_dev;
641 s32 *sensor_settings = sd->sensor_priv;
642 u8 data = S5K4AA_PAGE_MAP_2; 456 u8 data = S5K4AA_PAGE_MAP_2;
643 int err; 457 int err;
644 458
645 sensor_settings[BRIGHTNESS_IDX] = val;
646
647 PDEBUG(D_V4L2, "Set brightness to %d", val); 459 PDEBUG(D_V4L2, "Set brightness to %d", val);
648 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 460 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
649 if (err < 0) 461 if (err < 0)
@@ -653,25 +465,12 @@ static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
653 return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1); 465 return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
654} 466}
655 467
656static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
657{
658 struct sd *sd = (struct sd *) gspca_dev;
659 s32 *sensor_settings = sd->sensor_priv;
660
661 *val = sensor_settings[NOISE_SUPP_IDX];
662 PDEBUG(D_V4L2, "Read noise %d", *val);
663 return 0;
664}
665
666static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val) 468static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
667{ 469{
668 struct sd *sd = (struct sd *) gspca_dev; 470 struct sd *sd = (struct sd *) gspca_dev;
669 s32 *sensor_settings = sd->sensor_priv;
670 u8 data = S5K4AA_PAGE_MAP_2; 471 u8 data = S5K4AA_PAGE_MAP_2;
671 int err; 472 int err;
672 473
673 sensor_settings[NOISE_SUPP_IDX] = val;
674
675 PDEBUG(D_V4L2, "Set noise to %d", val); 474 PDEBUG(D_V4L2, "Set noise to %d", val);
676 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 475 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
677 if (err < 0) 476 if (err < 0)
@@ -681,10 +480,41 @@ static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
681 return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1); 480 return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
682} 481}
683 482
483static int s5k4aa_s_ctrl(struct v4l2_ctrl *ctrl)
484{
485 struct gspca_dev *gspca_dev =
486 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
487 int err;
488
489 if (!gspca_dev->streaming)
490 return 0;
491
492 switch (ctrl->id) {
493 case V4L2_CID_BRIGHTNESS:
494 err = s5k4aa_set_brightness(gspca_dev, ctrl->val);
495 break;
496 case V4L2_CID_EXPOSURE:
497 err = s5k4aa_set_exposure(gspca_dev, ctrl->val);
498 break;
499 case V4L2_CID_GAIN:
500 err = s5k4aa_set_gain(gspca_dev, ctrl->val);
501 break;
502 case V4L2_CID_SHARPNESS:
503 err = s5k4aa_set_noise(gspca_dev, ctrl->val);
504 break;
505 case V4L2_CID_HFLIP:
506 err = s5k4aa_set_hvflip(gspca_dev);
507 break;
508 default:
509 return -EINVAL;
510 }
511
512 return err;
513}
514
684void s5k4aa_disconnect(struct sd *sd) 515void s5k4aa_disconnect(struct sd *sd)
685{ 516{
686 sd->sensor = NULL; 517 sd->sensor = NULL;
687 kfree(sd->sensor_priv);
688} 518}
689 519
690static void s5k4aa_dump_registers(struct sd *sd) 520static void s5k4aa_dump_registers(struct sd *sd)
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h
index 8e0035e731c7..9953e9766954 100644
--- a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h
@@ -69,6 +69,7 @@ extern bool dump_sensor;
69 69
70int s5k4aa_probe(struct sd *sd); 70int s5k4aa_probe(struct sd *sd);
71int s5k4aa_init(struct sd *sd); 71int s5k4aa_init(struct sd *sd);
72int s5k4aa_init_controls(struct sd *sd);
72int s5k4aa_start(struct sd *sd); 73int s5k4aa_start(struct sd *sd);
73void s5k4aa_disconnect(struct sd *sd); 74void s5k4aa_disconnect(struct sd *sd);
74 75
@@ -79,6 +80,7 @@ static const struct m5602_sensor s5k4aa = {
79 80
80 .probe = s5k4aa_probe, 81 .probe = s5k4aa_probe,
81 .init = s5k4aa_init, 82 .init = s5k4aa_init,
83 .init_controls = s5k4aa_init_controls,
82 .start = s5k4aa_start, 84 .start = s5k4aa_start,
83 .disconnect = s5k4aa_disconnect, 85 .disconnect = s5k4aa_disconnect,
84}; 86};
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
index 1de743a02b02..69ee6e26b8ea 100644
--- a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
@@ -21,16 +21,11 @@
21#include <linux/kthread.h> 21#include <linux/kthread.h>
22#include "m5602_s5k83a.h" 22#include "m5602_s5k83a.h"
23 23
24static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); 24static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl);
25static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); 25
26static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); 26static const struct v4l2_ctrl_ops s5k83a_ctrl_ops = {
27static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); 27 .s_ctrl = s5k83a_s_ctrl,
28static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val); 28};
29static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
30static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
31static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
32static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
33static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
34 29
35static struct v4l2_pix_format s5k83a_modes[] = { 30static struct v4l2_pix_format s5k83a_modes[] = {
36 { 31 {
@@ -46,83 +41,6 @@ static struct v4l2_pix_format s5k83a_modes[] = {
46 } 41 }
47}; 42};
48 43
49static const struct ctrl s5k83a_ctrls[] = {
50#define GAIN_IDX 0
51 {
52 {
53 .id = V4L2_CID_GAIN,
54 .type = V4L2_CTRL_TYPE_INTEGER,
55 .name = "gain",
56 .minimum = 0x00,
57 .maximum = 0xff,
58 .step = 0x01,
59 .default_value = S5K83A_DEFAULT_GAIN,
60 .flags = V4L2_CTRL_FLAG_SLIDER
61 },
62 .set = s5k83a_set_gain,
63 .get = s5k83a_get_gain
64
65 },
66#define BRIGHTNESS_IDX 1
67 {
68 {
69 .id = V4L2_CID_BRIGHTNESS,
70 .type = V4L2_CTRL_TYPE_INTEGER,
71 .name = "brightness",
72 .minimum = 0x00,
73 .maximum = 0xff,
74 .step = 0x01,
75 .default_value = S5K83A_DEFAULT_BRIGHTNESS,
76 .flags = V4L2_CTRL_FLAG_SLIDER
77 },
78 .set = s5k83a_set_brightness,
79 .get = s5k83a_get_brightness,
80 },
81#define EXPOSURE_IDX 2
82 {
83 {
84 .id = V4L2_CID_EXPOSURE,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "exposure",
87 .minimum = 0x00,
88 .maximum = S5K83A_MAXIMUM_EXPOSURE,
89 .step = 0x01,
90 .default_value = S5K83A_DEFAULT_EXPOSURE,
91 .flags = V4L2_CTRL_FLAG_SLIDER
92 },
93 .set = s5k83a_set_exposure,
94 .get = s5k83a_get_exposure
95 },
96#define HFLIP_IDX 3
97 {
98 {
99 .id = V4L2_CID_HFLIP,
100 .type = V4L2_CTRL_TYPE_BOOLEAN,
101 .name = "horizontal flip",
102 .minimum = 0,
103 .maximum = 1,
104 .step = 1,
105 .default_value = 0
106 },
107 .set = s5k83a_set_hflip,
108 .get = s5k83a_get_hflip
109 },
110#define VFLIP_IDX 4
111 {
112 {
113 .id = V4L2_CID_VFLIP,
114 .type = V4L2_CTRL_TYPE_BOOLEAN,
115 .name = "vertical flip",
116 .minimum = 0,
117 .maximum = 1,
118 .step = 1,
119 .default_value = 0
120 },
121 .set = s5k83a_set_vflip,
122 .get = s5k83a_get_vflip
123 }
124};
125
126static void s5k83a_dump_registers(struct sd *sd); 44static void s5k83a_dump_registers(struct sd *sd);
127static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data); 45static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
128static int s5k83a_set_led_indication(struct sd *sd, u8 val); 46static int s5k83a_set_led_indication(struct sd *sd, u8 val);
@@ -131,7 +49,6 @@ static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
131 49
132int s5k83a_probe(struct sd *sd) 50int s5k83a_probe(struct sd *sd)
133{ 51{
134 struct s5k83a_priv *sens_priv;
135 u8 prod_id = 0, ver_id = 0; 52 u8 prod_id = 0, ver_id = 0;
136 int i, err = 0; 53 int i, err = 0;
137 54
@@ -173,38 +90,18 @@ int s5k83a_probe(struct sd *sd)
173 pr_info("Detected a s5k83a sensor\n"); 90 pr_info("Detected a s5k83a sensor\n");
174 91
175sensor_found: 92sensor_found:
176 sens_priv = kmalloc(
177 sizeof(struct s5k83a_priv), GFP_KERNEL);
178 if (!sens_priv)
179 return -ENOMEM;
180
181 sens_priv->settings =
182 kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
183 if (!sens_priv->settings) {
184 kfree(sens_priv);
185 return -ENOMEM;
186 }
187
188 sd->gspca_dev.cam.cam_mode = s5k83a_modes; 93 sd->gspca_dev.cam.cam_mode = s5k83a_modes;
189 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes); 94 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
190 sd->desc->ctrls = s5k83a_ctrls;
191 sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
192 95
193 /* null the pointer! thread is't running now */ 96 /* null the pointer! thread is't running now */
194 sens_priv->rotation_thread = NULL; 97 sd->rotation_thread = NULL;
195
196 for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++)
197 sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value;
198 98
199 sd->sensor_priv = sens_priv;
200 return 0; 99 return 0;
201} 100}
202 101
203int s5k83a_init(struct sd *sd) 102int s5k83a_init(struct sd *sd)
204{ 103{
205 int i, err = 0; 104 int i, err = 0;
206 s32 *sensor_settings =
207 ((struct s5k83a_priv *) sd->sensor_priv)->settings;
208 105
209 for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) { 106 for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
210 u8 data[2] = {0x00, 0x00}; 107 u8 data[2] = {0x00, 0x00};
@@ -237,33 +134,44 @@ int s5k83a_init(struct sd *sd)
237 if (dump_sensor) 134 if (dump_sensor)
238 s5k83a_dump_registers(sd); 135 s5k83a_dump_registers(sd);
239 136
240 err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]); 137 return err;
241 if (err < 0) 138}
242 return err;
243 139
244 err = s5k83a_set_brightness(&sd->gspca_dev, 140int s5k83a_init_controls(struct sd *sd)
245 sensor_settings[BRIGHTNESS_IDX]); 141{
246 if (err < 0) 142 struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
247 return err;
248 143
249 err = s5k83a_set_exposure(&sd->gspca_dev, 144 sd->gspca_dev.vdev.ctrl_handler = hdl;
250 sensor_settings[EXPOSURE_IDX]); 145 v4l2_ctrl_handler_init(hdl, 6);
251 if (err < 0)
252 return err;
253 146
254 err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]); 147 v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_BRIGHTNESS,
255 if (err < 0) 148 0, 255, 1, S5K83A_DEFAULT_BRIGHTNESS);
256 return err;
257 149
258 err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]); 150 v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_EXPOSURE,
151 0, S5K83A_MAXIMUM_EXPOSURE, 1,
152 S5K83A_DEFAULT_EXPOSURE);
259 153
260 return err; 154 v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_GAIN,
155 0, 255, 1, S5K83A_DEFAULT_GAIN);
156
157 sd->hflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_HFLIP,
158 0, 1, 1, 0);
159 sd->vflip = v4l2_ctrl_new_std(hdl, &s5k83a_ctrl_ops, V4L2_CID_VFLIP,
160 0, 1, 1, 0);
161
162 if (hdl->error) {
163 pr_err("Could not initialize controls\n");
164 return hdl->error;
165 }
166
167 v4l2_ctrl_cluster(2, &sd->hflip);
168
169 return 0;
261} 170}
262 171
263static int rotation_thread_function(void *data) 172static int rotation_thread_function(void *data)
264{ 173{
265 struct sd *sd = (struct sd *) data; 174 struct sd *sd = (struct sd *) data;
266 struct s5k83a_priv *sens_priv = sd->sensor_priv;
267 u8 reg, previous_rotation = 0; 175 u8 reg, previous_rotation = 0;
268 __s32 vflip, hflip; 176 __s32 vflip, hflip;
269 177
@@ -277,8 +185,8 @@ static int rotation_thread_function(void *data)
277 previous_rotation = reg; 185 previous_rotation = reg;
278 pr_info("Camera was flipped\n"); 186 pr_info("Camera was flipped\n");
279 187
280 s5k83a_get_vflip((struct gspca_dev *) sd, &vflip); 188 hflip = sd->hflip->val;
281 s5k83a_get_hflip((struct gspca_dev *) sd, &hflip); 189 vflip = sd->vflip->val;
282 190
283 if (reg) { 191 if (reg) {
284 vflip = !vflip; 192 vflip = !vflip;
@@ -294,26 +202,25 @@ static int rotation_thread_function(void *data)
294 202
295 /* return to "front" flip */ 203 /* return to "front" flip */
296 if (previous_rotation) { 204 if (previous_rotation) {
297 s5k83a_get_vflip((struct gspca_dev *) sd, &vflip); 205 hflip = sd->hflip->val;
298 s5k83a_get_hflip((struct gspca_dev *) sd, &hflip); 206 vflip = sd->vflip->val;
299 s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip); 207 s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
300 } 208 }
301 209
302 sens_priv->rotation_thread = NULL; 210 sd->rotation_thread = NULL;
303 return 0; 211 return 0;
304} 212}
305 213
306int s5k83a_start(struct sd *sd) 214int s5k83a_start(struct sd *sd)
307{ 215{
308 int i, err = 0; 216 int i, err = 0;
309 struct s5k83a_priv *sens_priv = sd->sensor_priv;
310 217
311 /* Create another thread, polling the GPIO ports of the camera to check 218 /* Create another thread, polling the GPIO ports of the camera to check
312 if it got rotated. This is how the windows driver does it so we have 219 if it got rotated. This is how the windows driver does it so we have
313 to assume that there is no better way of accomplishing this */ 220 to assume that there is no better way of accomplishing this */
314 sens_priv->rotation_thread = kthread_create(rotation_thread_function, 221 sd->rotation_thread = kthread_create(rotation_thread_function,
315 sd, "rotation thread"); 222 sd, "rotation thread");
316 wake_up_process(sens_priv->rotation_thread); 223 wake_up_process(sd->rotation_thread);
317 224
318 /* Preinit the sensor */ 225 /* Preinit the sensor */
319 for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) { 226 for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
@@ -333,32 +240,17 @@ int s5k83a_start(struct sd *sd)
333 240
334int s5k83a_stop(struct sd *sd) 241int s5k83a_stop(struct sd *sd)
335{ 242{
336 struct s5k83a_priv *sens_priv = sd->sensor_priv; 243 if (sd->rotation_thread)
337 244 kthread_stop(sd->rotation_thread);
338 if (sens_priv->rotation_thread)
339 kthread_stop(sens_priv->rotation_thread);
340 245
341 return s5k83a_set_led_indication(sd, 0); 246 return s5k83a_set_led_indication(sd, 0);
342} 247}
343 248
344void s5k83a_disconnect(struct sd *sd) 249void s5k83a_disconnect(struct sd *sd)
345{ 250{
346 struct s5k83a_priv *sens_priv = sd->sensor_priv;
347
348 s5k83a_stop(sd); 251 s5k83a_stop(sd);
349 252
350 sd->sensor = NULL; 253 sd->sensor = NULL;
351 kfree(sens_priv->settings);
352 kfree(sens_priv);
353}
354
355static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
356{
357 struct sd *sd = (struct sd *) gspca_dev;
358 struct s5k83a_priv *sens_priv = sd->sensor_priv;
359
360 *val = sens_priv->settings[GAIN_IDX];
361 return 0;
362} 254}
363 255
364static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) 256static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
@@ -366,9 +258,6 @@ static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
366 int err; 258 int err;
367 u8 data[2]; 259 u8 data[2];
368 struct sd *sd = (struct sd *) gspca_dev; 260 struct sd *sd = (struct sd *) gspca_dev;
369 struct s5k83a_priv *sens_priv = sd->sensor_priv;
370
371 sens_priv->settings[GAIN_IDX] = val;
372 261
373 data[0] = 0x00; 262 data[0] = 0x00;
374 data[1] = 0x20; 263 data[1] = 0x20;
@@ -391,60 +280,29 @@ static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
391 return err; 280 return err;
392} 281}
393 282
394static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
395{
396 struct sd *sd = (struct sd *) gspca_dev;
397 struct s5k83a_priv *sens_priv = sd->sensor_priv;
398
399 *val = sens_priv->settings[BRIGHTNESS_IDX];
400 return 0;
401}
402
403static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) 283static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
404{ 284{
405 int err; 285 int err;
406 u8 data[1]; 286 u8 data[1];
407 struct sd *sd = (struct sd *) gspca_dev; 287 struct sd *sd = (struct sd *) gspca_dev;
408 struct s5k83a_priv *sens_priv = sd->sensor_priv;
409 288
410 sens_priv->settings[BRIGHTNESS_IDX] = val;
411 data[0] = val; 289 data[0] = val;
412 err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1); 290 err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
413 return err; 291 return err;
414} 292}
415 293
416static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
417{
418 struct sd *sd = (struct sd *) gspca_dev;
419 struct s5k83a_priv *sens_priv = sd->sensor_priv;
420
421 *val = sens_priv->settings[EXPOSURE_IDX];
422 return 0;
423}
424
425static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val) 294static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
426{ 295{
427 int err; 296 int err;
428 u8 data[2]; 297 u8 data[2];
429 struct sd *sd = (struct sd *) gspca_dev; 298 struct sd *sd = (struct sd *) gspca_dev;
430 struct s5k83a_priv *sens_priv = sd->sensor_priv;
431 299
432 sens_priv->settings[EXPOSURE_IDX] = val;
433 data[0] = 0; 300 data[0] = 0;
434 data[1] = val; 301 data[1] = val;
435 err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2); 302 err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
436 return err; 303 return err;
437} 304}
438 305
439static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
440{
441 struct sd *sd = (struct sd *) gspca_dev;
442 struct s5k83a_priv *sens_priv = sd->sensor_priv;
443
444 *val = sens_priv->settings[VFLIP_IDX];
445 return 0;
446}
447
448static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, 306static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
449 __s32 vflip, __s32 hflip) 307 __s32 vflip, __s32 hflip)
450{ 308{
@@ -476,60 +334,52 @@ static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
476 return err; 334 return err;
477} 335}
478 336
479static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) 337static int s5k83a_set_hvflip(struct gspca_dev *gspca_dev)
480{ 338{
481 int err; 339 int err;
482 u8 reg; 340 u8 reg;
483 __s32 hflip;
484 struct sd *sd = (struct sd *) gspca_dev; 341 struct sd *sd = (struct sd *) gspca_dev;
485 struct s5k83a_priv *sens_priv = sd->sensor_priv; 342 int hflip = sd->hflip->val;
486 343 int vflip = sd->vflip->val;
487 sens_priv->settings[VFLIP_IDX] = val;
488
489 s5k83a_get_hflip(gspca_dev, &hflip);
490 344
491 err = s5k83a_get_rotation(sd, &reg); 345 err = s5k83a_get_rotation(sd, &reg);
492 if (err < 0) 346 if (err < 0)
493 return err; 347 return err;
494 if (reg) { 348 if (reg) {
495 val = !val;
496 hflip = !hflip; 349 hflip = !hflip;
350 vflip = !vflip;
497 } 351 }
498 352
499 err = s5k83a_set_flip_real(gspca_dev, val, hflip); 353 err = s5k83a_set_flip_real(gspca_dev, vflip, hflip);
500 return err; 354 return err;
501} 355}
502 356
503static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) 357static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl)
504{
505 struct sd *sd = (struct sd *) gspca_dev;
506 struct s5k83a_priv *sens_priv = sd->sensor_priv;
507
508 *val = sens_priv->settings[HFLIP_IDX];
509 return 0;
510}
511
512static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
513{ 358{
359 struct gspca_dev *gspca_dev =
360 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
514 int err; 361 int err;
515 u8 reg;
516 __s32 vflip;
517 struct sd *sd = (struct sd *) gspca_dev;
518 struct s5k83a_priv *sens_priv = sd->sensor_priv;
519
520 sens_priv->settings[HFLIP_IDX] = val;
521 362
522 s5k83a_get_vflip(gspca_dev, &vflip); 363 if (!gspca_dev->streaming)
523 364 return 0;
524 err = s5k83a_get_rotation(sd, &reg); 365
525 if (err < 0) 366 switch (ctrl->id) {
526 return err; 367 case V4L2_CID_BRIGHTNESS:
527 if (reg) { 368 err = s5k83a_set_brightness(gspca_dev, ctrl->val);
528 val = !val; 369 break;
529 vflip = !vflip; 370 case V4L2_CID_EXPOSURE:
371 err = s5k83a_set_exposure(gspca_dev, ctrl->val);
372 break;
373 case V4L2_CID_GAIN:
374 err = s5k83a_set_gain(gspca_dev, ctrl->val);
375 break;
376 case V4L2_CID_HFLIP:
377 err = s5k83a_set_hvflip(gspca_dev);
378 break;
379 default:
380 return -EINVAL;
530 } 381 }
531 382
532 err = s5k83a_set_flip_real(gspca_dev, vflip, val);
533 return err; 383 return err;
534} 384}
535 385
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.h b/drivers/media/usb/gspca/m5602/m5602_s5k83a.h
index 79952247b534..d61b918228df 100644
--- a/drivers/media/usb/gspca/m5602/m5602_s5k83a.h
+++ b/drivers/media/usb/gspca/m5602/m5602_s5k83a.h
@@ -45,6 +45,7 @@ extern bool dump_sensor;
45 45
46int s5k83a_probe(struct sd *sd); 46int s5k83a_probe(struct sd *sd);
47int s5k83a_init(struct sd *sd); 47int s5k83a_init(struct sd *sd);
48int s5k83a_init_controls(struct sd *sd);
48int s5k83a_start(struct sd *sd); 49int s5k83a_start(struct sd *sd);
49int s5k83a_stop(struct sd *sd); 50int s5k83a_stop(struct sd *sd);
50void s5k83a_disconnect(struct sd *sd); 51void s5k83a_disconnect(struct sd *sd);
@@ -53,6 +54,7 @@ static const struct m5602_sensor s5k83a = {
53 .name = "S5K83A", 54 .name = "S5K83A",
54 .probe = s5k83a_probe, 55 .probe = s5k83a_probe,
55 .init = s5k83a_init, 56 .init = s5k83a_init,
57 .init_controls = s5k83a_init_controls,
56 .start = s5k83a_start, 58 .start = s5k83a_start,
57 .stop = s5k83a_stop, 59 .stop = s5k83a_stop,
58 .disconnect = s5k83a_disconnect, 60 .disconnect = s5k83a_disconnect,
@@ -60,13 +62,6 @@ static const struct m5602_sensor s5k83a = {
60 .i2c_regW = 2, 62 .i2c_regW = 2,
61}; 63};
62 64
63struct s5k83a_priv {
64 /* We use another thread periodically
65 probing the orientation of the camera */
66 struct task_struct *rotation_thread;
67 s32 *settings;
68};
69
70static const unsigned char preinit_s5k83a[][4] = { 65static const unsigned char preinit_s5k83a[][4] = {
71 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00}, 66 {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
72 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00}, 67 {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
diff --git a/drivers/media/usb/gspca/m5602/m5602_sensor.h b/drivers/media/usb/gspca/m5602/m5602_sensor.h
index edff4f1f586f..48341b4d607b 100644
--- a/drivers/media/usb/gspca/m5602/m5602_sensor.h
+++ b/drivers/media/usb/gspca/m5602/m5602_sensor.h
@@ -57,6 +57,9 @@ struct m5602_sensor {
57 /* Performs a initialization sequence */ 57 /* Performs a initialization sequence */
58 int (*init)(struct sd *sd); 58 int (*init)(struct sd *sd);
59 59
60 /* Controls initialization, maybe NULL */
61 int (*init_controls)(struct sd *sd);
62
60 /* Executed when the camera starts to send data */ 63 /* Executed when the camera starts to send data */
61 int (*start)(struct sd *sd); 64 int (*start)(struct sd *sd);
62 65