20 #include <linux/i2c.h>
22 #include <linux/module.h>
24 #include <linux/slab.h>
36 #define DRIVER_NAME "S5K6AA"
39 #define S5K6AA_TERM 0xffff
40 #define S5K6AA_OUT_WIDTH_DEF 640
41 #define S5K6AA_OUT_HEIGHT_DEF 480
42 #define S5K6AA_WIN_WIDTH_MAX 1280
43 #define S5K6AA_WIN_HEIGHT_MAX 1024
44 #define S5K6AA_WIN_WIDTH_MIN 8
45 #define S5K6AA_WIN_HEIGHT_MIN 8
50 #define AHB_MSB_ADDR_PTR 0xfcfc
51 #define GEN_REG_OFFSH 0xd000
52 #define REG_CMDWR_ADDRH 0x0028
53 #define REG_CMDWR_ADDRL 0x002a
54 #define REG_CMDRD_ADDRH 0x002c
55 #define REG_CMDRD_ADDRL 0x002e
56 #define REG_CMDBUF0_ADDR 0x0f12
57 #define REG_CMDBUF1_ADDR 0x0f10
64 #define HOST_SWIF_OFFSH 0x7000
68 #define REG_I_INCLK_FREQ_L 0x01b8
69 #define REG_I_INCLK_FREQ_H 0x01ba
70 #define MIN_MCLK_FREQ_KHZ 6000U
71 #define MAX_MCLK_FREQ_KHZ 27000U
72 #define REG_I_USE_NPVI_CLOCKS 0x01c6
73 #define REG_I_USE_NMIPI_CLOCKS 0x01c8
76 #define REG_I_OPCLK_4KHZ(n) ((n) * 6 + 0x01cc)
77 #define REG_I_MIN_OUTRATE_4KHZ(n) ((n) * 6 + 0x01ce)
78 #define REG_I_MAX_OUTRATE_4KHZ(n) ((n) * 6 + 0x01d0)
79 #define SYS_PLL_OUT_FREQ (48000000 / 4000)
80 #define PCLK_FREQ_MIN (24000000 / 4000)
81 #define PCLK_FREQ_MAX (48000000 / 4000)
82 #define REG_I_INIT_PARAMS_UPDATED 0x01e0
83 #define REG_I_ERROR_INFO 0x01e2
86 #define REG_USER_BRIGHTNESS 0x01e4
87 #define REG_USER_CONTRAST 0x01e6
88 #define REG_USER_SATURATION 0x01e8
89 #define REG_USER_SHARPBLUR 0x01ea
91 #define REG_G_SPEC_EFFECTS 0x01ee
92 #define REG_G_ENABLE_PREV 0x01f0
93 #define REG_G_ENABLE_PREV_CHG 0x01f2
94 #define REG_G_NEW_CFG_SYNC 0x01f8
95 #define REG_G_PREVZOOM_IN_WIDTH 0x020a
96 #define REG_G_PREVZOOM_IN_HEIGHT 0x020c
97 #define REG_G_PREVZOOM_IN_XOFFS 0x020e
98 #define REG_G_PREVZOOM_IN_YOFFS 0x0210
99 #define REG_G_INPUTS_CHANGE_REQ 0x021a
100 #define REG_G_ACTIVE_PREV_CFG 0x021c
101 #define REG_G_PREV_CFG_CHG 0x021e
102 #define REG_G_PREV_OPEN_AFTER_CH 0x0220
103 #define REG_G_PREV_CFG_ERROR 0x0222
106 #define PREG(n, x) ((n) * 0x26 + x)
107 #define REG_P_OUT_WIDTH(n) PREG(n, 0x0242)
108 #define REG_P_OUT_HEIGHT(n) PREG(n, 0x0244)
109 #define REG_P_FMT(n) PREG(n, 0x0246)
110 #define REG_P_MAX_OUT_RATE(n) PREG(n, 0x0248)
111 #define REG_P_MIN_OUT_RATE(n) PREG(n, 0x024a)
112 #define REG_P_PVI_MASK(n) PREG(n, 0x024c)
113 #define REG_P_CLK_INDEX(n) PREG(n, 0x024e)
114 #define REG_P_FR_RATE_TYPE(n) PREG(n, 0x0250)
115 #define FR_RATE_DYNAMIC 0
116 #define FR_RATE_FIXED 1
117 #define FR_RATE_FIXED_ACCURATE 2
118 #define REG_P_FR_RATE_Q_TYPE(n) PREG(n, 0x0252)
119 #define FR_RATE_Q_BEST_FRRATE 1
120 #define FR_RATE_Q_BEST_QUALITY 2
122 #define REG_P_MAX_FR_TIME(n) PREG(n, 0x0254)
123 #define REG_P_MIN_FR_TIME(n) PREG(n, 0x0256)
125 #define US_TO_FR_TIME(__t) ((__t) / 100)
126 #define S5K6AA_MIN_FR_TIME 33300
127 #define S5K6AA_MAX_FR_TIME 650000
128 #define S5K6AA_MAX_HIGHRES_FR_TIME 666
130 #define REG_P_COLORTEMP(n) PREG(n, 0x025e)
131 #define REG_P_PREV_MIRROR(n) PREG(n, 0x0262)
135 #define REG_SF_USR_EXPOSURE_L 0x03c6
136 #define REG_SF_USR_EXPOSURE_H 0x03c8
137 #define REG_SF_USR_EXPOSURE_CHG 0x03ca
138 #define REG_SF_USR_TOT_GAIN 0x03cc
139 #define REG_SF_USR_TOT_GAIN_CHG 0x03ce
140 #define REG_SF_RGAIN 0x03d0
141 #define REG_SF_RGAIN_CHG 0x03d2
142 #define REG_SF_GGAIN 0x03d4
143 #define REG_SF_GGAIN_CHG 0x03d6
144 #define REG_SF_BGAIN 0x03d8
145 #define REG_SF_BGAIN_CHG 0x03da
146 #define REG_SF_FLICKER_QUANT 0x03dc
147 #define REG_SF_FLICKER_QUANT_CHG 0x03de
150 #define REG_OIF_EN_MIPI_LANES 0x03fa
151 #define REG_OIF_EN_PACKETS 0x03fc
152 #define REG_OIF_CFG_CHG 0x03fe
155 #define REG_DBG_AUTOALG_EN 0x0400
156 #define AALG_ALL_EN_MASK (1 << 0)
157 #define AALG_AE_EN_MASK (1 << 1)
158 #define AALG_DIVLEI_EN_MASK (1 << 2)
159 #define AALG_WB_EN_MASK (1 << 3)
160 #define AALG_FLICKER_EN_MASK (1 << 5)
161 #define AALG_FIT_EN_MASK (1 << 6)
162 #define AALG_WRHW_EN_MASK (1 << 7)
165 #define REG_FW_APIVER 0x012e
166 #define S5K6AAFX_FW_APIVER 0x0001
167 #define REG_FW_REVISION 0x0130
170 #define S5K6AA_MAX_PRESETS 1
172 static const char *
const s5k6aa_supply_names[] = {
180 #define S5K6AA_NUM_SUPPLIES ARRAY_SIZE(s5k6aa_supply_names)
271 { 0x112a, 0x0000 }, { 0x1132, 0x0000 },
272 { 0x113e, 0x0000 }, { 0x115c, 0x0000 },
273 { 0x1164, 0x0000 }, { 0x1174, 0x0000 },
274 { 0x1178, 0x0000 }, { 0x077a, 0x0000 },
275 { 0x077c, 0x0000 }, { 0x077e, 0x0000 },
276 { 0x0780, 0x0000 }, { 0x0782, 0x0000 },
277 { 0x0784, 0x0000 }, { 0x0786, 0x0000 },
278 { 0x0788, 0x0000 }, { 0x07a2, 0x0000 },
279 { 0x07a4, 0x0000 }, { 0x07a6, 0x0000 },
280 { 0x07a8, 0x0000 }, { 0x07b6, 0x0000 },
281 { 0x07b8, 0x0002 }, { 0x07ba, 0x0004 },
282 { 0x07bc, 0x0004 }, { 0x07be, 0x0005 },
295 { 1000, {10000, 1000000}, {1280, 1024} },
296 { 666, {15000, 1000000}, {1280, 1024} },
297 { 500, {20000, 1000000}, {1280, 720} },
298 { 400, {25000, 1000000}, {640, 480} },
299 { 333, {33300, 1000000}, {640, 480} },
302 #define S5K6AA_INTERVAL_DEF_INDEX 1
315 static void s5k6aa_presets_data_init(
struct s5k6aa *
s5k6aa)
335 u8 wbuf[2] = {addr >> 8, addr & 0xFF};
353 v4l2_dbg(3,
debug, client,
"i2c_read: 0x%04X : 0x%04x\n", addr, *val);
355 return ret == 2 ? 0 :
ret;
360 u8 buf[4] = {addr >> 8, addr & 0xFF, val >> 8, val & 0xFF};
363 v4l2_dbg(3,
debug, client,
"i2c_write: 0x%04X : 0x%04x\n", addr, val);
365 return ret == 4 ? 0 :
ret;
389 struct i2c_client *client = v4l2_get_subdevdata(sd);
403 addr_incr = (msg + 1)->addr - msg->
addr;
411 static int s5k6aa_set_ahb_address(
struct i2c_client *client)
428 static int s5k6aa_configure_pixel_clocks(
struct s5k6aa *s5k6aa)
430 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->
sd);
436 "Invalid clock frequency: %ld\n", fmclk))
463 return ret ? ret : (status ? -
EINVAL : 0);
467 static int s5k6aa_set_mirror(
struct s5k6aa *s5k6aa,
int horiz_flip)
469 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->
sd);
472 unsigned int vflip = s5k6aa->
ctrls.vflip->val ^ s5k6aa->
inv_vflip;
473 unsigned int flip = (horiz_flip ^ s5k6aa->
inv_hflip) | (vflip << 1);
479 static int s5k6aa_set_awb(
struct s5k6aa *s5k6aa,
int awb)
481 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->
sd);
515 unsigned int time = exposure / 10;
525 static int s5k6aa_set_user_gain(
struct i2c_client *client,
int gain)
534 static int s5k6aa_set_auto_exposure(
struct s5k6aa *s5k6aa,
int value)
536 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->
sd);
537 unsigned int exp_time = s5k6aa->
ctrls.exposure->val;
544 v4l2_dbg(1,
debug, c,
"man_exp: %d, auto_exp: %d, a_alg: 0x%x\n",
545 exp_time, value, auto_alg);
550 ret = s5k6aa_set_user_exposure(c, exp_time);
553 ret = s5k6aa_set_user_gain(c, s5k6aa->
ctrls.gain->val);
562 static int s5k6aa_set_anti_flicker(
struct s5k6aa *s5k6aa,
int value)
564 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->
sd);
589 static int s5k6aa_set_colorfx(
struct s5k6aa *s5k6aa,
int val)
591 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->
sd);
603 if (colorfx[i].
id == val)
610 static int s5k6aa_preview_config_status(
struct i2c_client *client)
615 v4l2_dbg(1,
debug, client,
"error: 0x%x (%d)\n", error, ret);
616 return ret ? ret : (error ? -
EINVAL : 0);
619 static int s5k6aa_get_pixfmt_index(
struct s5k6aa *s5k6aa,
620 struct v4l2_mbus_framefmt *mf)
624 for (i = 0; i <
ARRAY_SIZE(s5k6aa_formats); i++)
625 if (mf->colorspace == s5k6aa_formats[i].
colorspace &&
626 mf->code == s5k6aa_formats[i].
code)
631 static int s5k6aa_set_output_framefmt(
struct s5k6aa *s5k6aa,
634 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->
sd);
635 int fmt_index = s5k6aa_get_pixfmt_index(s5k6aa, &preset->
mbus_fmt);
649 static int s5k6aa_set_input_params(
struct s5k6aa *s5k6aa)
651 struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->
sd);
677 static int s5k6aa_configure_video_bus(
struct s5k6aa *s5k6aa,
680 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->
sd);
701 static int s5k6aa_new_config_sync(
struct i2c_client *client,
int timeout,
731 static int s5k6aa_set_prev_config(
struct s5k6aa *s5k6aa,
734 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->
sd);
744 ret = s5k6aa_set_output_framefmt(s5k6aa, preset);
762 s5k6aa->
fiv->reg_fr_time + 33);
765 s5k6aa->
fiv->reg_fr_time - 33);
767 ret = s5k6aa_new_config_sync(client, 250, idx);
769 ret = s5k6aa_preview_config_status(client);
773 v4l2_dbg(1,
debug, client,
"Frame interval: %d +/- 3.3ms. (%d)\n",
774 s5k6aa->
fiv->reg_fr_time, ret);
786 static int s5k6aa_initialize_isp(
struct v4l2_subdev *sd)
788 struct i2c_client *client = v4l2_get_subdevdata(sd);
789 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
796 ret = s5k6aa_set_ahb_address(client);
799 ret = s5k6aa_configure_video_bus(s5k6aa, s5k6aa->
bus_type,
803 ret = s5k6aa_write_array(sd, s5k6aa_analog_config);
808 return s5k6aa_configure_pixel_clocks(s5k6aa);
811 static int s5k6aa_gpio_set_value(
struct s5k6aa *
priv,
int id,
u32 val)
813 if (!gpio_is_valid(priv->
gpio[
id].gpio))
819 static int s5k6aa_gpio_assert(
struct s5k6aa *priv,
int id)
821 return s5k6aa_gpio_set_value(priv,
id, priv->
gpio[
id].level);
824 static int s5k6aa_gpio_deassert(
struct s5k6aa *priv,
int id)
826 return s5k6aa_gpio_set_value(priv,
id, !priv->
gpio[
id].level);
829 static int __s5k6aa_power_on(
struct s5k6aa *s5k6aa)
836 if (s5k6aa_gpio_deassert(s5k6aa,
STBY))
843 if (s5k6aa_gpio_deassert(s5k6aa,
RST))
849 static int __s5k6aa_power_off(
struct s5k6aa *s5k6aa)
853 if (s5k6aa_gpio_assert(s5k6aa,
RST))
861 if (s5k6aa_gpio_assert(s5k6aa,
STBY))
871 static int s5k6aa_set_power(
struct v4l2_subdev *sd,
int on)
873 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
878 if (!on == s5k6aa->
power) {
880 ret = __s5k6aa_power_on(s5k6aa);
882 ret = s5k6aa_initialize_isp(sd);
884 ret = __s5k6aa_power_off(s5k6aa);
888 s5k6aa->
power += on ? 1 : -1;
893 if (!on || ret || s5k6aa->
power != 1)
899 static int __s5k6aa_stream(
struct s5k6aa *s5k6aa,
int enable)
901 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->
sd);
913 static int s5k6aa_s_stream(
struct v4l2_subdev *sd,
int on)
915 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
922 ret = s5k6aa_set_prev_config(s5k6aa, s5k6aa->
preset);
924 ret = s5k6aa_set_input_params(s5k6aa);
926 ret = __s5k6aa_stream(s5k6aa, !!on);
933 static int s5k6aa_g_frame_interval(
struct v4l2_subdev *sd,
934 struct v4l2_subdev_frame_interval *fi)
936 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
939 fi->interval = s5k6aa->
fiv->interval;
945 static int __s5k6aa_set_frame_interval(
struct s5k6aa *s5k6aa,
946 struct v4l2_subdev_frame_interval *fi)
948 struct v4l2_mbus_framefmt *mbus_fmt = &s5k6aa->
preset->mbus_fmt;
951 unsigned int i, fr_time;
953 if (fi->interval.denominator == 0)
956 fr_time = fi->interval.numerator * 10000 / fi->interval.denominator;
958 for (i = 0; i <
ARRAY_SIZE(s5k6aa_intervals); i++) {
961 if (mbus_fmt->width > iv->
size.width ||
962 mbus_fmt->height > iv->
size.height)
978 static int s5k6aa_s_frame_interval(
struct v4l2_subdev *sd,
979 struct v4l2_subdev_frame_interval *fi)
981 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
985 fi->interval.numerator, fi->interval.denominator);
988 ret = __s5k6aa_set_frame_interval(s5k6aa, fi);
998 static int s5k6aa_enum_frame_interval(
struct v4l2_subdev *sd,
1000 struct v4l2_subdev_frame_interval_enum *fie)
1002 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1006 if (fie->index >
ARRAY_SIZE(s5k6aa_intervals))
1015 fi = &s5k6aa_intervals[fie->index];
1016 if (fie->width > fi->
size.width || fie->height > fi->
size.height)
1025 static int s5k6aa_enum_mbus_code(
struct v4l2_subdev *sd,
1027 struct v4l2_subdev_mbus_code_enum *
code)
1029 if (code->index >=
ARRAY_SIZE(s5k6aa_formats))
1032 code->code = s5k6aa_formats[code->index].
code;
1036 static int s5k6aa_enum_frame_size(
struct v4l2_subdev *sd,
1038 struct v4l2_subdev_frame_size_enum *fse)
1046 if (fse->code == s5k6aa_formats[i].
code)
1049 fse->code = s5k6aa_formats[
i].
code;
1059 __s5k6aa_get_crop_rect(
struct s5k6aa *s5k6aa,
struct v4l2_subdev_fh *fh,
1066 return v4l2_subdev_get_try_crop(fh, 0);
1069 static void s5k6aa_try_format(
struct s5k6aa *s5k6aa,
1070 struct v4l2_mbus_framefmt *mf)
1083 index = s5k6aa_get_pixfmt_index(s5k6aa, mf);
1093 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1094 struct v4l2_mbus_framefmt *mf;
1099 mf = v4l2_subdev_get_try_format(fh, 0);
1114 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1116 struct v4l2_mbus_framefmt *mf;
1121 s5k6aa_try_format(s5k6aa, &fmt->
format);
1124 mf = v4l2_subdev_get_try_format(fh, fmt->
pad);
1125 crop = v4l2_subdev_get_try_crop(fh, 0);
1137 struct v4l2_subdev_frame_interval fiv = {
1157 ret = __s5k6aa_set_frame_interval(s5k6aa, &fiv);
1167 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1173 rect = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->
which);
1177 v4l2_dbg(1,
debug, sd,
"Current crop rectangle: (%d,%d)/%dx%d\n",
1186 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1187 struct v4l2_mbus_framefmt *mf;
1188 unsigned int max_x, max_y;
1192 crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->
which);
1195 mf = &s5k6aa->
preset->mbus_fmt;
1198 mf = v4l2_subdev_get_try_format(fh, 0);
1202 &crop->
rect.height, mf->height,
1211 *crop_r = crop->
rect;
1215 v4l2_dbg(1,
debug, sd,
"Set crop rectangle: (%d,%d)/%dx%d\n",
1222 .enum_mbus_code = s5k6aa_enum_mbus_code,
1223 .enum_frame_size = s5k6aa_enum_frame_size,
1224 .enum_frame_interval = s5k6aa_enum_frame_interval,
1225 .get_fmt = s5k6aa_get_fmt,
1226 .set_fmt = s5k6aa_set_fmt,
1227 .get_crop = s5k6aa_get_crop,
1228 .set_crop = s5k6aa_set_crop,
1232 .g_frame_interval = s5k6aa_g_frame_interval,
1233 .s_frame_interval = s5k6aa_s_frame_interval,
1234 .s_stream = s5k6aa_s_stream,
1244 struct i2c_client *client = v4l2_get_subdevdata(sd);
1245 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1256 if (s5k6aa->
power == 0)
1258 idx = s5k6aa->
preset->index;
1262 err = s5k6aa_set_awb(s5k6aa, ctrl->
val);
1270 err = s5k6aa_set_colorfx(s5k6aa, ctrl->
val);
1278 err = s5k6aa_set_auto_exposure(s5k6aa, ctrl->
val);
1282 err = s5k6aa_set_mirror(s5k6aa, ctrl->
val);
1289 err = s5k6aa_set_anti_flicker(s5k6aa, ctrl->
val);
1313 .s_ctrl = s5k6aa_s_ctrl,
1316 static int s5k6aa_log_status(
struct v4l2_subdev *sd)
1322 #define V4L2_CID_RED_GAIN (V4L2_CTRL_CLASS_CAMERA | 0x1001)
1323 #define V4L2_CID_GREEN_GAIN (V4L2_CTRL_CLASS_CAMERA | 0x1002)
1324 #define V4L2_CID_BLUE_GAIN (V4L2_CTRL_CLASS_CAMERA | 0x1003)
1328 .ops = &s5k6aa_ctrl_ops,
1331 .name =
"Gain, Red",
1337 .ops = &s5k6aa_ctrl_ops,
1340 .name =
"Gain, Green",
1346 .ops = &s5k6aa_ctrl_ops,
1349 .name =
"Gain, Blue",
1357 static int s5k6aa_initialize_ctrls(
struct s5k6aa *s5k6aa)
1360 struct s5k6aa_ctrls *ctrls = &s5k6aa->
ctrls;
1383 0, 6000000
U, 1, 100000
U);
1410 s5k6aa->
sd.ctrl_handler = hdl;
1419 struct v4l2_mbus_framefmt *
format = v4l2_subdev_get_try_format(fh, 0);
1420 struct v4l2_rect *crop = v4l2_subdev_get_try_crop(fh, 0);
1422 format->colorspace = s5k6aa_formats[0].
colorspace;
1423 format->code = s5k6aa_formats[0].
code;
1436 static int s5k6aa_check_fw_revision(
struct s5k6aa *s5k6aa)
1438 struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->
sd);
1441 int ret = s5k6aa_set_ahb_address(client);
1448 v4l2_err(&s5k6aa->
sd,
"FW revision check failed!\n");
1452 v4l2_info(&s5k6aa->
sd,
"FW API ver.: 0x%X, FW rev.: 0x%X\n",
1458 static int s5k6aa_registered(
struct v4l2_subdev *sd)
1460 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1464 ret = __s5k6aa_power_on(s5k6aa);
1467 ret = s5k6aa_check_fw_revision(s5k6aa);
1468 __s5k6aa_power_off(s5k6aa);
1476 .registered = s5k6aa_registered,
1477 .open = s5k6aa_open,
1481 .s_power = s5k6aa_set_power,
1482 .log_status = s5k6aa_log_status,
1486 .core = &s5k6aa_core_ops,
1487 .pad = &s5k6aa_pad_ops,
1488 .video = &s5k6aa_video_ops,
1494 static int s5k6aa_configure_gpio(
int nr,
int val,
const char *
name)
1499 if (!gpio_is_valid(nr))
1507 static void s5k6aa_free_gpios(
struct s5k6aa *s5k6aa)
1512 if (!gpio_is_valid(s5k6aa->
gpio[i].gpio))
1519 static int s5k6aa_configure_gpios(
struct s5k6aa *s5k6aa,
1528 ret = s5k6aa_configure_gpio(gpio->
gpio, gpio->
level,
"S5K6AA_STBY");
1530 s5k6aa_free_gpios(s5k6aa);
1534 if (gpio_is_valid(gpio->
gpio))
1538 ret = s5k6aa_configure_gpio(gpio->
gpio, gpio->
level,
"S5K6AA_RST");
1540 s5k6aa_free_gpios(s5k6aa);
1544 if (gpio_is_valid(gpio->
gpio))
1550 static int s5k6aa_probe(
struct i2c_client *client,
1555 struct s5k6aa *s5k6aa;
1558 if (pdata ==
NULL) {
1559 dev_err(&client->
dev,
"Platform data not specified\n");
1564 dev_err(&client->
dev,
"MCLK frequency not specified\n");
1594 ret = s5k6aa_configure_gpios(s5k6aa, pdata);
1599 s5k6aa->
supplies[i].supply = s5k6aa_supply_names[i];
1604 dev_err(&client->
dev,
"Failed to get regulators\n");
1608 ret = s5k6aa_initialize_ctrls(s5k6aa);
1612 s5k6aa_presets_data_init(s5k6aa);
1624 s5k6aa_free_gpios(s5k6aa);
1630 static int s5k6aa_remove(
struct i2c_client *client)
1632 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1633 struct s5k6aa *s5k6aa = to_s5k6aa(sd);
1639 s5k6aa_free_gpios(s5k6aa);
1651 static struct i2c_driver s5k6aa_i2c_driver = {
1655 .probe = s5k6aa_probe,
1656 .remove = s5k6aa_remove,
1657 .id_table = s5k6aa_id,