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 * @mode: Desired mode of the scenemode
131 * WARNING: The execution order is important. Do not change the order.
133 int m5mols_do_scenemode(struct m5mols_info
*info
, u8 mode
)
135 struct v4l2_subdev
*sd
= &info
->sd
;
136 struct m5mols_scenemode scenemode
= m5mols_default_scenemode
[mode
];
139 if (mode
> REG_SCENE_CANDLE
)
142 ret
= v4l2_ctrl_s_ctrl(info
->lock_3a
, 0);
144 ret
= m5mols_write(sd
, AE_EV_PRESET_MONITOR
, mode
);
146 ret
= m5mols_write(sd
, AE_EV_PRESET_CAPTURE
, mode
);
148 ret
= m5mols_write(sd
, AE_MODE
, scenemode
.metering
);
150 ret
= m5mols_write(sd
, AE_INDEX
, scenemode
.ev_bias
);
152 ret
= m5mols_write(sd
, AWB_MODE
, scenemode
.wb_mode
);
154 ret
= m5mols_write(sd
, AWB_MANUAL
, scenemode
.wb_preset
);
156 ret
= m5mols_write(sd
, MON_CHROMA_EN
, scenemode
.chroma_en
);
158 ret
= m5mols_write(sd
, MON_CHROMA_LVL
, scenemode
.chroma_lvl
);
160 ret
= m5mols_write(sd
, MON_EDGE_EN
, scenemode
.edge_en
);
162 ret
= m5mols_write(sd
, MON_EDGE_LVL
, scenemode
.edge_lvl
);
163 if (!ret
&& is_available_af(info
))
164 ret
= m5mols_write(sd
, AF_MODE
, scenemode
.af_range
);
165 if (!ret
&& is_available_af(info
))
166 ret
= m5mols_write(sd
, FD_CTL
, scenemode
.fd_mode
);
168 ret
= m5mols_write(sd
, MON_TONE_CTL
, scenemode
.tone
);
170 ret
= m5mols_write(sd
, AE_ISO
, scenemode
.iso
);
172 ret
= m5mols_set_mode(info
, REG_CAPTURE
);
174 ret
= m5mols_write(sd
, CAPP_WDR_EN
, scenemode
.wdr
);
176 ret
= m5mols_write(sd
, CAPP_MCC_MODE
, scenemode
.mcc
);
178 ret
= m5mols_write(sd
, CAPP_LIGHT_CTRL
, scenemode
.light
);
180 ret
= m5mols_write(sd
, CAPP_FLASH_CTRL
, scenemode
.flash
);
182 ret
= m5mols_write(sd
, CAPC_MODE
, scenemode
.capt_mode
);
184 ret
= m5mols_set_mode(info
, REG_MONITOR
);
189 static int m5mols_3a_lock(struct m5mols_info
*info
, struct v4l2_ctrl
*ctrl
)
191 bool af_lock
= ctrl
->val
& V4L2_LOCK_FOCUS
;
194 if ((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_EXPOSURE
) {
195 bool ae_lock
= ctrl
->val
& V4L2_LOCK_EXPOSURE
;
197 ret
= m5mols_write(&info
->sd
, AE_LOCK
, ae_lock
?
198 REG_AE_LOCK
: REG_AE_UNLOCK
);
203 if (((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_WHITE_BALANCE
)
204 && info
->auto_wb
->val
) {
205 bool awb_lock
= ctrl
->val
& V4L2_LOCK_WHITE_BALANCE
;
207 ret
= m5mols_write(&info
->sd
, AWB_LOCK
, awb_lock
?
208 REG_AWB_LOCK
: REG_AWB_UNLOCK
);
213 if (!info
->ver
.af
|| !af_lock
)
216 if ((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_FOCUS
)
217 ret
= m5mols_write(&info
->sd
, AF_EXECUTE
, REG_AF_STOP
);
222 static int m5mols_set_metering_mode(struct m5mols_info
*info
, int mode
)
224 unsigned int metering
;
227 case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED
:
228 metering
= REG_AE_CENTER
;
230 case V4L2_EXPOSURE_METERING_SPOT
:
231 metering
= REG_AE_SPOT
;
234 metering
= REG_AE_ALL
;
238 return m5mols_write(&info
->sd
, AE_MODE
, metering
);
241 static int m5mols_set_exposure(struct m5mols_info
*info
, int exposure
)
243 struct v4l2_subdev
*sd
= &info
->sd
;
246 if (exposure
== V4L2_EXPOSURE_AUTO
) {
247 /* Unlock auto exposure */
248 info
->lock_3a
->val
&= ~V4L2_LOCK_EXPOSURE
;
249 m5mols_3a_lock(info
, info
->lock_3a
);
251 ret
= m5mols_set_metering_mode(info
, info
->metering
->val
);
255 v4l2_dbg(1, m5mols_debug
, sd
,
256 "%s: exposure bias: %#x, metering: %#x\n",
257 __func__
, info
->exposure_bias
->val
,
258 info
->metering
->val
);
260 return m5mols_write(sd
, AE_INDEX
, info
->exposure_bias
->val
);
263 if (exposure
== V4L2_EXPOSURE_MANUAL
) {
264 ret
= m5mols_write(sd
, AE_MODE
, REG_AE_OFF
);
266 ret
= m5mols_write(sd
, AE_MAN_GAIN_MON
,
267 info
->exposure
->val
);
269 ret
= m5mols_write(sd
, AE_MAN_GAIN_CAP
,
270 info
->exposure
->val
);
272 v4l2_dbg(1, m5mols_debug
, sd
, "%s: exposure: %#x\n",
273 __func__
, info
->exposure
->val
);
279 static int m5mols_set_white_balance(struct m5mols_info
*info
, int val
)
281 static const unsigned short wb
[][2] = {
282 { V4L2_WHITE_BALANCE_INCANDESCENT
, REG_AWB_INCANDESCENT
},
283 { V4L2_WHITE_BALANCE_FLUORESCENT
, REG_AWB_FLUORESCENT_1
},
284 { V4L2_WHITE_BALANCE_FLUORESCENT_H
, REG_AWB_FLUORESCENT_2
},
285 { V4L2_WHITE_BALANCE_HORIZON
, REG_AWB_HORIZON
},
286 { V4L2_WHITE_BALANCE_DAYLIGHT
, REG_AWB_DAYLIGHT
},
287 { V4L2_WHITE_BALANCE_FLASH
, REG_AWB_LEDLIGHT
},
288 { V4L2_WHITE_BALANCE_CLOUDY
, REG_AWB_CLOUDY
},
289 { V4L2_WHITE_BALANCE_SHADE
, REG_AWB_SHADE
},
290 { V4L2_WHITE_BALANCE_AUTO
, REG_AWB_AUTO
},
293 struct v4l2_subdev
*sd
= &info
->sd
;
296 for (i
= 0; i
< ARRAY_SIZE(wb
); i
++) {
301 v4l2_dbg(1, m5mols_debug
, sd
,
302 "Setting white balance to: %#x\n", wb
[i
][0]);
304 awb
= wb
[i
][0] == V4L2_WHITE_BALANCE_AUTO
;
305 ret
= m5mols_write(sd
, AWB_MODE
, awb
? REG_AWB_AUTO
:
311 ret
= m5mols_write(sd
, AWB_MANUAL
, wb
[i
][1]);
317 static int m5mols_set_saturation(struct m5mols_info
*info
, int val
)
319 int ret
= m5mols_write(&info
->sd
, MON_CHROMA_LVL
, val
);
323 return m5mols_write(&info
->sd
, MON_CHROMA_EN
, REG_CHROMA_ON
);
326 static int m5mols_set_color_effect(struct m5mols_info
*info
, int val
)
328 unsigned int m_effect
= REG_COLOR_EFFECT_OFF
;
329 unsigned int p_effect
= REG_EFFECT_OFF
;
330 unsigned int cfix_r
= 0, cfix_b
= 0;
331 struct v4l2_subdev
*sd
= &info
->sd
;
335 case V4L2_COLORFX_BW
:
336 m_effect
= REG_COLOR_EFFECT_ON
;
338 case V4L2_COLORFX_NEGATIVE
:
339 p_effect
= REG_EFFECT_NEGA
;
341 case V4L2_COLORFX_EMBOSS
:
342 p_effect
= REG_EFFECT_EMBOSS
;
344 case V4L2_COLORFX_SEPIA
:
345 m_effect
= REG_COLOR_EFFECT_ON
;
346 cfix_r
= REG_CFIXR_SEPIA
;
347 cfix_b
= REG_CFIXB_SEPIA
;
351 ret
= m5mols_write(sd
, PARM_EFFECT
, p_effect
);
353 ret
= m5mols_write(sd
, MON_EFFECT
, m_effect
);
355 if (ret
== 0 && m_effect
== REG_COLOR_EFFECT_ON
) {
356 ret
= m5mols_write(sd
, MON_CFIXR
, cfix_r
);
358 ret
= m5mols_write(sd
, MON_CFIXB
, cfix_b
);
361 v4l2_dbg(1, m5mols_debug
, sd
,
362 "p_effect: %#x, m_effect: %#x, r: %#x, b: %#x (%d)\n",
363 p_effect
, m_effect
, cfix_r
, cfix_b
, ret
);
368 static int m5mols_set_iso(struct m5mols_info
*info
, int auto_iso
)
370 u32 iso
= auto_iso
? 0 : info
->iso
->val
+ 1;
372 return m5mols_write(&info
->sd
, AE_ISO
, iso
);
375 static int m5mols_set_wdr(struct m5mols_info
*info
, int wdr
)
379 ret
= m5mols_write(&info
->sd
, MON_TONE_CTL
, wdr
? 9 : 5);
383 ret
= m5mols_set_mode(info
, REG_CAPTURE
);
387 return m5mols_write(&info
->sd
, CAPP_WDR_EN
, wdr
);
390 static int m5mols_set_stabilization(struct m5mols_info
*info
, int val
)
392 struct v4l2_subdev
*sd
= &info
->sd
;
393 unsigned int evp
= val
? 0xe : 0x0;
396 ret
= m5mols_write(sd
, AE_EV_PRESET_MONITOR
, evp
);
400 return m5mols_write(sd
, AE_EV_PRESET_CAPTURE
, evp
);
403 static int m5mols_g_volatile_ctrl(struct v4l2_ctrl
*ctrl
)
405 struct v4l2_subdev
*sd
= to_sd(ctrl
);
406 struct m5mols_info
*info
= to_m5mols(sd
);
408 u8 status
= REG_ISO_AUTO
;
410 v4l2_dbg(1, m5mols_debug
, sd
, "%s: ctrl: %s (%d)\n",
411 __func__
, ctrl
->name
, info
->isp_ready
);
413 if (!info
->isp_ready
)
417 case V4L2_CID_ISO_SENSITIVITY_AUTO
:
418 ret
= m5mols_read_u8(sd
, AE_ISO
, &status
);
421 if (status
!= REG_ISO_AUTO
)
422 info
->iso
->val
= status
- 1;
425 case V4L2_CID_3A_LOCK
:
428 ret
= m5mols_read_u8(sd
, AE_LOCK
, &status
);
432 info
->lock_3a
->val
|= V4L2_LOCK_EXPOSURE
;
434 ret
= m5mols_read_u8(sd
, AWB_LOCK
, &status
);
438 info
->lock_3a
->val
|= V4L2_LOCK_EXPOSURE
;
440 ret
= m5mols_read_u8(sd
, AF_EXECUTE
, &status
);
442 info
->lock_3a
->val
|= V4L2_LOCK_EXPOSURE
;
449 static int m5mols_s_ctrl(struct v4l2_ctrl
*ctrl
)
451 unsigned int ctrl_mode
= m5mols_get_ctrl_mode(ctrl
);
452 struct v4l2_subdev
*sd
= to_sd(ctrl
);
453 struct m5mols_info
*info
= to_m5mols(sd
);
454 int last_mode
= info
->mode
;
458 * If needed, defer restoring the controls until
459 * the device is fully initialized.
461 if (!info
->isp_ready
) {
466 v4l2_dbg(1, m5mols_debug
, sd
, "%s: %s, val: %d, priv: %p\n",
467 __func__
, ctrl
->name
, ctrl
->val
, ctrl
->priv
);
469 if (ctrl_mode
&& ctrl_mode
!= info
->mode
) {
470 ret
= m5mols_set_mode(info
, ctrl_mode
);
476 case V4L2_CID_3A_LOCK
:
477 ret
= m5mols_3a_lock(info
, ctrl
);
480 case V4L2_CID_ZOOM_ABSOLUTE
:
481 ret
= m5mols_write(sd
, MON_ZOOM
, ctrl
->val
);
484 case V4L2_CID_EXPOSURE_AUTO
:
485 ret
= m5mols_set_exposure(info
, ctrl
->val
);
488 case V4L2_CID_ISO_SENSITIVITY
:
489 ret
= m5mols_set_iso(info
, ctrl
->val
);
492 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
:
493 ret
= m5mols_set_white_balance(info
, ctrl
->val
);
496 case V4L2_CID_SATURATION
:
497 ret
= m5mols_set_saturation(info
, ctrl
->val
);
500 case V4L2_CID_COLORFX
:
501 ret
= m5mols_set_color_effect(info
, ctrl
->val
);
504 case V4L2_CID_WIDE_DYNAMIC_RANGE
:
505 ret
= m5mols_set_wdr(info
, ctrl
->val
);
508 case V4L2_CID_IMAGE_STABILIZATION
:
509 ret
= m5mols_set_stabilization(info
, ctrl
->val
);
512 case V4L2_CID_JPEG_COMPRESSION_QUALITY
:
513 ret
= m5mols_write(sd
, CAPP_JPEG_RATIO
, ctrl
->val
);
517 if (ret
== 0 && info
->mode
!= last_mode
)
518 ret
= m5mols_set_mode(info
, last_mode
);
523 static const struct v4l2_ctrl_ops m5mols_ctrl_ops
= {
524 .g_volatile_ctrl
= m5mols_g_volatile_ctrl
,
525 .s_ctrl
= m5mols_s_ctrl
,
528 /* Supported manual ISO values */
529 static const s64 iso_qmenu
[] = {
530 /* AE_ISO: 0x01...0x07 (ISO: 50...3200) */
531 50000, 100000, 200000, 400000, 800000, 1600000, 3200000
534 /* Supported Exposure Bias values, -2.0EV...+2.0EV */
535 static const s64 ev_bias_qmenu
[] = {
536 /* AE_INDEX: 0x00...0x08 */
537 -2000, -1500, -1000, -500, 0, 500, 1000, 1500, 2000
540 int m5mols_init_controls(struct v4l2_subdev
*sd
)
542 struct m5mols_info
*info
= to_m5mols(sd
);
547 /* Determine the firmware dependent control range and step values */
548 ret
= m5mols_read_u16(sd
, AE_MAX_GAIN_MON
, &exposure_max
);
552 zoom_step
= is_manufacturer(info
, REG_SAMSUNG_OPTICS
) ? 31 : 1;
553 v4l2_ctrl_handler_init(&info
->handle
, 20);
555 info
->auto_wb
= v4l2_ctrl_new_std_menu(&info
->handle
,
556 &m5mols_ctrl_ops
, V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
,
557 9, ~0x3fe, V4L2_WHITE_BALANCE_AUTO
);
559 /* Exposure control cluster */
560 info
->auto_exposure
= v4l2_ctrl_new_std_menu(&info
->handle
,
561 &m5mols_ctrl_ops
, V4L2_CID_EXPOSURE_AUTO
,
562 1, ~0x03, V4L2_EXPOSURE_AUTO
);
564 info
->exposure
= v4l2_ctrl_new_std(&info
->handle
,
565 &m5mols_ctrl_ops
, V4L2_CID_EXPOSURE
,
566 0, exposure_max
, 1, exposure_max
/ 2);
568 info
->exposure_bias
= v4l2_ctrl_new_int_menu(&info
->handle
,
569 &m5mols_ctrl_ops
, V4L2_CID_AUTO_EXPOSURE_BIAS
,
570 ARRAY_SIZE(ev_bias_qmenu
) - 1,
571 ARRAY_SIZE(ev_bias_qmenu
)/2 - 1,
574 info
->metering
= v4l2_ctrl_new_std_menu(&info
->handle
,
575 &m5mols_ctrl_ops
, V4L2_CID_EXPOSURE_METERING
,
576 2, ~0x7, V4L2_EXPOSURE_METERING_AVERAGE
);
578 /* ISO control cluster */
579 info
->auto_iso
= v4l2_ctrl_new_std_menu(&info
->handle
, &m5mols_ctrl_ops
,
580 V4L2_CID_ISO_SENSITIVITY_AUTO
, 1, ~0x03, 1);
582 info
->iso
= v4l2_ctrl_new_int_menu(&info
->handle
, &m5mols_ctrl_ops
,
583 V4L2_CID_ISO_SENSITIVITY
, ARRAY_SIZE(iso_qmenu
) - 1,
584 ARRAY_SIZE(iso_qmenu
)/2 - 1, iso_qmenu
);
586 info
->saturation
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
587 V4L2_CID_SATURATION
, 1, 5, 1, 3);
589 info
->zoom
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
590 V4L2_CID_ZOOM_ABSOLUTE
, 1, 70, zoom_step
, 1);
592 info
->colorfx
= v4l2_ctrl_new_std_menu(&info
->handle
, &m5mols_ctrl_ops
,
593 V4L2_CID_COLORFX
, 4, 0, V4L2_COLORFX_NONE
);
595 info
->wdr
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
596 V4L2_CID_WIDE_DYNAMIC_RANGE
, 0, 1, 1, 0);
598 info
->stabilization
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
599 V4L2_CID_IMAGE_STABILIZATION
, 0, 1, 1, 0);
601 info
->jpeg_quality
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
602 V4L2_CID_JPEG_COMPRESSION_QUALITY
, 1, 100, 1, 80);
604 info
->lock_3a
= v4l2_ctrl_new_std(&info
->handle
, &m5mols_ctrl_ops
,
605 V4L2_CID_3A_LOCK
, 0, 0x7, 0, 0);
607 if (info
->handle
.error
) {
608 int ret
= info
->handle
.error
;
609 v4l2_err(sd
, "Failed to initialize controls: %d\n", ret
);
610 v4l2_ctrl_handler_free(&info
->handle
);
614 v4l2_ctrl_auto_cluster(4, &info
->auto_exposure
, 1, false);
615 info
->auto_iso
->flags
|= V4L2_CTRL_FLAG_VOLATILE
|
616 V4L2_CTRL_FLAG_UPDATE
;
617 v4l2_ctrl_auto_cluster(2, &info
->auto_iso
, 0, false);
619 info
->lock_3a
->flags
|= V4L2_CTRL_FLAG_VOLATILE
;
621 m5mols_set_ctrl_mode(info
->auto_exposure
, REG_PARAMETER
);
622 m5mols_set_ctrl_mode(info
->auto_wb
, REG_PARAMETER
);
623 m5mols_set_ctrl_mode(info
->colorfx
, REG_MONITOR
);
625 sd
->ctrl_handler
= &info
->handle
;