2 * Controls for M-5MOLS 8M Pixel camera sensor with ISP
4 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
5 * Author: HeungJun Kim <riverful.kim@samsung.com>
7 * Copyright (C) 2009 Samsung Electronics Co., Ltd.
8 * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
16 #include <linux/i2c.h>
17 #include <linux/delay.h>
18 #include <linux/videodev2.h>
19 #include <media/v4l2-ctrls.h>
22 #include "m5mols_reg.h"
24 static struct m5mols_scenemode m5mols_default_scenemode
[] = {
25 [REG_SCENE_NORMAL
] = {
26 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
27 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
28 REG_AF_NORMAL
, REG_FD_OFF
,
29 REG_MCC_NORMAL
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
30 5, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
32 [REG_SCENE_PORTRAIT
] = {
33 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
34 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 4,
35 REG_AF_NORMAL
, BIT_FD_EN
| BIT_FD_DRAW_FACE_FRAME
,
36 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
37 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
39 [REG_SCENE_LANDSCAPE
] = {
40 REG_AE_ALL
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
41 REG_CHROMA_ON
, 4, REG_EDGE_ON
, 6,
42 REG_AF_NORMAL
, REG_FD_OFF
,
43 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
44 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
46 [REG_SCENE_SPORTS
] = {
47 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
48 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
49 REG_AF_NORMAL
, REG_FD_OFF
,
50 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
51 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
53 [REG_SCENE_PARTY_INDOOR
] = {
54 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
55 REG_CHROMA_ON
, 4, REG_EDGE_ON
, 5,
56 REG_AF_NORMAL
, REG_FD_OFF
,
57 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
58 6, REG_ISO_200
, REG_CAP_NONE
, REG_WDR_OFF
,
60 [REG_SCENE_BEACH_SNOW
] = {
61 REG_AE_CENTER
, REG_AE_INDEX_10_POS
, REG_AWB_AUTO
, 0,
62 REG_CHROMA_ON
, 4, REG_EDGE_ON
, 5,
63 REG_AF_NORMAL
, REG_FD_OFF
,
64 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
65 6, REG_ISO_50
, REG_CAP_NONE
, REG_WDR_OFF
,
67 [REG_SCENE_SUNSET
] = {
68 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_PRESET
,
70 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
71 REG_AF_NORMAL
, REG_FD_OFF
,
72 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
73 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
75 [REG_SCENE_DAWN_DUSK
] = {
76 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_PRESET
,
77 REG_AWB_FLUORESCENT_1
,
78 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
79 REG_AF_NORMAL
, REG_FD_OFF
,
80 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
81 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
84 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
85 REG_CHROMA_ON
, 5, REG_EDGE_ON
, 5,
86 REG_AF_NORMAL
, REG_FD_OFF
,
87 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
88 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
91 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
92 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
93 REG_AF_NORMAL
, REG_FD_OFF
,
94 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
95 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
97 [REG_SCENE_AGAINST_LIGHT
] = {
98 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
99 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
100 REG_AF_NORMAL
, REG_FD_OFF
,
101 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
102 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
105 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
106 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
107 REG_AF_NORMAL
, REG_FD_OFF
,
108 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
109 6, REG_ISO_50
, REG_CAP_NONE
, REG_WDR_OFF
,
112 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
113 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 7,
114 REG_AF_MACRO
, REG_FD_OFF
,
115 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
116 6, REG_ISO_AUTO
, REG_CAP_ANTI_SHAKE
, REG_WDR_ON
,
118 [REG_SCENE_CANDLE
] = {
119 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
120 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
121 REG_AF_NORMAL
, REG_FD_OFF
,
122 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
123 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
128 * m5mols_do_scenemode() - Change current scenemode
129 * @info: M-5MOLS driver data structure
130 * @mode: Desired mode of the scenemode
132 * WARNING: The execution order is important. Do not change the order.
134 int m5mols_do_scenemode(struct m5mols_info
*info
, u8 mode
)
136 struct v4l2_subdev
*sd
= &info
->sd
;
137 struct m5mols_scenemode scenemode
= m5mols_default_scenemode
[mode
];
140 if (mode
> REG_SCENE_CANDLE
)
143 ret
= v4l2_ctrl_s_ctrl(info
->lock_3a
, 0);
145 ret
= m5mols_write(sd
, AE_EV_PRESET_MONITOR
, mode
);
147 ret
= m5mols_write(sd
, AE_EV_PRESET_CAPTURE
, mode
);
149 ret
= m5mols_write(sd
, AE_MODE
, scenemode
.metering
);
151 ret
= m5mols_write(sd
, AE_INDEX
, scenemode
.ev_bias
);
153 ret
= m5mols_write(sd
, AWB_MODE
, scenemode
.wb_mode
);
155 ret
= m5mols_write(sd
, AWB_MANUAL
, scenemode
.wb_preset
);
157 ret
= m5mols_write(sd
, MON_CHROMA_EN
, scenemode
.chroma_en
);
159 ret
= m5mols_write(sd
, MON_CHROMA_LVL
, scenemode
.chroma_lvl
);
161 ret
= m5mols_write(sd
, MON_EDGE_EN
, scenemode
.edge_en
);
163 ret
= m5mols_write(sd
, MON_EDGE_LVL
, scenemode
.edge_lvl
);
164 if (!ret
&& is_available_af(info
))
165 ret
= m5mols_write(sd
, AF_MODE
, scenemode
.af_range
);
166 if (!ret
&& is_available_af(info
))
167 ret
= m5mols_write(sd
, FD_CTL
, scenemode
.fd_mode
);
169 ret
= m5mols_write(sd
, MON_TONE_CTL
, scenemode
.tone
);
171 ret
= m5mols_write(sd
, AE_ISO
, scenemode
.iso
);
173 ret
= m5mols_set_mode(info
, REG_CAPTURE
);
175 ret
= m5mols_write(sd
, CAPP_WDR_EN
, scenemode
.wdr
);
177 ret
= m5mols_write(sd
, CAPP_MCC_MODE
, scenemode
.mcc
);
179 ret
= m5mols_write(sd
, CAPP_LIGHT_CTRL
, scenemode
.light
);
181 ret
= m5mols_write(sd
, CAPP_FLASH_CTRL
, scenemode
.flash
);
183 ret
= m5mols_write(sd
, CAPC_MODE
, scenemode
.capt_mode
);
185 ret
= m5mols_set_mode(info
, REG_MONITOR
);
190 static int m5mols_3a_lock(struct m5mols_info
*info
, struct v4l2_ctrl
*ctrl
)
192 bool af_lock
= ctrl
->val
& V4L2_LOCK_FOCUS
;
195 if ((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_EXPOSURE
) {
196 bool ae_lock
= ctrl
->val
& V4L2_LOCK_EXPOSURE
;
198 ret
= m5mols_write(&info
->sd
, AE_LOCK
, ae_lock
?
199 REG_AE_LOCK
: REG_AE_UNLOCK
);
204 if (((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_WHITE_BALANCE
)
205 && info
->auto_wb
->val
) {
206 bool awb_lock
= ctrl
->val
& V4L2_LOCK_WHITE_BALANCE
;
208 ret
= m5mols_write(&info
->sd
, AWB_LOCK
, awb_lock
?
209 REG_AWB_LOCK
: REG_AWB_UNLOCK
);
214 if (!info
->ver
.af
|| !af_lock
)
217 if ((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_FOCUS
)
218 ret
= m5mols_write(&info
->sd
, AF_EXECUTE
, REG_AF_STOP
);
223 static int m5mols_set_metering_mode(struct m5mols_info
*info
, int mode
)
225 unsigned int metering
;
228 case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED
:
229 metering
= REG_AE_CENTER
;
231 case V4L2_EXPOSURE_METERING_SPOT
:
232 metering
= REG_AE_SPOT
;
235 metering
= REG_AE_ALL
;
239 return m5mols_write(&info
->sd
, AE_MODE
, metering
);
242 static int m5mols_set_exposure(struct m5mols_info
*info
, int exposure
)
244 struct v4l2_subdev
*sd
= &info
->sd
;
247 if (exposure
== V4L2_EXPOSURE_AUTO
) {
248 /* Unlock auto exposure */
249 info
->lock_3a
->val
&= ~V4L2_LOCK_EXPOSURE
;
250 m5mols_3a_lock(info
, info
->lock_3a
);
252 ret
= m5mols_set_metering_mode(info
, info
->metering
->val
);
256 v4l2_dbg(1, m5mols_debug
, sd
,
257 "%s: exposure bias: %#x, metering: %#x\n",
258 __func__
, info
->exposure_bias
->val
,
259 info
->metering
->val
);
261 return m5mols_write(sd
, AE_INDEX
, info
->exposure_bias
->val
);
264 if (exposure
== V4L2_EXPOSURE_MANUAL
) {
265 ret
= m5mols_write(sd
, AE_MODE
, REG_AE_OFF
);
267 ret
= m5mols_write(sd
, AE_MAN_GAIN_MON
,
268 info
->exposure
->val
);
270 ret
= m5mols_write(sd
, AE_MAN_GAIN_CAP
,
271 info
->exposure
->val
);
273 v4l2_dbg(1, m5mols_debug
, sd
, "%s: exposure: %#x\n",
274 __func__
, info
->exposure
->val
);
280 static int m5mols_set_white_balance(struct m5mols_info
*info
, int val
)
282 static const unsigned short wb
[][2] = {
283 { V4L2_WHITE_BALANCE_INCANDESCENT
, REG_AWB_INCANDESCENT
},
284 { V4L2_WHITE_BALANCE_FLUORESCENT
, REG_AWB_FLUORESCENT_1
},
285 { V4L2_WHITE_BALANCE_FLUORESCENT_H
, REG_AWB_FLUORESCENT_2
},
286 { V4L2_WHITE_BALANCE_HORIZON
, REG_AWB_HORIZON
},
287 { V4L2_WHITE_BALANCE_DAYLIGHT
, REG_AWB_DAYLIGHT
},
288 { V4L2_WHITE_BALANCE_FLASH
, REG_AWB_LEDLIGHT
},
289 { V4L2_WHITE_BALANCE_CLOUDY
, REG_AWB_CLOUDY
},
290 { V4L2_WHITE_BALANCE_SHADE
, REG_AWB_SHADE
},
291 { V4L2_WHITE_BALANCE_AUTO
, REG_AWB_AUTO
},
294 struct v4l2_subdev
*sd
= &info
->sd
;
297 for (i
= 0; i
< ARRAY_SIZE(wb
); i
++) {
302 v4l2_dbg(1, m5mols_debug
, sd
,
303 "Setting white balance to: %#x\n", wb
[i
][0]);
305 awb
= wb
[i
][0] == V4L2_WHITE_BALANCE_AUTO
;
306 ret
= m5mols_write(sd
, AWB_MODE
, awb
? REG_AWB_AUTO
:
312 ret
= m5mols_write(sd
, AWB_MANUAL
, wb
[i
][1]);
318 static int m5mols_set_saturation(struct m5mols_info
*info
, int val
)
320 int ret
= m5mols_write(&info
->sd
, MON_CHROMA_LVL
, val
);
324 return m5mols_write(&info
->sd
, MON_CHROMA_EN
, REG_CHROMA_ON
);
327 static int m5mols_set_color_effect(struct m5mols_info
*info
, int val
)
329 unsigned int m_effect
= REG_COLOR_EFFECT_OFF
;
330 unsigned int p_effect
= REG_EFFECT_OFF
;
331 unsigned int cfix_r
= 0, cfix_b
= 0;
332 struct v4l2_subdev
*sd
= &info
->sd
;
336 case V4L2_COLORFX_BW
:
337 m_effect
= REG_COLOR_EFFECT_ON
;
339 case V4L2_COLORFX_NEGATIVE
:
340 p_effect
= REG_EFFECT_NEGA
;
342 case V4L2_COLORFX_EMBOSS
:
343 p_effect
= REG_EFFECT_EMBOSS
;
345 case V4L2_COLORFX_SEPIA
:
346 m_effect
= REG_COLOR_EFFECT_ON
;
347 cfix_r
= REG_CFIXR_SEPIA
;
348 cfix_b
= REG_CFIXB_SEPIA
;
352 ret
= m5mols_write(sd
, PARM_EFFECT
, p_effect
);
354 ret
= m5mols_write(sd
, MON_EFFECT
, m_effect
);
356 if (ret
== 0 && m_effect
== REG_COLOR_EFFECT_ON
) {
357 ret
= m5mols_write(sd
, MON_CFIXR
, cfix_r
);
359 ret
= m5mols_write(sd
, MON_CFIXB
, cfix_b
);
362 v4l2_dbg(1, m5mols_debug
, sd
,
363 "p_effect: %#x, m_effect: %#x, r: %#x, b: %#x (%d)\n",
364 p_effect
, m_effect
, cfix_r
, cfix_b
, ret
);
369 static int m5mols_set_iso(struct m5mols_info
*info
, int auto_iso
)
371 u32 iso
= auto_iso
? 0 : info
->iso
->val
+ 1;
373 return m5mols_write(&info
->sd
, AE_ISO
, iso
);
376 static int m5mols_set_wdr(struct m5mols_info
*info
, int wdr
)
380 ret
= m5mols_write(&info
->sd
, MON_TONE_CTL
, wdr
? 9 : 5);
384 ret
= m5mols_set_mode(info
, REG_CAPTURE
);
388 return m5mols_write(&info
->sd
, CAPP_WDR_EN
, wdr
);
391 static int m5mols_set_stabilization(struct m5mols_info
*info
, int val
)
393 struct v4l2_subdev
*sd
= &info
->sd
;
394 unsigned int evp
= val
? 0xe : 0x0;
397 ret
= m5mols_write(sd
, AE_EV_PRESET_MONITOR
, evp
);
401 return m5mols_write(sd
, AE_EV_PRESET_CAPTURE
, evp
);
404 static int m5mols_g_volatile_ctrl(struct v4l2_ctrl
*ctrl
)
406 struct v4l2_subdev
*sd
= to_sd(ctrl
);
407 struct m5mols_info
*info
= to_m5mols(sd
);
409 u8 status
= REG_ISO_AUTO
;
411 v4l2_dbg(1, m5mols_debug
, sd
, "%s: ctrl: %s (%d)\n",
412 __func__
, ctrl
->name
, info
->isp_ready
);
414 if (!info
->isp_ready
)
418 case V4L2_CID_ISO_SENSITIVITY_AUTO
:
419 ret
= m5mols_read_u8(sd
, AE_ISO
, &status
);
422 if (status
!= REG_ISO_AUTO
)
423 info
->iso
->val
= status
- 1;
426 case V4L2_CID_3A_LOCK
:
429 ret
= m5mols_read_u8(sd
, AE_LOCK
, &status
);
433 info
->lock_3a
->val
|= V4L2_LOCK_EXPOSURE
;
435 ret
= m5mols_read_u8(sd
, AWB_LOCK
, &status
);
439 info
->lock_3a
->val
|= V4L2_LOCK_EXPOSURE
;
441 ret
= m5mols_read_u8(sd
, AF_EXECUTE
, &status
);
443 info
->lock_3a
->val
|= V4L2_LOCK_EXPOSURE
;
450 static int m5mols_s_ctrl(struct v4l2_ctrl
*ctrl
)
452 unsigned int ctrl_mode
= m5mols_get_ctrl_mode(ctrl
);
453 struct v4l2_subdev
*sd
= to_sd(ctrl
);
454 struct m5mols_info
*info
= to_m5mols(sd
);
455 int last_mode
= info
->mode
;
459 * If needed, defer restoring the controls until
460 * the device is fully initialized.
462 if (!info
->isp_ready
) {
467 v4l2_dbg(1, m5mols_debug
, sd
, "%s: %s, val: %d, priv: %p\n",
468 __func__
, ctrl
->name
, ctrl
->val
, ctrl
->priv
);
470 if (ctrl_mode
&& ctrl_mode
!= info
->mode
) {
471 ret
= m5mols_set_mode(info
, ctrl_mode
);
477 case V4L2_CID_3A_LOCK
:
478 ret
= m5mols_3a_lock(info
, ctrl
);
481 case V4L2_CID_ZOOM_ABSOLUTE
:
482 ret
= m5mols_write(sd
, MON_ZOOM
, ctrl
->val
);
485 case V4L2_CID_EXPOSURE_AUTO
:
486 ret
= m5mols_set_exposure(info
, ctrl
->val
);
489 case V4L2_CID_ISO_SENSITIVITY
:
490 ret
= m5mols_set_iso(info
, ctrl
->val
);
493 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
:
494 ret
= m5mols_set_white_balance(info
, ctrl
->val
);
497 case V4L2_CID_SATURATION
:
498 ret
= m5mols_set_saturation(info
, ctrl
->val
);
501 case V4L2_CID_COLORFX
:
502 ret
= m5mols_set_color_effect(info
, ctrl
->val
);
505 case V4L2_CID_WIDE_DYNAMIC_RANGE
:
506 ret
= m5mols_set_wdr(info
, ctrl
->val
);
509 case V4L2_CID_IMAGE_STABILIZATION
:
510 ret
= m5mols_set_stabilization(info
, ctrl
->val
);
513 case V4L2_CID_JPEG_COMPRESSION_QUALITY
:
514 ret
= m5mols_write(sd
, CAPP_JPEG_RATIO
, ctrl
->val
);
518 if (ret
== 0 && info
->mode
!= last_mode
)
519 ret
= m5mols_set_mode(info
, last_mode
);
524 static const struct v4l2_ctrl_ops m5mols_ctrl_ops
= {
525 .g_volatile_ctrl
= m5mols_g_volatile_ctrl
,
526 .s_ctrl
= m5mols_s_ctrl
,
529 /* Supported manual ISO values */
530 static const s64 iso_qmenu
[] = {
531 /* AE_ISO: 0x01...0x07 (ISO: 50...3200) */
532 50000, 100000, 200000, 400000, 800000, 1600000, 3200000
535 /* Supported Exposure Bias values, -2.0EV...+2.0EV */
536 static const s64 ev_bias_qmenu
[] = {
537 /* AE_INDEX: 0x00...0x08 */
538 -2000, -1500, -1000, -500, 0, 500, 1000, 1500, 2000
541 int m5mols_init_controls(struct v4l2_subdev
*sd
)
543 struct m5mols_info
*info
= to_m5mols(sd
);
548 /* Determine the firmware dependent control range and step values */
549 ret
= m5mols_read_u16(sd
, AE_MAX_GAIN_MON
, &exposure_max
);
553 zoom_step
= is_manufacturer(info
, REG_SAMSUNG_OPTICS
) ? 31 : 1;
554 v4l2_ctrl_handler_init(&info
->handle
, 20);
556 info
->auto_wb
= v4l2_ctrl_new_std_menu(&info
->handle
,
557 &m5mols_ctrl_ops
, V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
,
558 9, ~0x3fe, V4L2_WHITE_BALANCE_AUTO
);
560 /* Exposure control cluster */
561 info
->auto_exposure
= v4l2_ctrl_new_std_menu(&info
->handle
,
562 &m5mols_ctrl_ops
, V4L2_CID_EXPOSURE_AUTO
,
563 1, ~0x03, V4L2_EXPOSURE_AUTO
);
565 info
->exposure
= v4l2_ctrl_new_std(&info
->handle
,
566 &m5mols_ctrl_ops
, V4L2_CID_EXPOSURE
,
567 0, exposure_max
, 1, exposure_max
/ 2);
569 info
->exposure_bias
= v4l2_ctrl_new_int_menu(&info
->handle
,
570 &m5mols_ctrl_ops
, V4L2_CID_AUTO_EXPOSURE_BIAS
,
571 ARRAY_SIZE(ev_bias_qmenu
) - 1,
572 ARRAY_SIZE(ev_bias_qmenu
)/2 - 1,
575 info
->metering
= v4l2_ctrl_new_std_menu(&info
->handle
,
576 &m5mols_ctrl_ops
, V4L2_CID_EXPOSURE_METERING
,
577 2, ~0x7, V4L2_EXPOSURE_METERING_AVERAGE
);
579 /* ISO control cluster */
580 info
->auto_iso
= v4l2_ctrl_new_std_menu(&info
->handle
, &m5mols_ctrl_ops
,
581 V4L2_CID_ISO_SENSITIVITY_AUTO
, 1, ~0x03, 1);
583 info
->iso
= v4l2_ctrl_new_int_menu(&info
->handle
, &m5mols_ctrl_ops
,
584 V4L2_CID_ISO_SENSITIVITY
, ARRAY_SIZE(iso_qmenu
) - 1,
585 ARRAY_SIZE(iso_qmenu
)/2 - 1, iso_qmenu
);
587 info
->saturation
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
588 V4L2_CID_SATURATION
, 1, 5, 1, 3);
590 info
->zoom
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
591 V4L2_CID_ZOOM_ABSOLUTE
, 1, 70, zoom_step
, 1);
593 info
->colorfx
= v4l2_ctrl_new_std_menu(&info
->handle
, &m5mols_ctrl_ops
,
594 V4L2_CID_COLORFX
, 4, 0, V4L2_COLORFX_NONE
);
596 info
->wdr
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
597 V4L2_CID_WIDE_DYNAMIC_RANGE
, 0, 1, 1, 0);
599 info
->stabilization
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
600 V4L2_CID_IMAGE_STABILIZATION
, 0, 1, 1, 0);
602 info
->jpeg_quality
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
603 V4L2_CID_JPEG_COMPRESSION_QUALITY
, 1, 100, 1, 80);
605 info
->lock_3a
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
606 V4L2_CID_3A_LOCK
, 0, 0x7, 0, 0);
608 if (info
->handle
.error
) {
609 int ret
= info
->handle
.error
;
610 v4l2_err(sd
, "Failed to initialize controls: %d\n", ret
);
611 v4l2_ctrl_handler_free(&info
->handle
);
615 v4l2_ctrl_auto_cluster(4, &info
->auto_exposure
, 1, false);
616 info
->auto_iso
->flags
|= V4L2_CTRL_FLAG_VOLATILE
|
617 V4L2_CTRL_FLAG_UPDATE
;
618 v4l2_ctrl_auto_cluster(2, &info
->auto_iso
, 0, false);
620 info
->lock_3a
->flags
|= V4L2_CTRL_FLAG_VOLATILE
;
622 m5mols_set_ctrl_mode(info
->auto_exposure
, REG_PARAMETER
);
623 m5mols_set_ctrl_mode(info
->auto_wb
, REG_PARAMETER
);
624 m5mols_set_ctrl_mode(info
->colorfx
, REG_MONITOR
);
626 sd
->ctrl_handler
= &info
->handle
;