1 // SPDX-License-Identifier: GPL-2.0-only
3 * Samsung LSI S5C73M3 8M pixel camera driver
5 * Copyright (C) 2012, Samsung Electronics, Co., Ltd.
6 * Sylwester Nawrocki <s.nawrocki@samsung.com>
7 * Andrzej Hajda <a.hajda@samsung.com>
10 #include <linux/sizes.h>
11 #include <linux/delay.h>
12 #include <linux/firmware.h>
13 #include <linux/gpio.h>
14 #include <linux/i2c.h>
15 #include <linux/init.h>
16 #include <linux/media.h>
17 #include <linux/module.h>
18 #include <linux/regulator/consumer.h>
19 #include <linux/slab.h>
20 #include <linux/spi/spi.h>
21 #include <linux/videodev2.h>
22 #include <media/media-entity.h>
23 #include <media/v4l2-ctrls.h>
24 #include <media/v4l2-device.h>
25 #include <media/v4l2-subdev.h>
26 #include <media/v4l2-mediabus.h>
27 #include <media/i2c/s5c73m3.h>
31 static int s5c73m3_get_af_status(struct s5c73m3
*state
, struct v4l2_ctrl
*ctrl
)
33 u16 reg
= REG_AF_STATUS_UNFOCUSED
;
35 int ret
= s5c73m3_read(state
, REG_AF_STATUS
, ®
);
38 case REG_CAF_STATUS_FIND_SEARCH_DIR
:
39 case REG_AF_STATUS_FOCUSING
:
40 case REG_CAF_STATUS_FOCUSING
:
41 ctrl
->val
= V4L2_AUTO_FOCUS_STATUS_BUSY
;
43 case REG_CAF_STATUS_FOCUSED
:
44 case REG_AF_STATUS_FOCUSED
:
45 ctrl
->val
= V4L2_AUTO_FOCUS_STATUS_REACHED
;
48 v4l2_info(&state
->sensor_sd
, "Unknown AF status %#x\n", reg
);
50 case REG_CAF_STATUS_UNFOCUSED
:
51 case REG_AF_STATUS_UNFOCUSED
:
52 case REG_AF_STATUS_INVALID
:
53 ctrl
->val
= V4L2_AUTO_FOCUS_STATUS_FAILED
;
60 static int s5c73m3_g_volatile_ctrl(struct v4l2_ctrl
*ctrl
)
62 struct v4l2_subdev
*sd
= ctrl_to_sensor_sd(ctrl
);
63 struct s5c73m3
*state
= sensor_sd_to_s5c73m3(sd
);
66 if (state
->power
== 0)
70 case V4L2_CID_FOCUS_AUTO
:
71 ret
= s5c73m3_get_af_status(state
, state
->ctrls
.af_status
);
80 static int s5c73m3_set_colorfx(struct s5c73m3
*state
, int val
)
82 static const unsigned short colorfx
[][2] = {
83 { V4L2_COLORFX_NONE
, COMM_IMAGE_EFFECT_NONE
},
84 { V4L2_COLORFX_BW
, COMM_IMAGE_EFFECT_MONO
},
85 { V4L2_COLORFX_SEPIA
, COMM_IMAGE_EFFECT_SEPIA
},
86 { V4L2_COLORFX_NEGATIVE
, COMM_IMAGE_EFFECT_NEGATIVE
},
87 { V4L2_COLORFX_AQUA
, COMM_IMAGE_EFFECT_AQUA
},
91 for (i
= 0; i
< ARRAY_SIZE(colorfx
); i
++) {
92 if (colorfx
[i
][0] != val
)
95 v4l2_dbg(1, s5c73m3_dbg
, &state
->sensor_sd
,
96 "Setting %s color effect\n",
97 v4l2_ctrl_get_menu(state
->ctrls
.colorfx
->id
)[i
]);
99 return s5c73m3_isp_command(state
, COMM_IMAGE_EFFECT
,
105 /* Set exposure metering/exposure bias */
106 static int s5c73m3_set_exposure(struct s5c73m3
*state
, int auto_exp
)
108 struct v4l2_subdev
*sd
= &state
->sensor_sd
;
109 struct s5c73m3_ctrls
*ctrls
= &state
->ctrls
;
112 if (ctrls
->exposure_metering
->is_new
) {
115 switch (ctrls
->exposure_metering
->val
) {
116 case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED
:
117 metering
= COMM_METERING_CENTER
;
119 case V4L2_EXPOSURE_METERING_SPOT
:
120 metering
= COMM_METERING_SPOT
;
123 metering
= COMM_METERING_AVERAGE
;
127 ret
= s5c73m3_isp_command(state
, COMM_METERING
, metering
);
130 if (!ret
&& ctrls
->exposure_bias
->is_new
) {
131 u16 exp_bias
= ctrls
->exposure_bias
->val
;
132 ret
= s5c73m3_isp_command(state
, COMM_EV
, exp_bias
);
135 v4l2_dbg(1, s5c73m3_dbg
, sd
,
136 "%s: exposure bias: %#x, metering: %#x (%d)\n", __func__
,
137 ctrls
->exposure_bias
->val
, ctrls
->exposure_metering
->val
, ret
);
142 static int s5c73m3_set_white_balance(struct s5c73m3
*state
, int val
)
144 static const unsigned short wb
[][2] = {
145 { V4L2_WHITE_BALANCE_INCANDESCENT
, COMM_AWB_MODE_INCANDESCENT
},
146 { V4L2_WHITE_BALANCE_FLUORESCENT
, COMM_AWB_MODE_FLUORESCENT1
},
147 { V4L2_WHITE_BALANCE_FLUORESCENT_H
, COMM_AWB_MODE_FLUORESCENT2
},
148 { V4L2_WHITE_BALANCE_CLOUDY
, COMM_AWB_MODE_CLOUDY
},
149 { V4L2_WHITE_BALANCE_DAYLIGHT
, COMM_AWB_MODE_DAYLIGHT
},
150 { V4L2_WHITE_BALANCE_AUTO
, COMM_AWB_MODE_AUTO
},
154 for (i
= 0; i
< ARRAY_SIZE(wb
); i
++) {
158 v4l2_dbg(1, s5c73m3_dbg
, &state
->sensor_sd
,
159 "Setting white balance to: %s\n",
160 v4l2_ctrl_get_menu(state
->ctrls
.auto_wb
->id
)[i
]);
162 return s5c73m3_isp_command(state
, COMM_AWB_MODE
, wb
[i
][1]);
168 static int s5c73m3_af_run(struct s5c73m3
*state
, bool on
)
170 struct s5c73m3_ctrls
*c
= &state
->ctrls
;
173 return s5c73m3_isp_command(state
, COMM_AF_CON
,
176 if (c
->focus_auto
->val
)
177 return s5c73m3_isp_command(state
, COMM_AF_MODE
,
178 COMM_AF_MODE_PREVIEW_CAF_START
);
180 return s5c73m3_isp_command(state
, COMM_AF_CON
, COMM_AF_CON_START
);
183 static int s5c73m3_3a_lock(struct s5c73m3
*state
, struct v4l2_ctrl
*ctrl
)
185 bool awb_lock
= ctrl
->val
& V4L2_LOCK_WHITE_BALANCE
;
186 bool ae_lock
= ctrl
->val
& V4L2_LOCK_EXPOSURE
;
187 bool af_lock
= ctrl
->val
& V4L2_LOCK_FOCUS
;
190 if ((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_EXPOSURE
) {
191 ret
= s5c73m3_isp_command(state
, COMM_AE_CON
,
192 ae_lock
? COMM_AE_STOP
: COMM_AE_START
);
197 if (((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_WHITE_BALANCE
)
198 && state
->ctrls
.auto_wb
->val
) {
199 ret
= s5c73m3_isp_command(state
, COMM_AWB_CON
,
200 awb_lock
? COMM_AWB_STOP
: COMM_AWB_START
);
205 if ((ctrl
->val
^ ctrl
->cur
.val
) & V4L2_LOCK_FOCUS
)
206 ret
= s5c73m3_af_run(state
, !af_lock
);
211 static int s5c73m3_set_auto_focus(struct s5c73m3
*state
, int caf
)
213 struct s5c73m3_ctrls
*c
= &state
->ctrls
;
216 if (c
->af_distance
->is_new
) {
217 u16 mode
= (c
->af_distance
->val
== V4L2_AUTO_FOCUS_RANGE_MACRO
)
218 ? COMM_AF_MODE_MACRO
: COMM_AF_MODE_NORMAL
;
219 ret
= s5c73m3_isp_command(state
, COMM_AF_MODE
, mode
);
224 if (!ret
|| (c
->focus_auto
->is_new
&& c
->focus_auto
->val
) ||
226 ret
= s5c73m3_af_run(state
, 1);
227 else if ((c
->focus_auto
->is_new
&& !c
->focus_auto
->val
) ||
229 ret
= s5c73m3_af_run(state
, 0);
236 static int s5c73m3_set_contrast(struct s5c73m3
*state
, int val
)
238 u16 reg
= (val
< 0) ? -val
+ 2 : val
;
239 return s5c73m3_isp_command(state
, COMM_CONTRAST
, reg
);
242 static int s5c73m3_set_saturation(struct s5c73m3
*state
, int val
)
244 u16 reg
= (val
< 0) ? -val
+ 2 : val
;
245 return s5c73m3_isp_command(state
, COMM_SATURATION
, reg
);
248 static int s5c73m3_set_sharpness(struct s5c73m3
*state
, int val
)
250 u16 reg
= (val
< 0) ? -val
+ 2 : val
;
251 return s5c73m3_isp_command(state
, COMM_SHARPNESS
, reg
);
254 static int s5c73m3_set_iso(struct s5c73m3
*state
, int val
)
258 if (val
== V4L2_ISO_SENSITIVITY_MANUAL
)
259 iso
= state
->ctrls
.iso
->val
+ 1;
263 return s5c73m3_isp_command(state
, COMM_ISO
, iso
);
266 static int s5c73m3_set_stabilization(struct s5c73m3
*state
, int val
)
268 struct v4l2_subdev
*sd
= &state
->sensor_sd
;
270 v4l2_dbg(1, s5c73m3_dbg
, sd
, "Image stabilization: %d\n", val
);
272 return s5c73m3_isp_command(state
, COMM_FRAME_RATE
, val
?
273 COMM_FRAME_RATE_ANTI_SHAKE
: COMM_FRAME_RATE_AUTO_SET
);
276 static int s5c73m3_set_jpeg_quality(struct s5c73m3
*state
, int quality
)
281 reg
= COMM_IMAGE_QUALITY_NORMAL
;
282 else if (quality
<= 75)
283 reg
= COMM_IMAGE_QUALITY_FINE
;
285 reg
= COMM_IMAGE_QUALITY_SUPERFINE
;
287 return s5c73m3_isp_command(state
, COMM_IMAGE_QUALITY
, reg
);
290 static int s5c73m3_set_scene_program(struct s5c73m3
*state
, int val
)
292 static const unsigned short scene_lookup
[] = {
293 COMM_SCENE_MODE_NONE
, /* V4L2_SCENE_MODE_NONE */
294 COMM_SCENE_MODE_AGAINST_LIGHT
,/* V4L2_SCENE_MODE_BACKLIGHT */
295 COMM_SCENE_MODE_BEACH
, /* V4L2_SCENE_MODE_BEACH_SNOW */
296 COMM_SCENE_MODE_CANDLE
, /* V4L2_SCENE_MODE_CANDLE_LIGHT */
297 COMM_SCENE_MODE_DAWN
, /* V4L2_SCENE_MODE_DAWN_DUSK */
298 COMM_SCENE_MODE_FALL
, /* V4L2_SCENE_MODE_FALL_COLORS */
299 COMM_SCENE_MODE_FIRE
, /* V4L2_SCENE_MODE_FIREWORKS */
300 COMM_SCENE_MODE_LANDSCAPE
, /* V4L2_SCENE_MODE_LANDSCAPE */
301 COMM_SCENE_MODE_NIGHT
, /* V4L2_SCENE_MODE_NIGHT */
302 COMM_SCENE_MODE_INDOOR
, /* V4L2_SCENE_MODE_PARTY_INDOOR */
303 COMM_SCENE_MODE_PORTRAIT
, /* V4L2_SCENE_MODE_PORTRAIT */
304 COMM_SCENE_MODE_SPORTS
, /* V4L2_SCENE_MODE_SPORTS */
305 COMM_SCENE_MODE_SUNSET
, /* V4L2_SCENE_MODE_SUNSET */
306 COMM_SCENE_MODE_TEXT
, /* V4L2_SCENE_MODE_TEXT */
309 v4l2_dbg(1, s5c73m3_dbg
, &state
->sensor_sd
, "Setting %s scene mode\n",
310 v4l2_ctrl_get_menu(state
->ctrls
.scene_mode
->id
)[val
]);
312 return s5c73m3_isp_command(state
, COMM_SCENE_MODE
, scene_lookup
[val
]);
315 static int s5c73m3_set_power_line_freq(struct s5c73m3
*state
, int val
)
317 unsigned int pwr_line_freq
= COMM_FLICKER_NONE
;
320 case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED
:
321 pwr_line_freq
= COMM_FLICKER_NONE
;
323 case V4L2_CID_POWER_LINE_FREQUENCY_50HZ
:
324 pwr_line_freq
= COMM_FLICKER_AUTO_50HZ
;
326 case V4L2_CID_POWER_LINE_FREQUENCY_60HZ
:
327 pwr_line_freq
= COMM_FLICKER_AUTO_60HZ
;
330 case V4L2_CID_POWER_LINE_FREQUENCY_AUTO
:
331 pwr_line_freq
= COMM_FLICKER_NONE
;
334 return s5c73m3_isp_command(state
, COMM_FLICKER_MODE
, pwr_line_freq
);
337 static int s5c73m3_s_ctrl(struct v4l2_ctrl
*ctrl
)
339 struct v4l2_subdev
*sd
= ctrl_to_sensor_sd(ctrl
);
340 struct s5c73m3
*state
= sensor_sd_to_s5c73m3(sd
);
343 v4l2_dbg(1, s5c73m3_dbg
, sd
, "set_ctrl: %s, value: %d\n",
344 ctrl
->name
, ctrl
->val
);
346 mutex_lock(&state
->lock
);
348 * If the device is not powered up by the host driver do
349 * not apply any controls to H/W at this time. Instead
350 * the controls will be restored right after power-up.
352 if (state
->power
== 0)
355 if (ctrl
->flags
& V4L2_CTRL_FLAG_INACTIVE
) {
361 case V4L2_CID_3A_LOCK
:
362 ret
= s5c73m3_3a_lock(state
, ctrl
);
365 case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
:
366 ret
= s5c73m3_set_white_balance(state
, ctrl
->val
);
369 case V4L2_CID_CONTRAST
:
370 ret
= s5c73m3_set_contrast(state
, ctrl
->val
);
373 case V4L2_CID_COLORFX
:
374 ret
= s5c73m3_set_colorfx(state
, ctrl
->val
);
377 case V4L2_CID_EXPOSURE_AUTO
:
378 ret
= s5c73m3_set_exposure(state
, ctrl
->val
);
381 case V4L2_CID_FOCUS_AUTO
:
382 ret
= s5c73m3_set_auto_focus(state
, ctrl
->val
);
385 case V4L2_CID_IMAGE_STABILIZATION
:
386 ret
= s5c73m3_set_stabilization(state
, ctrl
->val
);
389 case V4L2_CID_ISO_SENSITIVITY
:
390 ret
= s5c73m3_set_iso(state
, ctrl
->val
);
393 case V4L2_CID_JPEG_COMPRESSION_QUALITY
:
394 ret
= s5c73m3_set_jpeg_quality(state
, ctrl
->val
);
397 case V4L2_CID_POWER_LINE_FREQUENCY
:
398 ret
= s5c73m3_set_power_line_freq(state
, ctrl
->val
);
401 case V4L2_CID_SATURATION
:
402 ret
= s5c73m3_set_saturation(state
, ctrl
->val
);
405 case V4L2_CID_SCENE_MODE
:
406 ret
= s5c73m3_set_scene_program(state
, ctrl
->val
);
409 case V4L2_CID_SHARPNESS
:
410 ret
= s5c73m3_set_sharpness(state
, ctrl
->val
);
413 case V4L2_CID_WIDE_DYNAMIC_RANGE
:
414 ret
= s5c73m3_isp_command(state
, COMM_WDR
, !!ctrl
->val
);
417 case V4L2_CID_ZOOM_ABSOLUTE
:
418 ret
= s5c73m3_isp_command(state
, COMM_ZOOM_STEP
, ctrl
->val
);
422 mutex_unlock(&state
->lock
);
426 static const struct v4l2_ctrl_ops s5c73m3_ctrl_ops
= {
427 .g_volatile_ctrl
= s5c73m3_g_volatile_ctrl
,
428 .s_ctrl
= s5c73m3_s_ctrl
,
431 /* Supported manual ISO values */
432 static const s64 iso_qmenu
[] = {
433 /* COMM_ISO: 0x0001...0x0004 */
437 /* Supported exposure bias values (-2.0EV...+2.0EV) */
438 static const s64 ev_bias_qmenu
[] = {
439 /* COMM_EV: 0x0000...0x0008 */
440 -2000, -1500, -1000, -500, 0, 500, 1000, 1500, 2000
443 int s5c73m3_init_controls(struct s5c73m3
*state
)
445 const struct v4l2_ctrl_ops
*ops
= &s5c73m3_ctrl_ops
;
446 struct s5c73m3_ctrls
*ctrls
= &state
->ctrls
;
447 struct v4l2_ctrl_handler
*hdl
= &ctrls
->handler
;
449 int ret
= v4l2_ctrl_handler_init(hdl
, 22);
454 ctrls
->auto_wb
= v4l2_ctrl_new_std_menu(hdl
, ops
,
455 V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
,
456 9, ~0x15e, V4L2_WHITE_BALANCE_AUTO
);
458 /* Exposure (only automatic exposure) */
459 ctrls
->auto_exposure
= v4l2_ctrl_new_std_menu(hdl
, ops
,
460 V4L2_CID_EXPOSURE_AUTO
, 0, ~0x01, V4L2_EXPOSURE_AUTO
);
462 ctrls
->exposure_bias
= v4l2_ctrl_new_int_menu(hdl
, ops
,
463 V4L2_CID_AUTO_EXPOSURE_BIAS
,
464 ARRAY_SIZE(ev_bias_qmenu
) - 1,
465 ARRAY_SIZE(ev_bias_qmenu
)/2 - 1,
468 ctrls
->exposure_metering
= v4l2_ctrl_new_std_menu(hdl
, ops
,
469 V4L2_CID_EXPOSURE_METERING
,
470 2, ~0x7, V4L2_EXPOSURE_METERING_AVERAGE
);
473 ctrls
->focus_auto
= v4l2_ctrl_new_std(hdl
, ops
,
474 V4L2_CID_FOCUS_AUTO
, 0, 1, 1, 0);
476 ctrls
->af_start
= v4l2_ctrl_new_std(hdl
, ops
,
477 V4L2_CID_AUTO_FOCUS_START
, 0, 1, 1, 0);
479 ctrls
->af_stop
= v4l2_ctrl_new_std(hdl
, ops
,
480 V4L2_CID_AUTO_FOCUS_STOP
, 0, 1, 1, 0);
482 ctrls
->af_status
= v4l2_ctrl_new_std(hdl
, ops
,
483 V4L2_CID_AUTO_FOCUS_STATUS
, 0,
484 (V4L2_AUTO_FOCUS_STATUS_BUSY
|
485 V4L2_AUTO_FOCUS_STATUS_REACHED
|
486 V4L2_AUTO_FOCUS_STATUS_FAILED
),
487 0, V4L2_AUTO_FOCUS_STATUS_IDLE
);
489 ctrls
->af_distance
= v4l2_ctrl_new_std_menu(hdl
, ops
,
490 V4L2_CID_AUTO_FOCUS_RANGE
,
491 V4L2_AUTO_FOCUS_RANGE_MACRO
,
492 ~(1 << V4L2_AUTO_FOCUS_RANGE_NORMAL
|
493 1 << V4L2_AUTO_FOCUS_RANGE_MACRO
),
494 V4L2_AUTO_FOCUS_RANGE_NORMAL
);
495 /* ISO sensitivity */
496 ctrls
->auto_iso
= v4l2_ctrl_new_std_menu(hdl
, ops
,
497 V4L2_CID_ISO_SENSITIVITY_AUTO
, 1, 0,
498 V4L2_ISO_SENSITIVITY_AUTO
);
500 ctrls
->iso
= v4l2_ctrl_new_int_menu(hdl
, ops
,
501 V4L2_CID_ISO_SENSITIVITY
, ARRAY_SIZE(iso_qmenu
) - 1,
502 ARRAY_SIZE(iso_qmenu
)/2 - 1, iso_qmenu
);
504 ctrls
->contrast
= v4l2_ctrl_new_std(hdl
, ops
,
505 V4L2_CID_CONTRAST
, -2, 2, 1, 0);
507 ctrls
->saturation
= v4l2_ctrl_new_std(hdl
, ops
,
508 V4L2_CID_SATURATION
, -2, 2, 1, 0);
510 ctrls
->sharpness
= v4l2_ctrl_new_std(hdl
, ops
,
511 V4L2_CID_SHARPNESS
, -2, 2, 1, 0);
513 ctrls
->zoom
= v4l2_ctrl_new_std(hdl
, ops
,
514 V4L2_CID_ZOOM_ABSOLUTE
, 0, 30, 1, 0);
516 ctrls
->colorfx
= v4l2_ctrl_new_std_menu(hdl
, ops
, V4L2_CID_COLORFX
,
517 V4L2_COLORFX_AQUA
, ~0x40f, V4L2_COLORFX_NONE
);
519 ctrls
->wdr
= v4l2_ctrl_new_std(hdl
, ops
,
520 V4L2_CID_WIDE_DYNAMIC_RANGE
, 0, 1, 1, 0);
522 ctrls
->stabilization
= v4l2_ctrl_new_std(hdl
, ops
,
523 V4L2_CID_IMAGE_STABILIZATION
, 0, 1, 1, 0);
525 v4l2_ctrl_new_std_menu(hdl
, ops
, V4L2_CID_POWER_LINE_FREQUENCY
,
526 V4L2_CID_POWER_LINE_FREQUENCY_AUTO
, 0,
527 V4L2_CID_POWER_LINE_FREQUENCY_AUTO
);
529 ctrls
->jpeg_quality
= v4l2_ctrl_new_std(hdl
, ops
,
530 V4L2_CID_JPEG_COMPRESSION_QUALITY
, 1, 100, 1, 80);
532 ctrls
->scene_mode
= v4l2_ctrl_new_std_menu(hdl
, ops
,
533 V4L2_CID_SCENE_MODE
, V4L2_SCENE_MODE_TEXT
, ~0x3fff,
534 V4L2_SCENE_MODE_NONE
);
536 ctrls
->aaa_lock
= v4l2_ctrl_new_std(hdl
, ops
,
537 V4L2_CID_3A_LOCK
, 0, 0x7, 0, 0);
541 v4l2_ctrl_handler_free(hdl
);
545 v4l2_ctrl_auto_cluster(3, &ctrls
->auto_exposure
, 0, false);
546 ctrls
->auto_iso
->flags
|= V4L2_CTRL_FLAG_VOLATILE
|
547 V4L2_CTRL_FLAG_UPDATE
;
548 v4l2_ctrl_auto_cluster(2, &ctrls
->auto_iso
, 0, false);
549 ctrls
->af_status
->flags
|= V4L2_CTRL_FLAG_VOLATILE
;
550 v4l2_ctrl_cluster(6, &ctrls
->focus_auto
);
552 state
->sensor_sd
.ctrl_handler
= hdl
;