1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Controls for M-5MOLS 8M Pixel camera sensor with ISP
5 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
6 * Author: HeungJun Kim <riverful.kim@samsung.com>
8 * Copyright (C) 2009 Samsung Electronics Co., Ltd.
9 * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
12 #include <linux/i2c.h>
13 #include <linux/delay.h>
14 #include <linux/videodev2.h>
15 #include <media/v4l2-ctrls.h>
18 #include "m5mols_reg.h"
20 static struct m5mols_scenemode m5mols_default_scenemode
[] = {
21 [REG_SCENE_NORMAL
] = {
22 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
23 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
24 REG_AF_NORMAL
, REG_FD_OFF
,
25 REG_MCC_NORMAL
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
26 5, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
28 [REG_SCENE_PORTRAIT
] = {
29 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
30 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 4,
31 REG_AF_NORMAL
, BIT_FD_EN
| BIT_FD_DRAW_FACE_FRAME
,
32 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
33 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
35 [REG_SCENE_LANDSCAPE
] = {
36 REG_AE_ALL
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
37 REG_CHROMA_ON
, 4, REG_EDGE_ON
, 6,
38 REG_AF_NORMAL
, REG_FD_OFF
,
39 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
40 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
42 [REG_SCENE_SPORTS
] = {
43 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
44 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
45 REG_AF_NORMAL
, REG_FD_OFF
,
46 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
47 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
49 [REG_SCENE_PARTY_INDOOR
] = {
50 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
51 REG_CHROMA_ON
, 4, REG_EDGE_ON
, 5,
52 REG_AF_NORMAL
, REG_FD_OFF
,
53 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
54 6, REG_ISO_200
, REG_CAP_NONE
, REG_WDR_OFF
,
56 [REG_SCENE_BEACH_SNOW
] = {
57 REG_AE_CENTER
, REG_AE_INDEX_10_POS
, REG_AWB_AUTO
, 0,
58 REG_CHROMA_ON
, 4, REG_EDGE_ON
, 5,
59 REG_AF_NORMAL
, REG_FD_OFF
,
60 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
61 6, REG_ISO_50
, REG_CAP_NONE
, REG_WDR_OFF
,
63 [REG_SCENE_SUNSET
] = {
64 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_PRESET
,
66 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
67 REG_AF_NORMAL
, REG_FD_OFF
,
68 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
69 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
71 [REG_SCENE_DAWN_DUSK
] = {
72 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_PRESET
,
73 REG_AWB_FLUORESCENT_1
,
74 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
75 REG_AF_NORMAL
, REG_FD_OFF
,
76 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
77 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
80 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
81 REG_CHROMA_ON
, 5, REG_EDGE_ON
, 5,
82 REG_AF_NORMAL
, REG_FD_OFF
,
83 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
84 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
87 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
88 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
89 REG_AF_NORMAL
, REG_FD_OFF
,
90 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
91 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
93 [REG_SCENE_AGAINST_LIGHT
] = {
94 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
95 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
96 REG_AF_NORMAL
, REG_FD_OFF
,
97 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
98 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
101 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
102 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
103 REG_AF_NORMAL
, REG_FD_OFF
,
104 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
105 6, REG_ISO_50
, REG_CAP_NONE
, REG_WDR_OFF
,
108 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
109 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 7,
110 REG_AF_MACRO
, REG_FD_OFF
,
111 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
112 6, REG_ISO_AUTO
, REG_CAP_ANTI_SHAKE
, REG_WDR_ON
,
114 [REG_SCENE_CANDLE
] = {
115 REG_AE_CENTER
, REG_AE_INDEX_00
, REG_AWB_AUTO
, 0,
116 REG_CHROMA_ON
, 3, REG_EDGE_ON
, 5,
117 REG_AF_NORMAL
, REG_FD_OFF
,
118 REG_MCC_OFF
, REG_LIGHT_OFF
, REG_FLASH_OFF
,
119 6, REG_ISO_AUTO
, REG_CAP_NONE
, REG_WDR_OFF
,
124 * m5mols_do_scenemode() - Change current scenemode
125 * @info: M-5MOLS driver data structure
126 * @mode: Desired mode of the scenemode
128 * WARNING: The execution order is important. Do not change the order.
130 int m5mols_do_scenemode(struct m5mols_info
*info
, u8 mode
)
132 struct v4l2_subdev
*sd
= &info
->sd
;
133 struct m5mols_scenemode scenemode
= m5mols_default_scenemode
[mode
];
136 if (mode
> REG_SCENE_CANDLE
)
139 ret
= v4l2_ctrl_s_ctrl(info
->lock_3a
, 0);
141 ret
= m5mols_write(sd
, AE_EV_PRESET_MONITOR
, mode
);
143 ret
= m5mols_write(sd
, AE_EV_PRESET_CAPTURE
, mode
);
145 ret
= m5mols_write(sd
, AE_MODE
, scenemode
.metering
);
147 ret
= m5mols_write(sd
, AE_INDEX
, scenemode
.ev_bias
);
149 ret
= m5mols_write(sd
, AWB_MODE
, scenemode
.wb_mode
);
151 ret
= m5mols_write(sd
, AWB_MANUAL
, scenemode
.wb_preset
);
153 ret
= m5mols_write(sd
, MON_CHROMA_EN
, scenemode
.chroma_en
);
155 ret
= m5mols_write(sd
, MON_CHROMA_LVL
, scenemode
.chroma_lvl
);
157 ret
= m5mols_write(sd
, MON_EDGE_EN
, scenemode
.edge_en
);
159 ret
= m5mols_write(sd
, MON_EDGE_LVL
, scenemode
.edge_lvl
);
160 if (!ret
&& is_available_af(info
))
161 ret
= m5mols_write(sd
, AF_MODE
, scenemode
.af_range
);
162 if (!ret
&& is_available_af(info
))
163 ret
= m5mols_write(sd
, FD_CTL
, scenemode
.fd_mode
);
165 ret
= m5mols_write(sd
, MON_TONE_CTL
, scenemode
.tone
);
167 ret
= m5mols_write(sd
, AE_ISO
, scenemode
.iso
);
169 ret
= m5mols_set_mode(info
, REG_CAPTURE
);
171 ret
= m5mols_write(sd
, CAPP_WDR_EN
, scenemode
.wdr
);
173 ret
= m5mols_write(sd
, CAPP_MCC_MODE
, scenemode
.mcc
);
175 ret
= m5mols_write(sd
, CAPP_LIGHT_CTRL
, scenemode
.light
);
177 ret
= m5mols_write(sd
, CAPP_FLASH_CTRL
, scenemode
.flash
);
179 ret
= m5mols_write(sd
, CAPC_MODE
, scenemode
.capt_mode
);
181 ret
= m5mols_set_mode(info
, REG_MONITOR
);
186 static int m5mols_3a_lock(struct m5mols_info
*info
, struct v4l2_ctrl
*ctrl
)
188 bool af_lock
= ctrl
->val
& V4L2_LOCK_FOCUS
;
191 if ((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_EXPOSURE
) {
192 bool ae_lock
= ctrl
->val
& V4L2_LOCK_EXPOSURE
;
194 ret
= m5mols_write(&info
->sd
, AE_LOCK
, ae_lock
?
195 REG_AE_LOCK
: REG_AE_UNLOCK
);
200 if (((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_WHITE_BALANCE
)
201 && info
->auto_wb
->val
) {
202 bool awb_lock
= ctrl
->val
& V4L2_LOCK_WHITE_BALANCE
;
204 ret
= m5mols_write(&info
->sd
, AWB_LOCK
, awb_lock
?
205 REG_AWB_LOCK
: REG_AWB_UNLOCK
);
210 if (!info
->ver
.af
|| !af_lock
)
213 if ((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_FOCUS
)
214 ret
= m5mols_write(&info
->sd
, AF_EXECUTE
, REG_AF_STOP
);
219 static int m5mols_set_metering_mode(struct m5mols_info
*info
, int mode
)
221 unsigned int metering
;
224 case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED
:
225 metering
= REG_AE_CENTER
;
227 case V4L2_EXPOSURE_METERING_SPOT
:
228 metering
= REG_AE_SPOT
;
231 metering
= REG_AE_ALL
;
235 return m5mols_write(&info
->sd
, AE_MODE
, metering
);
238 static int m5mols_set_exposure(struct m5mols_info
*info
, int exposure
)
240 struct v4l2_subdev
*sd
= &info
->sd
;
243 if (exposure
== V4L2_EXPOSURE_AUTO
) {
244 /* Unlock auto exposure */
245 info
->lock_3a
->val
&= ~V4L2_LOCK_EXPOSURE
;
246 m5mols_3a_lock(info
, info
->lock_3a
);
248 ret
= m5mols_set_metering_mode(info
, info
->metering
->val
);
252 v4l2_dbg(1, m5mols_debug
, sd
,
253 "%s: exposure bias: %#x, metering: %#x\n",
254 __func__
, info
->exposure_bias
->val
,
255 info
->metering
->val
);
257 return m5mols_write(sd
, AE_INDEX
, info
->exposure_bias
->val
);
260 if (exposure
== V4L2_EXPOSURE_MANUAL
) {
261 ret
= m5mols_write(sd
, AE_MODE
, REG_AE_OFF
);
263 ret
= m5mols_write(sd
, AE_MAN_GAIN_MON
,
264 info
->exposure
->val
);
266 ret
= m5mols_write(sd
, AE_MAN_GAIN_CAP
,
267 info
->exposure
->val
);
269 v4l2_dbg(1, m5mols_debug
, sd
, "%s: exposure: %#x\n",
270 __func__
, info
->exposure
->val
);
276 static int m5mols_set_white_balance(struct m5mols_info
*info
, int val
)
278 static const unsigned short wb
[][2] = {
279 { V4L2_WHITE_BALANCE_INCANDESCENT
, REG_AWB_INCANDESCENT
},
280 { V4L2_WHITE_BALANCE_FLUORESCENT
, REG_AWB_FLUORESCENT_1
},
281 { V4L2_WHITE_BALANCE_FLUORESCENT_H
, REG_AWB_FLUORESCENT_2
},
282 { V4L2_WHITE_BALANCE_HORIZON
, REG_AWB_HORIZON
},
283 { V4L2_WHITE_BALANCE_DAYLIGHT
, REG_AWB_DAYLIGHT
},
284 { V4L2_WHITE_BALANCE_FLASH
, REG_AWB_LEDLIGHT
},
285 { V4L2_WHITE_BALANCE_CLOUDY
, REG_AWB_CLOUDY
},
286 { V4L2_WHITE_BALANCE_SHADE
, REG_AWB_SHADE
},
287 { V4L2_WHITE_BALANCE_AUTO
, REG_AWB_AUTO
},
290 struct v4l2_subdev
*sd
= &info
->sd
;
293 for (i
= 0; i
< ARRAY_SIZE(wb
); i
++) {
298 v4l2_dbg(1, m5mols_debug
, sd
,
299 "Setting white balance to: %#x\n", wb
[i
][0]);
301 awb
= wb
[i
][0] == V4L2_WHITE_BALANCE_AUTO
;
302 ret
= m5mols_write(sd
, AWB_MODE
, awb
? REG_AWB_AUTO
:
308 ret
= m5mols_write(sd
, AWB_MANUAL
, wb
[i
][1]);
314 static int m5mols_set_saturation(struct m5mols_info
*info
, int val
)
316 int ret
= m5mols_write(&info
->sd
, MON_CHROMA_LVL
, val
);
320 return m5mols_write(&info
->sd
, MON_CHROMA_EN
, REG_CHROMA_ON
);
323 static int m5mols_set_color_effect(struct m5mols_info
*info
, int val
)
325 unsigned int m_effect
= REG_COLOR_EFFECT_OFF
;
326 unsigned int p_effect
= REG_EFFECT_OFF
;
327 unsigned int cfix_r
= 0, cfix_b
= 0;
328 struct v4l2_subdev
*sd
= &info
->sd
;
332 case V4L2_COLORFX_BW
:
333 m_effect
= REG_COLOR_EFFECT_ON
;
335 case V4L2_COLORFX_NEGATIVE
:
336 p_effect
= REG_EFFECT_NEGA
;
338 case V4L2_COLORFX_EMBOSS
:
339 p_effect
= REG_EFFECT_EMBOSS
;
341 case V4L2_COLORFX_SEPIA
:
342 m_effect
= REG_COLOR_EFFECT_ON
;
343 cfix_r
= REG_CFIXR_SEPIA
;
344 cfix_b
= REG_CFIXB_SEPIA
;
348 ret
= m5mols_write(sd
, PARM_EFFECT
, p_effect
);
350 ret
= m5mols_write(sd
, MON_EFFECT
, m_effect
);
352 if (ret
== 0 && m_effect
== REG_COLOR_EFFECT_ON
) {
353 ret
= m5mols_write(sd
, MON_CFIXR
, cfix_r
);
355 ret
= m5mols_write(sd
, MON_CFIXB
, cfix_b
);
358 v4l2_dbg(1, m5mols_debug
, sd
,
359 "p_effect: %#x, m_effect: %#x, r: %#x, b: %#x (%d)\n",
360 p_effect
, m_effect
, cfix_r
, cfix_b
, ret
);
365 static int m5mols_set_iso(struct m5mols_info
*info
, int auto_iso
)
367 u32 iso
= auto_iso
? 0 : info
->iso
->val
+ 1;
369 return m5mols_write(&info
->sd
, AE_ISO
, iso
);
372 static int m5mols_set_wdr(struct m5mols_info
*info
, int wdr
)
376 ret
= m5mols_write(&info
->sd
, MON_TONE_CTL
, wdr
? 9 : 5);
380 ret
= m5mols_set_mode(info
, REG_CAPTURE
);
384 return m5mols_write(&info
->sd
, CAPP_WDR_EN
, wdr
);
387 static int m5mols_set_stabilization(struct m5mols_info
*info
, int val
)
389 struct v4l2_subdev
*sd
= &info
->sd
;
390 unsigned int evp
= val
? 0xe : 0x0;
393 ret
= m5mols_write(sd
, AE_EV_PRESET_MONITOR
, evp
);
397 return m5mols_write(sd
, AE_EV_PRESET_CAPTURE
, evp
);
400 static int m5mols_g_volatile_ctrl(struct v4l2_ctrl
*ctrl
)
402 struct v4l2_subdev
*sd
= to_sd(ctrl
);
403 struct m5mols_info
*info
= to_m5mols(sd
);
405 u8 status
= REG_ISO_AUTO
;
407 v4l2_dbg(1, m5mols_debug
, sd
, "%s: ctrl: %s (%d)\n",
408 __func__
, ctrl
->name
, info
->isp_ready
);
410 if (!info
->isp_ready
)
414 case V4L2_CID_ISO_SENSITIVITY_AUTO
:
415 ret
= m5mols_read_u8(sd
, AE_ISO
, &status
);
418 if (status
!= REG_ISO_AUTO
)
419 info
->iso
->val
= status
- 1;
422 case V4L2_CID_3A_LOCK
:
425 ret
= m5mols_read_u8(sd
, AE_LOCK
, &status
);
429 info
->lock_3a
->val
|= V4L2_LOCK_EXPOSURE
;
431 ret
= m5mols_read_u8(sd
, AWB_LOCK
, &status
);
435 info
->lock_3a
->val
|= V4L2_LOCK_EXPOSURE
;
437 ret
= m5mols_read_u8(sd
, AF_EXECUTE
, &status
);
439 info
->lock_3a
->val
|= V4L2_LOCK_EXPOSURE
;
446 static int m5mols_s_ctrl(struct v4l2_ctrl
*ctrl
)
448 unsigned int ctrl_mode
= m5mols_get_ctrl_mode(ctrl
);
449 struct v4l2_subdev
*sd
= to_sd(ctrl
);
450 struct m5mols_info
*info
= to_m5mols(sd
);
451 int last_mode
= info
->mode
;
455 * If needed, defer restoring the controls until
456 * the device is fully initialized.
458 if (!info
->isp_ready
) {
463 v4l2_dbg(1, m5mols_debug
, sd
, "%s: %s, val: %d, priv: %p\n",
464 __func__
, ctrl
->name
, ctrl
->val
, ctrl
->priv
);
466 if (ctrl_mode
&& ctrl_mode
!= info
->mode
) {
467 ret
= m5mols_set_mode(info
, ctrl_mode
);
473 case V4L2_CID_3A_LOCK
:
474 ret
= m5mols_3a_lock(info
, ctrl
);
477 case V4L2_CID_ZOOM_ABSOLUTE
:
478 ret
= m5mols_write(sd
, MON_ZOOM
, ctrl
->val
);
481 case V4L2_CID_EXPOSURE_AUTO
:
482 ret
= m5mols_set_exposure(info
, ctrl
->val
);
485 case V4L2_CID_ISO_SENSITIVITY
:
486 ret
= m5mols_set_iso(info
, ctrl
->val
);
489 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
:
490 ret
= m5mols_set_white_balance(info
, ctrl
->val
);
493 case V4L2_CID_SATURATION
:
494 ret
= m5mols_set_saturation(info
, ctrl
->val
);
497 case V4L2_CID_COLORFX
:
498 ret
= m5mols_set_color_effect(info
, ctrl
->val
);
501 case V4L2_CID_WIDE_DYNAMIC_RANGE
:
502 ret
= m5mols_set_wdr(info
, ctrl
->val
);
505 case V4L2_CID_IMAGE_STABILIZATION
:
506 ret
= m5mols_set_stabilization(info
, ctrl
->val
);
509 case V4L2_CID_JPEG_COMPRESSION_QUALITY
:
510 ret
= m5mols_write(sd
, CAPP_JPEG_RATIO
, ctrl
->val
);
514 if (ret
== 0 && info
->mode
!= last_mode
)
515 ret
= m5mols_set_mode(info
, last_mode
);
520 static const struct v4l2_ctrl_ops m5mols_ctrl_ops
= {
521 .g_volatile_ctrl
= m5mols_g_volatile_ctrl
,
522 .s_ctrl
= m5mols_s_ctrl
,
525 /* Supported manual ISO values */
526 static const s64 iso_qmenu
[] = {
527 /* AE_ISO: 0x01...0x07 (ISO: 50...3200) */
528 50000, 100000, 200000, 400000, 800000, 1600000, 3200000
531 /* Supported Exposure Bias values, -2.0EV...+2.0EV */
532 static const s64 ev_bias_qmenu
[] = {
533 /* AE_INDEX: 0x00...0x08 */
534 -2000, -1500, -1000, -500, 0, 500, 1000, 1500, 2000
537 int m5mols_init_controls(struct v4l2_subdev
*sd
)
539 struct m5mols_info
*info
= to_m5mols(sd
);
544 /* Determine the firmware dependent control range and step values */
545 ret
= m5mols_read_u16(sd
, AE_MAX_GAIN_MON
, &exposure_max
);
549 zoom_step
= is_manufacturer(info
, REG_SAMSUNG_OPTICS
) ? 31 : 1;
550 v4l2_ctrl_handler_init(&info
->handle
, 20);
552 info
->auto_wb
= v4l2_ctrl_new_std_menu(&info
->handle
,
553 &m5mols_ctrl_ops
, V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
,
554 9, ~0x3fe, V4L2_WHITE_BALANCE_AUTO
);
556 /* Exposure control cluster */
557 info
->auto_exposure
= v4l2_ctrl_new_std_menu(&info
->handle
,
558 &m5mols_ctrl_ops
, V4L2_CID_EXPOSURE_AUTO
,
559 1, ~0x03, V4L2_EXPOSURE_AUTO
);
561 info
->exposure
= v4l2_ctrl_new_std(&info
->handle
,
562 &m5mols_ctrl_ops
, V4L2_CID_EXPOSURE
,
563 0, exposure_max
, 1, exposure_max
/ 2);
565 info
->exposure_bias
= v4l2_ctrl_new_int_menu(&info
->handle
,
566 &m5mols_ctrl_ops
, V4L2_CID_AUTO_EXPOSURE_BIAS
,
567 ARRAY_SIZE(ev_bias_qmenu
) - 1,
568 ARRAY_SIZE(ev_bias_qmenu
)/2 - 1,
571 info
->metering
= v4l2_ctrl_new_std_menu(&info
->handle
,
572 &m5mols_ctrl_ops
, V4L2_CID_EXPOSURE_METERING
,
573 2, ~0x7, V4L2_EXPOSURE_METERING_AVERAGE
);
575 /* ISO control cluster */
576 info
->auto_iso
= v4l2_ctrl_new_std_menu(&info
->handle
, &m5mols_ctrl_ops
,
577 V4L2_CID_ISO_SENSITIVITY_AUTO
, 1, ~0x03, 1);
579 info
->iso
= v4l2_ctrl_new_int_menu(&info
->handle
, &m5mols_ctrl_ops
,
580 V4L2_CID_ISO_SENSITIVITY
, ARRAY_SIZE(iso_qmenu
) - 1,
581 ARRAY_SIZE(iso_qmenu
)/2 - 1, iso_qmenu
);
583 info
->saturation
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
584 V4L2_CID_SATURATION
, 1, 5, 1, 3);
586 info
->zoom
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
587 V4L2_CID_ZOOM_ABSOLUTE
, 1, 70, zoom_step
, 1);
589 info
->colorfx
= v4l2_ctrl_new_std_menu(&info
->handle
, &m5mols_ctrl_ops
,
590 V4L2_CID_COLORFX
, 4, 0, V4L2_COLORFX_NONE
);
592 info
->wdr
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
593 V4L2_CID_WIDE_DYNAMIC_RANGE
, 0, 1, 1, 0);
595 info
->stabilization
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
596 V4L2_CID_IMAGE_STABILIZATION
, 0, 1, 1, 0);
598 info
->jpeg_quality
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
599 V4L2_CID_JPEG_COMPRESSION_QUALITY
, 1, 100, 1, 80);
601 info
->lock_3a
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
602 V4L2_CID_3A_LOCK
, 0, 0x7, 0, 0);
604 if (info
->handle
.error
) {
605 int ret
= info
->handle
.error
;
606 v4l2_err(sd
, "Failed to initialize controls: %d\n", ret
);
607 v4l2_ctrl_handler_free(&info
->handle
);
611 v4l2_ctrl_auto_cluster(4, &info
->auto_exposure
, 1, false);
612 info
->auto_iso
->flags
|= V4L2_CTRL_FLAG_VOLATILE
|
613 V4L2_CTRL_FLAG_UPDATE
;
614 v4l2_ctrl_auto_cluster(2, &info
->auto_iso
, 0, false);
616 info
->lock_3a
->flags
|= V4L2_CTRL_FLAG_VOLATILE
;
618 m5mols_set_ctrl_mode(info
->auto_exposure
, REG_PARAMETER
);
619 m5mols_set_ctrl_mode(info
->auto_wb
, REG_PARAMETER
);
620 m5mols_set_ctrl_mode(info
->colorfx
, REG_MONITOR
);
622 sd
->ctrl_handler
= &info
->handle
;