diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2012-04-09 12:51:56 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-14 13:32:14 -0400 |
commit | 3c5da0baaada8e8c7176a3e310dfdb4362f74d80 (patch) | |
tree | 502bd796f303fcb4a35f0aac2a2be71e81d263ce /drivers/media/video/m5mols/m5mols_controls.c | |
parent | 91f4eb0acb99a34e4b7fe9aee65ff9790be523c0 (diff) |
[media] m5mols: Refactored controls handling
This patch is a prerequisite for the new controls addition. It consolidates
the control handling code, which is moved to m5mols_controls.c and
staticized. The controls initialization is reordered to better reflect
the control clusters and make the diffs smaller when new controls are added.
To make the code easier to follow when more controls is added use separate
set function for each control.
Rewrite the image effect registers handling.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/m5mols/m5mols_controls.c')
-rw-r--r-- | drivers/media/video/m5mols/m5mols_controls.c | 227 |
1 files changed, 174 insertions, 53 deletions
diff --git a/drivers/media/video/m5mols/m5mols_controls.c b/drivers/media/video/m5mols/m5mols_controls.c index d135d20d09c..464ec0cdfb7 100644 --- a/drivers/media/video/m5mols/m5mols_controls.c +++ b/drivers/media/video/m5mols/m5mols_controls.c | |||
@@ -169,7 +169,7 @@ int m5mols_do_scenemode(struct m5mols_info *info, u8 mode) | |||
169 | if (!ret) | 169 | if (!ret) |
170 | ret = m5mols_write(sd, AE_ISO, scenemode.iso); | 170 | ret = m5mols_write(sd, AE_ISO, scenemode.iso); |
171 | if (!ret) | 171 | if (!ret) |
172 | ret = m5mols_mode(info, REG_CAPTURE); | 172 | ret = m5mols_set_mode(info, REG_CAPTURE); |
173 | if (!ret) | 173 | if (!ret) |
174 | ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr); | 174 | ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr); |
175 | if (!ret) | 175 | if (!ret) |
@@ -181,7 +181,7 @@ int m5mols_do_scenemode(struct m5mols_info *info, u8 mode) | |||
181 | if (!ret) | 181 | if (!ret) |
182 | ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode); | 182 | ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode); |
183 | if (!ret) | 183 | if (!ret) |
184 | ret = m5mols_mode(info, REG_MONITOR); | 184 | ret = m5mols_set_mode(info, REG_MONITOR); |
185 | 185 | ||
186 | return ret; | 186 | return ret; |
187 | } | 187 | } |
@@ -227,73 +227,194 @@ int m5mols_lock_3a(struct m5mols_info *info, bool lock) | |||
227 | return ret; | 227 | return ret; |
228 | } | 228 | } |
229 | 229 | ||
230 | /* m5mols_set_ctrl() - The main s_ctrl function called by m5mols_set_ctrl() */ | 230 | /* Set exposure/auto exposure cluster */ |
231 | int m5mols_set_ctrl(struct v4l2_ctrl *ctrl) | 231 | static int m5mols_set_exposure(struct m5mols_info *info, int exposure) |
232 | { | ||
233 | struct v4l2_subdev *sd = &info->sd; | ||
234 | int ret; | ||
235 | |||
236 | ret = m5mols_lock_ae(info, exposure != V4L2_EXPOSURE_AUTO); | ||
237 | if (ret < 0) | ||
238 | return ret; | ||
239 | |||
240 | if (exposure == V4L2_EXPOSURE_AUTO) { | ||
241 | ret = m5mols_write(sd, AE_MODE, REG_AE_ALL); | ||
242 | if (ret < 0) | ||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | if (exposure == V4L2_EXPOSURE_MANUAL) { | ||
247 | ret = m5mols_write(sd, AE_MODE, REG_AE_OFF); | ||
248 | if (ret == 0) | ||
249 | ret = m5mols_write(sd, AE_MAN_GAIN_MON, | ||
250 | info->exposure->val); | ||
251 | if (ret == 0) | ||
252 | ret = m5mols_write(sd, AE_MAN_GAIN_CAP, | ||
253 | info->exposure->val); | ||
254 | } | ||
255 | |||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | static int m5mols_set_white_balance(struct m5mols_info *info, int awb) | ||
260 | { | ||
261 | int ret; | ||
262 | |||
263 | ret = m5mols_lock_awb(info, !awb); | ||
264 | if (ret < 0) | ||
265 | return ret; | ||
266 | |||
267 | return m5mols_write(&info->sd, AWB_MODE, awb ? REG_AWB_AUTO : | ||
268 | REG_AWB_PRESET); | ||
269 | } | ||
270 | |||
271 | static int m5mols_set_saturation(struct m5mols_info *info, int val) | ||
272 | { | ||
273 | int ret = m5mols_write(&info->sd, MON_CHROMA_LVL, val); | ||
274 | if (ret < 0) | ||
275 | return ret; | ||
276 | |||
277 | return m5mols_write(&info->sd, MON_CHROMA_EN, REG_CHROMA_ON); | ||
278 | } | ||
279 | |||
280 | static int m5mols_set_color_effect(struct m5mols_info *info, int val) | ||
281 | { | ||
282 | unsigned int m_effect = REG_COLOR_EFFECT_OFF; | ||
283 | unsigned int p_effect = REG_EFFECT_OFF; | ||
284 | unsigned int cfix_r = 0, cfix_b = 0; | ||
285 | struct v4l2_subdev *sd = &info->sd; | ||
286 | int ret = 0; | ||
287 | |||
288 | switch (val) { | ||
289 | case V4L2_COLORFX_BW: | ||
290 | m_effect = REG_COLOR_EFFECT_ON; | ||
291 | break; | ||
292 | case V4L2_COLORFX_NEGATIVE: | ||
293 | p_effect = REG_EFFECT_NEGA; | ||
294 | break; | ||
295 | case V4L2_COLORFX_EMBOSS: | ||
296 | p_effect = REG_EFFECT_EMBOSS; | ||
297 | break; | ||
298 | case V4L2_COLORFX_SEPIA: | ||
299 | m_effect = REG_COLOR_EFFECT_ON; | ||
300 | cfix_r = REG_CFIXR_SEPIA; | ||
301 | cfix_b = REG_CFIXB_SEPIA; | ||
302 | break; | ||
303 | } | ||
304 | |||
305 | ret = m5mols_write(sd, PARM_EFFECT, p_effect); | ||
306 | if (!ret) | ||
307 | ret = m5mols_write(sd, MON_EFFECT, m_effect); | ||
308 | |||
309 | if (ret == 0 && m_effect == REG_COLOR_EFFECT_ON) { | ||
310 | ret = m5mols_write(sd, MON_CFIXR, cfix_r); | ||
311 | if (!ret) | ||
312 | ret = m5mols_write(sd, MON_CFIXB, cfix_b); | ||
313 | } | ||
314 | |||
315 | v4l2_dbg(1, m5mols_debug, sd, | ||
316 | "p_effect: %#x, m_effect: %#x, r: %#x, b: %#x (%d)\n", | ||
317 | p_effect, m_effect, cfix_r, cfix_b, ret); | ||
318 | |||
319 | return ret; | ||
320 | } | ||
321 | |||
322 | static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl) | ||
232 | { | 323 | { |
233 | struct v4l2_subdev *sd = to_sd(ctrl); | 324 | struct v4l2_subdev *sd = to_sd(ctrl); |
234 | struct m5mols_info *info = to_m5mols(sd); | 325 | struct m5mols_info *info = to_m5mols(sd); |
326 | int ispstate = info->mode; | ||
235 | int ret; | 327 | int ret; |
236 | 328 | ||
329 | /* | ||
330 | * If needed, defer restoring the controls until | ||
331 | * the device is fully initialized. | ||
332 | */ | ||
333 | if (!info->isp_ready) { | ||
334 | info->ctrl_sync = 0; | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | ret = m5mols_mode(info, REG_PARAMETER); | ||
339 | if (ret < 0) | ||
340 | return ret; | ||
341 | |||
237 | switch (ctrl->id) { | 342 | switch (ctrl->id) { |
238 | case V4L2_CID_ZOOM_ABSOLUTE: | 343 | case V4L2_CID_ZOOM_ABSOLUTE: |
239 | return m5mols_write(sd, MON_ZOOM, ctrl->val); | 344 | ret = m5mols_write(sd, MON_ZOOM, ctrl->val); |
345 | break; | ||
240 | 346 | ||
241 | case V4L2_CID_EXPOSURE_AUTO: | 347 | case V4L2_CID_EXPOSURE_AUTO: |
242 | ret = m5mols_lock_ae(info, | 348 | ret = m5mols_set_exposure(info, ctrl->val); |
243 | ctrl->val == V4L2_EXPOSURE_AUTO ? false : true); | 349 | break; |
244 | if (!ret && ctrl->val == V4L2_EXPOSURE_AUTO) | ||
245 | ret = m5mols_write(sd, AE_MODE, REG_AE_ALL); | ||
246 | if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL) { | ||
247 | int val = info->exposure->val; | ||
248 | ret = m5mols_write(sd, AE_MODE, REG_AE_OFF); | ||
249 | if (!ret) | ||
250 | ret = m5mols_write(sd, AE_MAN_GAIN_MON, val); | ||
251 | if (!ret) | ||
252 | ret = m5mols_write(sd, AE_MAN_GAIN_CAP, val); | ||
253 | } | ||
254 | return ret; | ||
255 | 350 | ||
256 | case V4L2_CID_AUTO_WHITE_BALANCE: | 351 | case V4L2_CID_AUTO_WHITE_BALANCE: |
257 | ret = m5mols_lock_awb(info, ctrl->val ? false : true); | 352 | ret = m5mols_set_white_balance(info, ctrl->val); |
258 | if (!ret) | 353 | break; |
259 | ret = m5mols_write(sd, AWB_MODE, ctrl->val ? | ||
260 | REG_AWB_AUTO : REG_AWB_PRESET); | ||
261 | return ret; | ||
262 | 354 | ||
263 | case V4L2_CID_SATURATION: | 355 | case V4L2_CID_SATURATION: |
264 | ret = m5mols_write(sd, MON_CHROMA_LVL, ctrl->val); | 356 | ret = m5mols_set_saturation(info, ctrl->val); |
265 | if (!ret) | 357 | break; |
266 | ret = m5mols_write(sd, MON_CHROMA_EN, REG_CHROMA_ON); | ||
267 | return ret; | ||
268 | 358 | ||
269 | case V4L2_CID_COLORFX: | 359 | case V4L2_CID_COLORFX: |
270 | /* | 360 | ret = m5mols_set_color_effect(info, ctrl->val); |
271 | * This control uses two kinds of registers: normal & color. | 361 | break; |
272 | * The normal effect belongs to category 1, while the color | 362 | } |
273 | * one belongs to category 2. | 363 | if (ret < 0) |
274 | * | 364 | return ret; |
275 | * The normal effect uses one register: CAT1_EFFECT. | 365 | |
276 | * The color effect uses three registers: | 366 | return m5mols_mode(info, ispstate); |
277 | * CAT2_COLOR_EFFECT, CAT2_CFIXR, CAT2_CFIXB. | 367 | } |
278 | */ | 368 | |
279 | ret = m5mols_write(sd, PARM_EFFECT, | 369 | static const struct v4l2_ctrl_ops m5mols_ctrl_ops = { |
280 | ctrl->val == V4L2_COLORFX_NEGATIVE ? REG_EFFECT_NEGA : | 370 | .s_ctrl = m5mols_s_ctrl, |
281 | ctrl->val == V4L2_COLORFX_EMBOSS ? REG_EFFECT_EMBOSS : | 371 | }; |
282 | REG_EFFECT_OFF); | 372 | |
283 | if (!ret) | 373 | int m5mols_init_controls(struct v4l2_subdev *sd) |
284 | ret = m5mols_write(sd, MON_EFFECT, | 374 | { |
285 | ctrl->val == V4L2_COLORFX_SEPIA ? | 375 | struct m5mols_info *info = to_m5mols(sd); |
286 | REG_COLOR_EFFECT_ON : REG_COLOR_EFFECT_OFF); | 376 | u16 exposure_max; |
287 | if (!ret) | 377 | u16 zoom_step; |
288 | ret = m5mols_write(sd, MON_CFIXR, | 378 | int ret; |
289 | ctrl->val == V4L2_COLORFX_SEPIA ? | 379 | |
290 | REG_CFIXR_SEPIA : 0); | 380 | /* Determine the firmware dependant control range and step values */ |
291 | if (!ret) | 381 | ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &exposure_max); |
292 | ret = m5mols_write(sd, MON_CFIXB, | 382 | if (ret < 0) |
293 | ctrl->val == V4L2_COLORFX_SEPIA ? | 383 | return ret; |
294 | REG_CFIXB_SEPIA : 0); | 384 | |
385 | zoom_step = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1; | ||
386 | |||
387 | v4l2_ctrl_handler_init(&info->handle, 6); | ||
388 | |||
389 | info->auto_wb = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops, | ||
390 | V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1); | ||
391 | |||
392 | info->auto_exposure = v4l2_ctrl_new_std_menu(&info->handle, | ||
393 | &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, | ||
394 | 1, ~0x03, V4L2_EXPOSURE_AUTO); | ||
395 | |||
396 | info->exposure = v4l2_ctrl_new_std(&info->handle, | ||
397 | &m5mols_ctrl_ops, V4L2_CID_EXPOSURE, | ||
398 | 0, exposure_max, 1, exposure_max / 2); | ||
399 | |||
400 | info->saturation = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops, | ||
401 | V4L2_CID_SATURATION, 1, 5, 1, 3); | ||
402 | |||
403 | info->zoom = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops, | ||
404 | V4L2_CID_ZOOM_ABSOLUTE, 1, 70, zoom_step, 1); | ||
405 | |||
406 | info->colorfx = v4l2_ctrl_new_std_menu(&info->handle, &m5mols_ctrl_ops, | ||
407 | V4L2_CID_COLORFX, 4, 0, V4L2_COLORFX_NONE); | ||
408 | |||
409 | if (info->handle.error) { | ||
410 | int ret = info->handle.error; | ||
411 | v4l2_err(sd, "Failed to initialize controls: %d\n", ret); | ||
412 | v4l2_ctrl_handler_free(&info->handle); | ||
295 | return ret; | 413 | return ret; |
296 | } | 414 | } |
297 | 415 | ||
298 | return -EINVAL; | 416 | v4l2_ctrl_auto_cluster(2, &info->auto_exposure, 1, false); |
417 | sd->ctrl_handler = &info->handle; | ||
418 | |||
419 | return 0; | ||
299 | } | 420 | } |