19 #include <linux/ctype.h>
23 #include <linux/i2c.h>
24 #include <linux/module.h>
26 #include <linux/slab.h>
27 #include <asm/unaligned.h>
39 #define S5K4ECGX_DRIVER_NAME "s5k4ecgx"
40 #define S5K4ECGX_FIRMWARE "s5k4ecgx.bin"
43 #define REG_FW_REVISION 0x700001a6
44 #define REG_FW_VERSION 0x700001a4
45 #define S5K4ECGX_REVISION_1_1 0x11
46 #define S5K4ECGX_FW_VERSION 0x4ec0
49 #define REG_USER_BRIGHTNESS 0x7000022c
50 #define REG_USER_CONTRAST 0x7000022e
51 #define REG_USER_SATURATION 0x70000230
53 #define REG_G_ENABLE_PREV 0x7000023e
54 #define REG_G_ENABLE_PREV_CHG 0x70000240
55 #define REG_G_NEW_CFG_SYNC 0x7000024a
56 #define REG_G_PREV_IN_WIDTH 0x70000250
57 #define REG_G_PREV_IN_HEIGHT 0x70000252
58 #define REG_G_PREV_IN_XOFFS 0x70000254
59 #define REG_G_PREV_IN_YOFFS 0x70000256
60 #define REG_G_CAP_IN_WIDTH 0x70000258
61 #define REG_G_CAP_IN_HEIGHT 0x7000025a
62 #define REG_G_CAP_IN_XOFFS 0x7000025c
63 #define REG_G_CAP_IN_YOFFS 0x7000025e
64 #define REG_G_INPUTS_CHANGE_REQ 0x70000262
65 #define REG_G_ACTIVE_PREV_CFG 0x70000266
66 #define REG_G_PREV_CFG_CHG 0x70000268
67 #define REG_G_PREV_OPEN_AFTER_CH 0x7000026a
70 #define PREG(n, x) ((n) * 0x30 + (x))
71 #define REG_P_OUT_WIDTH(n) PREG(n, 0x700002a6)
72 #define REG_P_OUT_HEIGHT(n) PREG(n, 0x700002a8)
73 #define REG_P_FMT(n) PREG(n, 0x700002aa)
74 #define REG_P_PVI_MASK(n) PREG(n, 0x700002b4)
75 #define REG_P_FR_TIME_TYPE(n) PREG(n, 0x700002be)
76 #define FR_TIME_DYNAMIC 0
77 #define FR_TIME_FIXED 1
78 #define FR_TIME_FIXED_ACCURATE 2
79 #define REG_P_FR_TIME_Q_TYPE(n) PREG(n, 0x700002c0)
80 #define FR_TIME_Q_DYNAMIC 0
81 #define FR_TIME_Q_BEST_FRRATE 1
82 #define FR_TIME_Q_BEST_QUALITY 2
85 #define REG_P_MAX_FR_TIME(n) PREG(n, 0x700002c2)
86 #define REG_P_MIN_FR_TIME(n) PREG(n, 0x700002c4)
87 #define US_TO_FR_TIME(__t) ((__t) / 100)
88 #define REG_P_PREV_MIRROR(n) PREG(n, 0x700002d0)
89 #define REG_P_CAP_MIRROR(n) PREG(n, 0x700002d2)
91 #define REG_G_PREVZOOM_IN_WIDTH 0x70000494
92 #define REG_G_PREVZOOM_IN_HEIGHT 0x70000496
93 #define REG_G_PREVZOOM_IN_XOFFS 0x70000498
94 #define REG_G_PREVZOOM_IN_YOFFS 0x7000049a
95 #define REG_G_CAPZOOM_IN_WIDTH 0x7000049c
96 #define REG_G_CAPZOOM_IN_HEIGHT 0x7000049e
97 #define REG_G_CAPZOOM_IN_XOFFS 0x700004a0
98 #define REG_G_CAPZOOM_IN_YOFFS 0x700004a2
101 #define REG_USER_SHARPNESS(n) (0x70000a28 + (n) * 0xb6)
104 #define SHARPNESS_DIV 8208
105 #define TOK_TERM 0xffffffff
112 #define AHB_MSB_ADDR_PTR 0xfcfc
113 #define GEN_REG_OFFSH 0xd000
114 #define REG_CMDWR_ADDRH 0x0028
115 #define REG_CMDWR_ADDRL 0x002a
116 #define REG_CMDRD_ADDRH 0x002c
117 #define REG_CMDRD_ADDRL 0x002e
118 #define REG_CMDBUF0_ADDR 0x0f12
137 .size = { 176, 144 },
138 .input_window = { 0x00, 0x00, 0x928, 0x780 },
140 .size = { 352, 288 },
141 .input_window = { 0x00, 0x00, 0x928, 0x780 },
143 .size = { 640, 480 },
144 .input_window = { 0x00, 0x00, 0xa00, 0x780 },
146 .size = { 720, 480 },
147 .input_window = { 0x00, 0x00, 0xa00, 0x6a8 },
151 #define S5K4ECGX_NUM_PREV ARRAY_SIZE(s5k4ecgx_prev_sizes)
165 static const char *
const s5k4ecgx_supply_names[] = {
176 #define S5K4ECGX_NUM_SUPPLIES ARRAY_SIZE(s5k4ecgx_supply_names)
207 u8 wbuf[2] = { addr >> 8, addr & 0xff };
225 v4l2_dbg(4,
debug, client,
"i2c_read: 0x%04X : 0x%04x\n", addr, *val);
227 return ret == 2 ? 0 :
ret;
232 u8 buf[4] = { addr >> 8, addr & 0xff, val >> 8, val & 0xff };
235 v4l2_dbg(4,
debug, client,
"i2c_write: 0x%04x : 0x%04x\n", addr, val);
237 return ret == 4 ? 0 :
ret;
245 v4l2_dbg(3,
debug, client,
"write: 0x%08x : 0x%04x\n", addr, val);
258 u16 high = addr >> 16, low = addr & 0xffff;
267 dev_err(&client->
dev,
"Failed to execute read command\n");
274 struct i2c_client *client = v4l2_get_subdevdata(sd);
275 u16 hw_rev, fw_ver = 0;
280 v4l2_err(sd,
"FW version check failed!\n");
288 v4l2_info(sd,
"chip found FW ver: 0x%x, HW rev: 0x%x\n",
293 static int s5k4ecgx_set_ahb_address(
struct v4l2_subdev *sd)
295 struct i2c_client *client = v4l2_get_subdevdata(sd);
307 ret = s5k4ecgx_i2c_write(client, 0x0010, 0x0001);
311 ret = s5k4ecgx_i2c_write(client, 0x1030, 0x0000);
315 return s5k4ecgx_i2c_write(client, 0x0014, 0x0001);
318 #define FW_CRC_SIZE 4
320 #define FW_RECORD_SIZE 6
330 static int s5k4ecgx_load_firmware(
struct v4l2_subdev *sd)
332 struct i2c_client *client = v4l2_get_subdevdata(sd);
335 int err,
i, regs_num;
356 crc =
crc32_le(~0, fw->
data, regs_num * FW_RECORD_SIZE);
357 if (crc != crc_file) {
358 v4l2_err(sd,
"FW: invalid crc (%#x:%#x)\n", crc, crc_file);
363 for (i = 1; i < regs_num; i++) {
368 if (addr - addr_inc != 2)
369 err = s5k4ecgx_write(client, addr, val);
382 static int s5k4ecgx_set_input_window(
struct i2c_client *
c,
407 static int s5k4ecgx_set_zoom_window(
struct i2c_client *c,
431 static int s5k4ecgx_set_output_framefmt(
struct s5k4ecgx *
priv)
433 struct i2c_client *client = v4l2_get_subdevdata(&priv->
sd);
442 ret = s5k4ecgx_write(client,
REG_P_FMT(0),
447 static int s5k4ecgx_init_sensor(
struct v4l2_subdev *sd)
451 ret = s5k4ecgx_set_ahb_address(sd);
457 ret = s5k4ecgx_load_firmware(sd);
459 v4l2_err(sd,
"Failed to write initial settings\n");
464 static int s5k4ecgx_gpio_set_value(
struct s5k4ecgx *priv,
int id,
u32 val)
466 if (!gpio_is_valid(priv->
gpio[
id].gpio))
473 static int __s5k4ecgx_power_on(
struct s5k4ecgx *priv)
483 if (s5k4ecgx_gpio_set_value(priv,
STBY, priv->
gpio[
STBY].level))
486 if (s5k4ecgx_gpio_set_value(priv,
RST, priv->
gpio[
RST].level))
492 static int __s5k4ecgx_power_off(
struct s5k4ecgx *priv)
494 if (s5k4ecgx_gpio_set_value(priv,
RST, !priv->
gpio[
RST].level))
497 if (s5k4ecgx_gpio_set_value(priv,
STBY, !priv->
gpio[
STBY].level))
506 static int s5k4ecgx_try_frame_size(
struct v4l2_mbus_framefmt *mf,
509 unsigned int min_err = ~0;
516 +
abs(fsize->
size.height - mf->height);
524 mf->width = match->
size.width;
525 mf->height = match->size.height;
534 static int s5k4ecgx_enum_mbus_code(
struct v4l2_subdev *sd,
536 struct v4l2_subdev_mbus_code_enum *
code)
538 if (code->index >=
ARRAY_SIZE(s5k4ecgx_formats))
540 code->code = s5k4ecgx_formats[code->index].
code;
548 struct s5k4ecgx *priv = to_s5k4ecgx(sd);
549 struct v4l2_mbus_framefmt *mf;
553 mf = v4l2_subdev_get_try_format(fh, 0);
573 struct v4l2_mbus_framefmt *mf)
578 if (mf->code == s5k4ecgx_formats[i].
code)
580 mf->code = s5k4ecgx_formats[
i].
code;
582 return &s5k4ecgx_formats[
i];
588 struct s5k4ecgx *priv = to_s5k4ecgx(sd);
591 struct v4l2_mbus_framefmt *mf;
594 pf = s5k4ecgx_try_fmt(sd, &fmt->
format);
595 s5k4ecgx_try_frame_size(&fmt->
format, &fsize);
600 mf = v4l2_subdev_get_try_format(fh, 0);
620 .enum_mbus_code = s5k4ecgx_enum_mbus_code,
621 .get_fmt = s5k4ecgx_get_fmt,
622 .set_fmt = s5k4ecgx_set_fmt,
632 struct i2c_client *client = v4l2_get_subdevdata(sd);
633 struct s5k4ecgx *priv = to_s5k4ecgx(sd);
651 for (i = 0; i < 4 && !
err; i++)
662 v4l2_err(sd,
"Failed to write s_ctrl err %d\n", err);
668 .s_ctrl = s5k4ecgx_s_ctrl,
674 static int s5k4ecgx_registered(
struct v4l2_subdev *sd)
677 struct s5k4ecgx *priv = to_s5k4ecgx(sd);
680 ret = __s5k4ecgx_power_on(priv);
682 ret = s5k4ecgx_read_fw_ver(sd);
683 __s5k4ecgx_power_off(priv);
695 struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(fh, 0);
697 mf->width = s5k4ecgx_prev_sizes[0].
size.width;
698 mf->height = s5k4ecgx_prev_sizes[0].
size.height;
699 mf->code = s5k4ecgx_formats[0].
code;
707 .registered = s5k4ecgx_registered,
708 .open = s5k4ecgx_open,
711 static int s5k4ecgx_s_power(
struct v4l2_subdev *sd,
int on)
713 struct s5k4ecgx *priv = to_s5k4ecgx(sd);
719 ret = __s5k4ecgx_power_on(priv);
724 ret = s5k4ecgx_init_sensor(sd);
726 __s5k4ecgx_power_off(priv);
730 ret = __s5k4ecgx_power_off(priv);
736 static int s5k4ecgx_log_status(
struct v4l2_subdev *sd)
744 .s_power = s5k4ecgx_s_power,
745 .log_status = s5k4ecgx_log_status,
748 static int __s5k4ecgx_s_params(
struct s5k4ecgx *priv)
750 struct i2c_client *client = v4l2_get_subdevdata(&priv->
sd);
754 ret = s5k4ecgx_set_input_window(client, crop_rect);
756 ret = s5k4ecgx_set_zoom_window(client, crop_rect);
760 ret = s5k4ecgx_write(client, 0x70000a1e, 0x28);
762 ret = s5k4ecgx_write(client, 0x70000ad4, 0x3c);
764 ret = s5k4ecgx_set_output_framefmt(priv);
795 static int __s5k4ecgx_s_stream(
struct s5k4ecgx *priv,
int on)
797 struct i2c_client *client = v4l2_get_subdevdata(&priv->
sd);
801 ret = __s5k4ecgx_s_params(priv);
816 static int s5k4ecgx_s_stream(
struct v4l2_subdev *sd,
int on)
818 struct s5k4ecgx *priv = to_s5k4ecgx(sd);
821 v4l2_dbg(1,
debug, sd,
"Turn streaming %s\n", on ?
"on" :
"off");
826 ret = __s5k4ecgx_s_stream(priv, on);
836 .s_stream = s5k4ecgx_s_stream,
840 .core = &s5k4ecgx_core_ops,
841 .pad = &s5k4ecgx_pad_ops,
842 .video = &s5k4ecgx_video_ops,
848 static int s5k4ecgx_config_gpio(
int nr,
int val,
const char *
name)
853 if (!gpio_is_valid(nr))
862 static void s5k4ecgx_free_gpios(
struct s5k4ecgx *priv)
867 if (!gpio_is_valid(priv->
gpio[i].gpio))
874 static int s5k4ecgx_config_gpios(
struct s5k4ecgx *priv,
883 ret = s5k4ecgx_config_gpio(gpio->
gpio, gpio->
level,
"S5K4ECGX_STBY");
886 s5k4ecgx_free_gpios(priv);
890 if (gpio_is_valid(gpio->
gpio))
895 ret = s5k4ecgx_config_gpio(gpio->
gpio, gpio->
level,
"S5K4ECGX_RST");
897 s5k4ecgx_free_gpios(priv);
901 if (gpio_is_valid(gpio->
gpio))
907 static int s5k4ecgx_init_v4l2_ctrls(
struct s5k4ecgx *priv)
929 priv->
sd.ctrl_handler = hdl;
934 static int s5k4ecgx_probe(
struct i2c_client *client,
943 dev_err(&client->
dev,
"platform data is missing!\n");
969 ret = s5k4ecgx_config_gpios(priv, pdata);
971 dev_err(&client->
dev,
"Failed to set gpios\n");
975 priv->
supplies[i].supply = s5k4ecgx_supply_names[i];
980 dev_err(&client->
dev,
"Failed to get regulators\n");
983 ret = s5k4ecgx_init_v4l2_ctrls(priv);
993 s5k4ecgx_free_gpios(priv);
1000 static int s5k4ecgx_remove(
struct i2c_client *client)
1002 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1003 struct s5k4ecgx *priv = to_s5k4ecgx(sd);
1006 s5k4ecgx_free_gpios(priv);
1025 .probe = s5k4ecgx_probe,
1026 .remove = s5k4ecgx_remove,
1027 .id_table = s5k4ecgx_id,