2 * Samsung LSI S5C73M3 8M pixel camera driver
4 * Copyright (C) 2012, Samsung Electronics, Co., Ltd.
5 * Sylwester Nawrocki <s.nawrocki@samsung.com>
6 * Andrzej Hajda <a.hajda@samsung.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #include <linux/sizes.h>
19 #include <linux/delay.h>
20 #include <linux/firmware.h>
21 #include <linux/gpio.h>
22 #include <linux/i2c.h>
23 #include <linux/init.h>
24 #include <linux/media.h>
25 #include <linux/module.h>
26 #include <linux/regulator/consumer.h>
27 #include <linux/slab.h>
28 #include <linux/spi/spi.h>
29 #include <linux/videodev2.h>
30 #include <media/media-entity.h>
31 #include <media/v4l2-ctrls.h>
32 #include <media/v4l2-device.h>
33 #include <media/v4l2-subdev.h>
34 #include <media/v4l2-mediabus.h>
35 #include <media/i2c/s5c73m3.h>
39 static int s5c73m3_get_af_status(struct s5c73m3
*state
, struct v4l2_ctrl
*ctrl
)
41 u16 reg
= REG_AF_STATUS_UNFOCUSED
;
43 int ret
= s5c73m3_read(state
, REG_AF_STATUS
, ®
);
46 case REG_CAF_STATUS_FIND_SEARCH_DIR
:
47 case REG_AF_STATUS_FOCUSING
:
48 case REG_CAF_STATUS_FOCUSING
:
49 ctrl
->val
= V4L2_AUTO_FOCUS_STATUS_BUSY
;
51 case REG_CAF_STATUS_FOCUSED
:
52 case REG_AF_STATUS_FOCUSED
:
53 ctrl
->val
= V4L2_AUTO_FOCUS_STATUS_REACHED
;
56 v4l2_info(&state
->sensor_sd
, "Unknown AF status %#x\n", reg
);
58 case REG_CAF_STATUS_UNFOCUSED
:
59 case REG_AF_STATUS_UNFOCUSED
:
60 case REG_AF_STATUS_INVALID
:
61 ctrl
->val
= V4L2_AUTO_FOCUS_STATUS_FAILED
;
68 static int s5c73m3_g_volatile_ctrl(struct v4l2_ctrl
*ctrl
)
70 struct v4l2_subdev
*sd
= ctrl_to_sensor_sd(ctrl
);
71 struct s5c73m3
*state
= sensor_sd_to_s5c73m3(sd
);
74 if (state
->power
== 0)
78 case V4L2_CID_FOCUS_AUTO
:
79 ret
= s5c73m3_get_af_status(state
, state
->ctrls
.af_status
);
88 static int s5c73m3_set_colorfx(struct s5c73m3
*state
, int val
)
90 static const unsigned short colorfx
[][2] = {
91 { V4L2_COLORFX_NONE
, COMM_IMAGE_EFFECT_NONE
},
92 { V4L2_COLORFX_BW
, COMM_IMAGE_EFFECT_MONO
},
93 { V4L2_COLORFX_SEPIA
, COMM_IMAGE_EFFECT_SEPIA
},
94 { V4L2_COLORFX_NEGATIVE
, COMM_IMAGE_EFFECT_NEGATIVE
},
95 { V4L2_COLORFX_AQUA
, COMM_IMAGE_EFFECT_AQUA
},
99 for (i
= 0; i
< ARRAY_SIZE(colorfx
); i
++) {
100 if (colorfx
[i
][0] != val
)
103 v4l2_dbg(1, s5c73m3_dbg
, &state
->sensor_sd
,
104 "Setting %s color effect\n",
105 v4l2_ctrl_get_menu(state
->ctrls
.colorfx
->id
)[i
]);
107 return s5c73m3_isp_command(state
, COMM_IMAGE_EFFECT
,
113 /* Set exposure metering/exposure bias */
114 static int s5c73m3_set_exposure(struct s5c73m3
*state
, int auto_exp
)
116 struct v4l2_subdev
*sd
= &state
->sensor_sd
;
117 struct s5c73m3_ctrls
*ctrls
= &state
->ctrls
;
120 if (ctrls
->exposure_metering
->is_new
) {
123 switch (ctrls
->exposure_metering
->val
) {
124 case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED
:
125 metering
= COMM_METERING_CENTER
;
127 case V4L2_EXPOSURE_METERING_SPOT
:
128 metering
= COMM_METERING_SPOT
;
131 metering
= COMM_METERING_AVERAGE
;
135 ret
= s5c73m3_isp_command(state
, COMM_METERING
, metering
);
138 if (!ret
&& ctrls
->exposure_bias
->is_new
) {
139 u16 exp_bias
= ctrls
->exposure_bias
->val
;
140 ret
= s5c73m3_isp_command(state
, COMM_EV
, exp_bias
);
143 v4l2_dbg(1, s5c73m3_dbg
, sd
,
144 "%s: exposure bias: %#x, metering: %#x (%d)\n", __func__
,
145 ctrls
->exposure_bias
->val
, ctrls
->exposure_metering
->val
, ret
);
150 static int s5c73m3_set_white_balance(struct s5c73m3
*state
, int val
)
152 static const unsigned short wb
[][2] = {
153 { V4L2_WHITE_BALANCE_INCANDESCENT
, COMM_AWB_MODE_INCANDESCENT
},
154 { V4L2_WHITE_BALANCE_FLUORESCENT
, COMM_AWB_MODE_FLUORESCENT1
},
155 { V4L2_WHITE_BALANCE_FLUORESCENT_H
, COMM_AWB_MODE_FLUORESCENT2
},
156 { V4L2_WHITE_BALANCE_CLOUDY
, COMM_AWB_MODE_CLOUDY
},
157 { V4L2_WHITE_BALANCE_DAYLIGHT
, COMM_AWB_MODE_DAYLIGHT
},
158 { V4L2_WHITE_BALANCE_AUTO
, COMM_AWB_MODE_AUTO
},
162 for (i
= 0; i
< ARRAY_SIZE(wb
); i
++) {
166 v4l2_dbg(1, s5c73m3_dbg
, &state
->sensor_sd
,
167 "Setting white balance to: %s\n",
168 v4l2_ctrl_get_menu(state
->ctrls
.auto_wb
->id
)[i
]);
170 return s5c73m3_isp_command(state
, COMM_AWB_MODE
, wb
[i
][1]);
176 static int s5c73m3_af_run(struct s5c73m3
*state
, bool on
)
178 struct s5c73m3_ctrls
*c
= &state
->ctrls
;
181 return s5c73m3_isp_command(state
, COMM_AF_CON
,
184 if (c
->focus_auto
->val
)
185 return s5c73m3_isp_command(state
, COMM_AF_MODE
,
186 COMM_AF_MODE_PREVIEW_CAF_START
);
188 return s5c73m3_isp_command(state
, COMM_AF_CON
, COMM_AF_CON_START
);
191 static int s5c73m3_3a_lock(struct s5c73m3
*state
, struct v4l2_ctrl
*ctrl
)
193 bool awb_lock
= ctrl
->val
& V4L2_LOCK_WHITE_BALANCE
;
194 bool ae_lock
= ctrl
->val
& V4L2_LOCK_EXPOSURE
;
195 bool af_lock
= ctrl
->val
& V4L2_LOCK_FOCUS
;
198 if ((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_EXPOSURE
) {
199 ret
= s5c73m3_isp_command(state
, COMM_AE_CON
,
200 ae_lock
? COMM_AE_STOP
: COMM_AE_START
);
205 if (((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_WHITE_BALANCE
)
206 && state
->ctrls
.auto_wb
->val
) {
207 ret
= s5c73m3_isp_command(state
, COMM_AWB_CON
,
208 awb_lock
? COMM_AWB_STOP
: COMM_AWB_START
);
213 if ((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_FOCUS
)
214 ret
= s5c73m3_af_run(state
, ~af_lock
);
219 static int s5c73m3_set_auto_focus(struct s5c73m3
*state
, int caf
)
221 struct s5c73m3_ctrls
*c
= &state
->ctrls
;
224 if (c
->af_distance
->is_new
) {
225 u16 mode
= (c
->af_distance
->val
== V4L2_AUTO_FOCUS_RANGE_MACRO
)
226 ? COMM_AF_MODE_MACRO
: COMM_AF_MODE_NORMAL
;
227 ret
= s5c73m3_isp_command(state
, COMM_AF_MODE
, mode
);
232 if (!ret
|| (c
->focus_auto
->is_new
&& c
->focus_auto
->val
) ||
234 ret
= s5c73m3_af_run(state
, 1);
235 else if ((c
->focus_auto
->is_new
&& !c
->focus_auto
->val
) ||
237 ret
= s5c73m3_af_run(state
, 0);
244 static int s5c73m3_set_contrast(struct s5c73m3
*state
, int val
)
246 u16 reg
= (val
< 0) ? -val
+ 2 : val
;
247 return s5c73m3_isp_command(state
, COMM_CONTRAST
, reg
);
250 static int s5c73m3_set_saturation(struct s5c73m3
*state
, int val
)
252 u16 reg
= (val
< 0) ? -val
+ 2 : val
;
253 return s5c73m3_isp_command(state
, COMM_SATURATION
, reg
);
256 static int s5c73m3_set_sharpness(struct s5c73m3
*state
, int val
)
258 u16 reg
= (val
< 0) ? -val
+ 2 : val
;
259 return s5c73m3_isp_command(state
, COMM_SHARPNESS
, reg
);
262 static int s5c73m3_set_iso(struct s5c73m3
*state
, int val
)
266 if (val
== V4L2_ISO_SENSITIVITY_MANUAL
)
267 iso
= state
->ctrls
.iso
->val
+ 1;
271 return s5c73m3_isp_command(state
, COMM_ISO
, iso
);
274 static int s5c73m3_set_stabilization(struct s5c73m3
*state
, int val
)
276 struct v4l2_subdev
*sd
= &state
->sensor_sd
;
278 v4l2_dbg(1, s5c73m3_dbg
, sd
, "Image stabilization: %d\n", val
);
280 return s5c73m3_isp_command(state
, COMM_FRAME_RATE
, val
?
281 COMM_FRAME_RATE_ANTI_SHAKE
: COMM_FRAME_RATE_AUTO_SET
);
284 static int s5c73m3_set_jpeg_quality(struct s5c73m3
*state
, int quality
)
289 reg
= COMM_IMAGE_QUALITY_NORMAL
;
290 else if (quality
<= 75)
291 reg
= COMM_IMAGE_QUALITY_FINE
;
293 reg
= COMM_IMAGE_QUALITY_SUPERFINE
;
295 return s5c73m3_isp_command(state
, COMM_IMAGE_QUALITY
, reg
);
298 static int s5c73m3_set_scene_program(struct s5c73m3
*state
, int val
)
300 static const unsigned short scene_lookup
[] = {
301 COMM_SCENE_MODE_NONE
, /* V4L2_SCENE_MODE_NONE */
302 COMM_SCENE_MODE_AGAINST_LIGHT
,/* V4L2_SCENE_MODE_BACKLIGHT */
303 COMM_SCENE_MODE_BEACH
, /* V4L2_SCENE_MODE_BEACH_SNOW */
304 COMM_SCENE_MODE_CANDLE
, /* V4L2_SCENE_MODE_CANDLE_LIGHT */
305 COMM_SCENE_MODE_DAWN
, /* V4L2_SCENE_MODE_DAWN_DUSK */
306 COMM_SCENE_MODE_FALL
, /* V4L2_SCENE_MODE_FALL_COLORS */
307 COMM_SCENE_MODE_FIRE
, /* V4L2_SCENE_MODE_FIREWORKS */
308 COMM_SCENE_MODE_LANDSCAPE
, /* V4L2_SCENE_MODE_LANDSCAPE */
309 COMM_SCENE_MODE_NIGHT
, /* V4L2_SCENE_MODE_NIGHT */
310 COMM_SCENE_MODE_INDOOR
, /* V4L2_SCENE_MODE_PARTY_INDOOR */
311 COMM_SCENE_MODE_PORTRAIT
, /* V4L2_SCENE_MODE_PORTRAIT */
312 COMM_SCENE_MODE_SPORTS
, /* V4L2_SCENE_MODE_SPORTS */
313 COMM_SCENE_MODE_SUNSET
, /* V4L2_SCENE_MODE_SUNSET */
314 COMM_SCENE_MODE_TEXT
, /* V4L2_SCENE_MODE_TEXT */
317 v4l2_dbg(1, s5c73m3_dbg
, &state
->sensor_sd
, "Setting %s scene mode\n",
318 v4l2_ctrl_get_menu(state
->ctrls
.scene_mode
->id
)[val
]);
320 return s5c73m3_isp_command(state
, COMM_SCENE_MODE
, scene_lookup
[val
]);
323 static int s5c73m3_set_power_line_freq(struct s5c73m3
*state
, int val
)
325 unsigned int pwr_line_freq
= COMM_FLICKER_NONE
;
328 case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED
:
329 pwr_line_freq
= COMM_FLICKER_NONE
;
331 case V4L2_CID_POWER_LINE_FREQUENCY_50HZ
:
332 pwr_line_freq
= COMM_FLICKER_AUTO_50HZ
;
334 case V4L2_CID_POWER_LINE_FREQUENCY_60HZ
:
335 pwr_line_freq
= COMM_FLICKER_AUTO_60HZ
;
338 case V4L2_CID_POWER_LINE_FREQUENCY_AUTO
:
339 pwr_line_freq
= COMM_FLICKER_NONE
;
342 return s5c73m3_isp_command(state
, COMM_FLICKER_MODE
, pwr_line_freq
);
345 static int s5c73m3_s_ctrl(struct v4l2_ctrl
*ctrl
)
347 struct v4l2_subdev
*sd
= ctrl_to_sensor_sd(ctrl
);
348 struct s5c73m3
*state
= sensor_sd_to_s5c73m3(sd
);
351 v4l2_dbg(1, s5c73m3_dbg
, sd
, "set_ctrl: %s, value: %d\n",
352 ctrl
->name
, ctrl
->val
);
354 mutex_lock(&state
->lock
);
356 * If the device is not powered up by the host driver do
357 * not apply any controls to H/W at this time. Instead
358 * the controls will be restored right after power-up.
360 if (state
->power
== 0)
363 if (ctrl
->flags
& V4L2_CTRL_FLAG_INACTIVE
) {
369 case V4L2_CID_3A_LOCK
:
370 ret
= s5c73m3_3a_lock(state
, ctrl
);
373 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
:
374 ret
= s5c73m3_set_white_balance(state
, ctrl
->val
);
377 case V4L2_CID_CONTRAST
:
378 ret
= s5c73m3_set_contrast(state
, ctrl
->val
);
381 case V4L2_CID_COLORFX
:
382 ret
= s5c73m3_set_colorfx(state
, ctrl
->val
);
385 case V4L2_CID_EXPOSURE_AUTO
:
386 ret
= s5c73m3_set_exposure(state
, ctrl
->val
);
389 case V4L2_CID_FOCUS_AUTO
:
390 ret
= s5c73m3_set_auto_focus(state
, ctrl
->val
);
393 case V4L2_CID_IMAGE_STABILIZATION
:
394 ret
= s5c73m3_set_stabilization(state
, ctrl
->val
);
397 case V4L2_CID_ISO_SENSITIVITY
:
398 ret
= s5c73m3_set_iso(state
, ctrl
->val
);
401 case V4L2_CID_JPEG_COMPRESSION_QUALITY
:
402 ret
= s5c73m3_set_jpeg_quality(state
, ctrl
->val
);
405 case V4L2_CID_POWER_LINE_FREQUENCY
:
406 ret
= s5c73m3_set_power_line_freq(state
, ctrl
->val
);
409 case V4L2_CID_SATURATION
:
410 ret
= s5c73m3_set_saturation(state
, ctrl
->val
);
413 case V4L2_CID_SCENE_MODE
:
414 ret
= s5c73m3_set_scene_program(state
, ctrl
->val
);
417 case V4L2_CID_SHARPNESS
:
418 ret
= s5c73m3_set_sharpness(state
, ctrl
->val
);
421 case V4L2_CID_WIDE_DYNAMIC_RANGE
:
422 ret
= s5c73m3_isp_command(state
, COMM_WDR
, !!ctrl
->val
);
425 case V4L2_CID_ZOOM_ABSOLUTE
:
426 ret
= s5c73m3_isp_command(state
, COMM_ZOOM_STEP
, ctrl
->val
);
430 mutex_unlock(&state
->lock
);
434 static const struct v4l2_ctrl_ops s5c73m3_ctrl_ops
= {
435 .g_volatile_ctrl
= s5c73m3_g_volatile_ctrl
,
436 .s_ctrl
= s5c73m3_s_ctrl
,
439 /* Supported manual ISO values */
440 static const s64 iso_qmenu
[] = {
441 /* COMM_ISO: 0x0001...0x0004 */
445 /* Supported exposure bias values (-2.0EV...+2.0EV) */
446 static const s64 ev_bias_qmenu
[] = {
447 /* COMM_EV: 0x0000...0x0008 */
448 -2000, -1500, -1000, -500, 0, 500, 1000, 1500, 2000
451 int s5c73m3_init_controls(struct s5c73m3
*state
)
453 const struct v4l2_ctrl_ops
*ops
= &s5c73m3_ctrl_ops
;
454 struct s5c73m3_ctrls
*ctrls
= &state
->ctrls
;
455 struct v4l2_ctrl_handler
*hdl
= &ctrls
->handler
;
457 int ret
= v4l2_ctrl_handler_init(hdl
, 22);
462 ctrls
->auto_wb
= v4l2_ctrl_new_std_menu(hdl
, ops
,
463 V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
,
464 9, ~0x15e, V4L2_WHITE_BALANCE_AUTO
);
466 /* Exposure (only automatic exposure) */
467 ctrls
->auto_exposure
= v4l2_ctrl_new_std_menu(hdl
, ops
,
468 V4L2_CID_EXPOSURE_AUTO
, 0, ~0x01, V4L2_EXPOSURE_AUTO
);
470 ctrls
->exposure_bias
= v4l2_ctrl_new_int_menu(hdl
, ops
,
471 V4L2_CID_AUTO_EXPOSURE_BIAS
,
472 ARRAY_SIZE(ev_bias_qmenu
) - 1,
473 ARRAY_SIZE(ev_bias_qmenu
)/2 - 1,
476 ctrls
->exposure_metering
= v4l2_ctrl_new_std_menu(hdl
, ops
,
477 V4L2_CID_EXPOSURE_METERING
,
478 2, ~0x7, V4L2_EXPOSURE_METERING_AVERAGE
);
481 ctrls
->focus_auto
= v4l2_ctrl_new_std(hdl
, ops
,
482 V4L2_CID_FOCUS_AUTO
, 0, 1, 1, 0);
484 ctrls
->af_start
= v4l2_ctrl_new_std(hdl
, ops
,
485 V4L2_CID_AUTO_FOCUS_START
, 0, 1, 1, 0);
487 ctrls
->af_stop
= v4l2_ctrl_new_std(hdl
, ops
,
488 V4L2_CID_AUTO_FOCUS_STOP
, 0, 1, 1, 0);
490 ctrls
->af_status
= v4l2_ctrl_new_std(hdl
, ops
,
491 V4L2_CID_AUTO_FOCUS_STATUS
, 0,
492 (V4L2_AUTO_FOCUS_STATUS_BUSY
|
493 V4L2_AUTO_FOCUS_STATUS_REACHED
|
494 V4L2_AUTO_FOCUS_STATUS_FAILED
),
495 0, V4L2_AUTO_FOCUS_STATUS_IDLE
);
497 ctrls
->af_distance
= v4l2_ctrl_new_std_menu(hdl
, ops
,
498 V4L2_CID_AUTO_FOCUS_RANGE
,
499 V4L2_AUTO_FOCUS_RANGE_MACRO
,
500 ~(1 << V4L2_AUTO_FOCUS_RANGE_NORMAL
|
501 1 << V4L2_AUTO_FOCUS_RANGE_MACRO
),
502 V4L2_AUTO_FOCUS_RANGE_NORMAL
);
503 /* ISO sensitivity */
504 ctrls
->auto_iso
= v4l2_ctrl_new_std_menu(hdl
, ops
,
505 V4L2_CID_ISO_SENSITIVITY_AUTO
, 1, 0,
506 V4L2_ISO_SENSITIVITY_AUTO
);
508 ctrls
->iso
= v4l2_ctrl_new_int_menu(hdl
, ops
,
509 V4L2_CID_ISO_SENSITIVITY
, ARRAY_SIZE(iso_qmenu
) - 1,
510 ARRAY_SIZE(iso_qmenu
)/2 - 1, iso_qmenu
);
512 ctrls
->contrast
= v4l2_ctrl_new_std(hdl
, ops
,
513 V4L2_CID_CONTRAST
, -2, 2, 1, 0);
515 ctrls
->saturation
= v4l2_ctrl_new_std(hdl
, ops
,
516 V4L2_CID_SATURATION
, -2, 2, 1, 0);
518 ctrls
->sharpness
= v4l2_ctrl_new_std(hdl
, ops
,
519 V4L2_CID_SHARPNESS
, -2, 2, 1, 0);
521 ctrls
->zoom
= v4l2_ctrl_new_std(hdl
, ops
,
522 V4L2_CID_ZOOM_ABSOLUTE
, 0, 30, 1, 0);
524 ctrls
->colorfx
= v4l2_ctrl_new_std_menu(hdl
, ops
, V4L2_CID_COLORFX
,
525 V4L2_COLORFX_AQUA
, ~0x40f, V4L2_COLORFX_NONE
);
527 ctrls
->wdr
= v4l2_ctrl_new_std(hdl
, ops
,
528 V4L2_CID_WIDE_DYNAMIC_RANGE
, 0, 1, 1, 0);
530 ctrls
->stabilization
= v4l2_ctrl_new_std(hdl
, ops
,
531 V4L2_CID_IMAGE_STABILIZATION
, 0, 1, 1, 0);
533 v4l2_ctrl_new_std_menu(hdl
, ops
, V4L2_CID_POWER_LINE_FREQUENCY
,
534 V4L2_CID_POWER_LINE_FREQUENCY_AUTO
, 0,
535 V4L2_CID_POWER_LINE_FREQUENCY_AUTO
);
537 ctrls
->jpeg_quality
= v4l2_ctrl_new_std(hdl
, ops
,
538 V4L2_CID_JPEG_COMPRESSION_QUALITY
, 1, 100, 1, 80);
540 ctrls
->scene_mode
= v4l2_ctrl_new_std_menu(hdl
, ops
,
541 V4L2_CID_SCENE_MODE
, V4L2_SCENE_MODE_TEXT
, ~0x3fff,
542 V4L2_SCENE_MODE_NONE
);
544 ctrls
->aaa_lock
= v4l2_ctrl_new_std(hdl
, ops
,
545 V4L2_CID_3A_LOCK
, 0, 0x7, 0, 0);
549 v4l2_ctrl_handler_free(hdl
);
553 v4l2_ctrl_auto_cluster(3, &ctrls
->auto_exposure
, 0, false);
554 ctrls
->auto_iso
->flags
|= V4L2_CTRL_FLAG_VOLATILE
|
555 V4L2_CTRL_FLAG_UPDATE
;
556 v4l2_ctrl_auto_cluster(2, &ctrls
->auto_iso
, 0, false);
557 ctrls
->af_status
->flags
|= V4L2_CTRL_FLAG_VOLATILE
;
558 v4l2_ctrl_cluster(6, &ctrls
->focus_auto
);
560 state
->sensor_sd
.ctrl_handler
= hdl
;