aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/m5mols/m5mols_controls.c
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2012-04-09 12:51:56 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-14 13:32:14 -0400
commit3c5da0baaada8e8c7176a3e310dfdb4362f74d80 (patch)
tree502bd796f303fcb4a35f0aac2a2be71e81d263ce /drivers/media/video/m5mols/m5mols_controls.c
parent91f4eb0acb99a34e4b7fe9aee65ff9790be523c0 (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.c227
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 */
231int m5mols_set_ctrl(struct v4l2_ctrl *ctrl) 231static 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
259static 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
271static 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
280static 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
322static 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, 369static 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) 373int 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}