diff options
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_bridge.h | 27 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_core.c | 16 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_mt9m111.c | 388 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_mt9m111.h | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_ov7660.c | 300 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_ov7660.h | 3 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_ov9650.c | 445 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_ov9650.h | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_po1030.c | 452 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_po1030.h | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_s5k4aa.c | 338 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_s5k4aa.h | 2 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_s5k83a.c | 290 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_s5k83a.h | 9 | ||||
-rw-r--r-- | drivers/media/usb/gspca/m5602/m5602_sensor.h | 3 |
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 | ||
151 | int m5602_read_bridge( | 168 | int 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 | ||
255 | static 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 | |||
255 | static int m5602_start_transfer(struct gspca_dev *gspca_dev) | 265 | static 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 */ |
340 | static struct sd_desc sd_desc = { | 350 | static 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 | ||
23 | static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | 23 | static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl); |
24 | static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | 24 | static void mt9m111_dump_registers(struct sd *sd); |
25 | static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
26 | static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
27 | static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
28 | static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
29 | static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, | ||
30 | __s32 val); | ||
31 | static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev, | ||
32 | __s32 *val); | ||
33 | static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
34 | static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
35 | static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
36 | static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
37 | static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
38 | static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
39 | 25 | ||
40 | static struct v4l2_pix_format mt9m111_modes[] = { | 26 | static 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 | ||
53 | static const struct ctrl mt9m111_ctrls[] = { | 39 | static 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 | ||
158 | static void mt9m111_dump_registers(struct sd *sd); | 43 | static 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 | ||
160 | int mt9m111_probe(struct sd *sd) | 55 | int 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 | ||
202 | sensor_found: | 96 | sensor_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: | |||
220 | int mt9m111_init(struct sd *sd) | 103 | int 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, | 129 | int 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 | ||
270 | int mt9m111_start(struct sd *sd) | 167 | int 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) | |||
361 | void mt9m111_disconnect(struct sd *sd) | 242 | void mt9m111_disconnect(struct sd *sd) |
362 | { | 243 | { |
363 | sd->sensor = NULL; | 244 | sd->sensor = NULL; |
364 | kfree(sd->sensor_priv); | ||
365 | } | ||
366 | |||
367 | static 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 | |||
378 | static 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 | |||
407 | static 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 | ||
418 | static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | 247 | static 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 | ||
447 | static 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 | |||
458 | static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev, | 281 | static 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 | ||
479 | static 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 | |||
489 | static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) | 300 | static 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 | ||
551 | static 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 | |||
561 | static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) | 357 | static 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 | ||
577 | static 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 | |||
587 | static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) | 371 | static 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 | ||
603 | static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) | 385 | static 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 | ||
613 | static void mt9m111_dump_registers(struct sd *sd) | 421 | static 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 | ||
111 | int mt9m111_probe(struct sd *sd); | 111 | int mt9m111_probe(struct sd *sd); |
112 | int mt9m111_init(struct sd *sd); | 112 | int mt9m111_init(struct sd *sd); |
113 | int mt9m111_init_controls(struct sd *sd); | ||
113 | int mt9m111_start(struct sd *sd); | 114 | int mt9m111_start(struct sd *sd); |
114 | void mt9m111_disconnect(struct sd *sd); | 115 | void 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 | ||
23 | static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | 23 | static int ov7660_s_ctrl(struct v4l2_ctrl *ctrl); |
24 | static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val); | 24 | static void ov7660_dump_registers(struct sd *sd); |
25 | static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev, | ||
26 | __s32 *val); | ||
27 | static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev, | ||
28 | __s32 val); | ||
29 | static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
30 | static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
31 | static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
32 | static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
33 | static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
34 | static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
35 | static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
36 | static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
37 | |||
38 | static 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 | ||
129 | static struct v4l2_pix_format ov7660_modes[] = { | 26 | static 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 | ||
143 | static void ov7660_dump_registers(struct sd *sd); | 40 | static const struct v4l2_ctrl_ops ov7660_ctrl_ops = { |
41 | .s_ctrl = ov7660_s_ctrl, | ||
42 | }; | ||
144 | 43 | ||
145 | int ov7660_probe(struct sd *sd) | 44 | int 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 | ||
193 | sensor_found: | 90 | sensor_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: | |||
211 | int ov7660_init(struct sd *sd) | 97 | int 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, | 122 | int 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 | ||
263 | int ov7660_start(struct sd *sd) | 155 | int 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 | |||
281 | static 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 | ||
291 | static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val) | 172 | static 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 | |||
307 | static 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 | |||
317 | static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev, | 184 | static 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 | ||
338 | static 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 | |||
348 | static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) | 203 | static 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 | ||
367 | static 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 | |||
377 | static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, | 220 | static 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 | ||
397 | static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | 239 | static 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 | |||
407 | static 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 | ||
426 | static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) | 254 | static 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 | |||
437 | static 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 | ||
91 | int ov7660_probe(struct sd *sd); | 91 | int ov7660_probe(struct sd *sd); |
92 | int ov7660_init(struct sd *sd); | 92 | int ov7660_init(struct sd *sd); |
93 | int ov7660_init(struct sd *sd); | ||
94 | int ov7660_init_controls(struct sd *sd); | ||
93 | int ov7660_start(struct sd *sd); | 95 | int ov7660_start(struct sd *sd); |
94 | int ov7660_stop(struct sd *sd); | 96 | int ov7660_stop(struct sd *sd); |
95 | void ov7660_disconnect(struct sd *sd); | 97 | void 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 | ||
23 | static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | 23 | static int ov9650_s_ctrl(struct v4l2_ctrl *ctrl); |
24 | static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | 24 | static void ov9650_dump_registers(struct sd *sd); |
25 | static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
26 | static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
27 | static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
28 | static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
29 | static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
30 | static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
31 | static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
32 | static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
33 | static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
34 | static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
35 | static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, | ||
36 | __s32 *val); | ||
37 | static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, | ||
38 | __s32 val); | ||
39 | static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
40 | static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
41 | static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
42 | static 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 | ||
116 | static 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 | |||
250 | static struct v4l2_pix_format ov9650_modes[] = { | 98 | static 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 | ||
294 | static void ov9650_dump_registers(struct sd *sd); | 142 | static const struct v4l2_ctrl_ops ov9650_ctrl_ops = { |
143 | .s_ctrl = ov9650_s_ctrl, | ||
144 | }; | ||
295 | 145 | ||
296 | int ov9650_probe(struct sd *sd) | 146 | int 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 | ||
340 | sensor_found: | 189 | sensor_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, | 216 | int 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 | ||
417 | int ov9650_start(struct sd *sd) | 261 | int 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 | |||
559 | static 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 | ||
569 | static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | 401 | static 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 | ||
599 | static 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 | |||
609 | static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val) | 429 | static 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 | ||
640 | static 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 | |||
650 | static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) | 457 | static 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 | ||
666 | static 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 | |||
677 | static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) | 470 | static 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 | ||
693 | static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | 483 | static 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 | |||
703 | static 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 | |||
726 | static 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 | |||
737 | static 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 | ||
762 | static 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 | |||
772 | static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, | 508 | static 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 | ||
792 | static 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 | |||
802 | static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, | 527 | static 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 | ||
823 | static 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 | |||
833 | static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) | 546 | static 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 | ||
563 | static 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 | |||
852 | static void ov9650_dump_registers(struct sd *sd) | 605 | static 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 | ||
140 | int ov9650_probe(struct sd *sd); | 140 | int ov9650_probe(struct sd *sd); |
141 | int ov9650_init(struct sd *sd); | 141 | int ov9650_init(struct sd *sd); |
142 | int ov9650_init_controls(struct sd *sd); | ||
142 | int ov9650_start(struct sd *sd); | 143 | int ov9650_start(struct sd *sd); |
143 | int ov9650_stop(struct sd *sd); | 144 | int ov9650_stop(struct sd *sd); |
144 | void ov9650_disconnect(struct sd *sd); | 145 | void 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 | ||
23 | static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | 23 | static int po1030_s_ctrl(struct v4l2_ctrl *ctrl); |
24 | static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | 24 | static void po1030_dump_registers(struct sd *sd); |
25 | static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
26 | static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
27 | static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
28 | static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
29 | static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
30 | static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
31 | static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val); | ||
32 | static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val); | ||
33 | static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
34 | static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
35 | static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
36 | static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
37 | static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, | ||
38 | __s32 val); | ||
39 | static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev, | ||
40 | __s32 *val); | ||
41 | static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev, | ||
42 | __s32 val); | ||
43 | static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev, | ||
44 | __s32 *val); | ||
45 | 25 | ||
46 | static struct v4l2_pix_format po1030_modes[] = { | 26 | static 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 | ||
59 | static const struct ctrl po1030_ctrls[] = { | 39 | static 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 | ||
193 | static void po1030_dump_registers(struct sd *sd); | 43 | static 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 | ||
195 | int po1030_probe(struct sd *sd) | 55 | int 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 | ||
231 | sensor_found: | 90 | sensor_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 | ||
249 | int po1030_init(struct sd *sd) | 97 | int 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, | 132 | int 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 | ||
324 | int po1030_start(struct sd *sd) | 175 | int 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 | ||
451 | static 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 | |||
461 | static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | 302 | static 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 | ||
489 | static 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 | |||
499 | static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) | 328 | static 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 | ||
515 | static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | 341 | static 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 | |||
526 | static 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 | |||
548 | static 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 | |||
559 | static 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 | ||
581 | static 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 | |||
591 | static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) | 361 | static 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 | ||
607 | static 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 | |||
618 | static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) | 374 | static 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 | ||
635 | static 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 | |||
646 | static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val) | 388 | static 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 | ||
666 | static 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 | |||
678 | static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev, | 406 | static 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 | ||
698 | static 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 | |||
709 | static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev, | 423 | static 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, | |||
727 | void po1030_disconnect(struct sd *sd) | 440 | void po1030_disconnect(struct sd *sd) |
728 | { | 441 | { |
729 | sd->sensor = NULL; | 442 | sd->sensor = NULL; |
730 | kfree(sd->sensor_priv); | 443 | } |
444 | |||
445 | static 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 | ||
733 | static void po1030_dump_registers(struct sd *sd) | 487 | static 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 | ||
152 | int po1030_probe(struct sd *sd); | 152 | int po1030_probe(struct sd *sd); |
153 | int po1030_init(struct sd *sd); | 153 | int po1030_init(struct sd *sd); |
154 | int po1030_init_controls(struct sd *sd); | ||
154 | int po1030_start(struct sd *sd); | 155 | int po1030_start(struct sd *sd); |
155 | void po1030_disconnect(struct sd *sd); | 156 | void 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 | ||
23 | static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | 23 | static int s5k4aa_s_ctrl(struct v4l2_ctrl *ctrl); |
24 | static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | 24 | static void s5k4aa_dump_registers(struct sd *sd); |
25 | static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | 25 | |
26 | static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | 26 | static const struct v4l2_ctrl_ops s5k4aa_ctrl_ops = { |
27 | static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | 27 | .s_ctrl = s5k4aa_s_ctrl, |
28 | static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | 28 | }; |
29 | static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
30 | static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
31 | static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val); | ||
32 | static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val); | ||
33 | static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
34 | static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val); | ||
35 | 29 | ||
36 | static | 30 | static |
37 | const | 31 | const |
@@ -147,104 +141,11 @@ static struct v4l2_pix_format s5k4aa_modes[] = { | |||
147 | } | 141 | } |
148 | }; | 142 | }; |
149 | 143 | ||
150 | static 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 | |||
240 | static void s5k4aa_dump_registers(struct sd *sd); | ||
241 | |||
242 | int s5k4aa_probe(struct sd *sd) | 144 | int 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 | ||
305 | sensor_found: | 206 | sensor_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 | ||
431 | int s5k4aa_init(struct sd *sd) | 292 | int 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 | ||
469 | static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) | 330 | int 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) | |||
480 | static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | 364 | static 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 | ||
502 | static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) | 384 | static 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 | |||
513 | static 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 | |||
550 | static 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 | |||
561 | static 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 | |||
598 | static 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 | ||
608 | static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) | 436 | static 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 | ||
628 | static 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 | |||
638 | static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val) | 453 | static 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 | ||
656 | static 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 | |||
666 | static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val) | 468 | static 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 | ||
483 | static 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 | |||
684 | void s5k4aa_disconnect(struct sd *sd) | 515 | void s5k4aa_disconnect(struct sd *sd) |
685 | { | 516 | { |
686 | sd->sensor = NULL; | 517 | sd->sensor = NULL; |
687 | kfree(sd->sensor_priv); | ||
688 | } | 518 | } |
689 | 519 | ||
690 | static void s5k4aa_dump_registers(struct sd *sd) | 520 | static 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 | ||
70 | int s5k4aa_probe(struct sd *sd); | 70 | int s5k4aa_probe(struct sd *sd); |
71 | int s5k4aa_init(struct sd *sd); | 71 | int s5k4aa_init(struct sd *sd); |
72 | int s5k4aa_init_controls(struct sd *sd); | ||
72 | int s5k4aa_start(struct sd *sd); | 73 | int s5k4aa_start(struct sd *sd); |
73 | void s5k4aa_disconnect(struct sd *sd); | 74 | void 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 | ||
24 | static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val); | 24 | static int s5k83a_s_ctrl(struct v4l2_ctrl *ctrl); |
25 | static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | 25 | |
26 | static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val); | 26 | static const struct v4l2_ctrl_ops s5k83a_ctrl_ops = { |
27 | static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); | 27 | .s_ctrl = s5k83a_s_ctrl, |
28 | static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | 28 | }; |
29 | static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
30 | static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
31 | static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | ||
32 | static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
33 | static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | ||
34 | 29 | ||
35 | static struct v4l2_pix_format s5k83a_modes[] = { | 30 | static 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 | ||
49 | static 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 | |||
126 | static void s5k83a_dump_registers(struct sd *sd); | 44 | static void s5k83a_dump_registers(struct sd *sd); |
127 | static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data); | 45 | static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data); |
128 | static int s5k83a_set_led_indication(struct sd *sd, u8 val); | 46 | static 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 | ||
132 | int s5k83a_probe(struct sd *sd) | 50 | int 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 | ||
175 | sensor_found: | 92 | sensor_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 | ||
203 | int s5k83a_init(struct sd *sd) | 102 | int 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, | 140 | int 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 | ||
263 | static int rotation_thread_function(void *data) | 172 | static 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 | ||
306 | int s5k83a_start(struct sd *sd) | 214 | int 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 | ||
334 | int s5k83a_stop(struct sd *sd) | 241 | int 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 | ||
344 | void s5k83a_disconnect(struct sd *sd) | 249 | void 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 | |||
355 | static 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 | ||
364 | static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val) | 256 | static 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 | ||
394 | static 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 | |||
403 | static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val) | 283 | static 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 | ||
416 | static 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 | |||
425 | static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | 294 | static 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 | ||
439 | static 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 | |||
448 | static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev, | 306 | static 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 | ||
479 | static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | 337 | static 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, ®); | 345 | err = s5k83a_get_rotation(sd, ®); |
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 | ||
503 | static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) | 357 | static 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 | |||
512 | static 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, ®); | 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 | ||
46 | int s5k83a_probe(struct sd *sd); | 46 | int s5k83a_probe(struct sd *sd); |
47 | int s5k83a_init(struct sd *sd); | 47 | int s5k83a_init(struct sd *sd); |
48 | int s5k83a_init_controls(struct sd *sd); | ||
48 | int s5k83a_start(struct sd *sd); | 49 | int s5k83a_start(struct sd *sd); |
49 | int s5k83a_stop(struct sd *sd); | 50 | int s5k83a_stop(struct sd *sd); |
50 | void s5k83a_disconnect(struct sd *sd); | 51 | void 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 | ||
63 | struct 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 | |||
70 | static const unsigned char preinit_s5k83a[][4] = { | 65 | static 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 | ||