16 #include <linux/i2c.h>
17 #include <linux/slab.h>
23 #include <linux/videodev2.h>
24 #include <linux/module.h>
36 #define MODULE_NAME "M5MOLS"
37 #define M5MOLS_I2C_CHECK_RETRY 500
72 #define SIZE_DEFAULT_FFMT ARRAY_SIZE(m5mols_default_ffmt)
127 else if (length == 2)
167 msg[1].len = size + 1;
176 *val = m5mols_swap_byte(&rbuf[1], size);
181 v4l2_err(sd,
"read failed: size:%d cat:%02x cmd:%02x. %d\n",
182 size, category, cmd, ret);
184 return ret < 0 ? ret : -
EIO;
197 ret = m5mols_read(sd,
I2C_SIZE(reg), reg, &val_32);
215 ret = m5mols_read(sd,
I2C_SIZE(reg), reg, &val_32);
230 return m5mols_read(sd,
I2C_SIZE(reg), reg, val);
242 struct i2c_client *client = v4l2_get_subdevdata(sd);
255 if (size != 1 && size != 2 && size != 4) {
269 *buf = m5mols_swap_byte((
u8 *)&val, size);
278 v4l2_err(sd,
"write failed: cat:%02x cmd:%02x ret:%d\n",
281 return ret < 0 ? ret : -
EIO;
308 if (!ret && (status & mask & 0xff) == (value & 0xff))
340 atomic_add_unless(&info->
irq_done, -1, 0),
382 if (ret || reg == mode)
391 ret = m5mols_reg_mode(sd, REG_CAPTURE);
400 ret = m5mols_reg_mode(sd, REG_CAPTURE);
427 static int m5mols_get_version(
struct v4l2_subdev *sd)
464 "Samsung Electro-Machanics" :
466 "Samsung Fiber-Optics" :
468 "Samsung Techwin" :
"None");
469 v4l2_info(sd,
"Customer/Project\t[0x%02x/0x%02x]\n",
470 info->
ver.customer, info->
ver.project);
473 v4l2_info(sd,
"No support Auto Focus on this firmware\n");
487 if (code == m5mols_default_ffmt[type].code)
503 static int __find_resolution(
struct v4l2_subdev *sd,
504 struct v4l2_mbus_framefmt *mf,
512 unsigned int min_err = ~0;
516 if (stype == fsize->
type) {
529 mf->height = match->
height;
530 *resolution = match->
reg;
538 static struct v4l2_mbus_framefmt *__find_format(
struct m5mols_info *info,
544 return fh ? v4l2_subdev_get_try_format(fh, 0) :
NULL;
553 struct v4l2_mbus_framefmt *
format;
558 format = __find_format(info, fh, fmt->
which, info->
res_type);
572 struct v4l2_mbus_framefmt *format = &fmt->
format;
573 struct v4l2_mbus_framefmt *sfmt;
578 ret = __find_resolution(sd, format, &type, &resolution);
582 sfmt = __find_format(info, fh, fmt->
which, type);
588 format->code = m5mols_default_ffmt[
type].code;
602 static int m5mols_get_frame_desc(
struct v4l2_subdev *sd,
unsigned int pad,
607 if (pad != 0 || fd ==
NULL)
615 fd->
entry[0].length = info->
cap.buf_size;
625 static int m5mols_set_frame_desc(
struct v4l2_subdev *sd,
unsigned int pad,
631 if (pad != 0 || fd ==
NULL)
637 mf->width * mf->height,
640 info->
cap.buf_size = fd->
entry[0].length;
647 static int m5mols_enum_mbus_code(
struct v4l2_subdev *sd,
649 struct v4l2_subdev_mbus_code_enum *code)
654 code->code = m5mols_default_ffmt[code->index].code;
661 .get_fmt = m5mols_get_fmt,
662 .set_fmt = m5mols_set_fmt,
663 .get_frame_desc = m5mols_get_frame_desc,
664 .set_frame_desc = m5mols_set_frame_desc,
697 static int m5mols_start_monitor(
struct m5mols_info *info)
726 ret = m5mols_start_monitor(info);
743 static int m5mols_sensor_power(
struct m5mols_info *info,
bool enable)
746 struct i2c_client *client = v4l2_get_subdevdata(sd);
750 if (info->
power == enable)
819 ret = m5mols_get_version(sd);
836 static int m5mols_auto_focus_stop(
struct m5mols_info *info)
856 static int m5mols_s_power(
struct v4l2_subdev *sd,
int on)
864 ret = m5mols_sensor_power(info,
true);
866 ret = m5mols_fw_start(sd);
871 ret = m5mols_auto_focus_stop(info);
873 v4l2_warn(sd,
"Soft landing lens failed\n");
875 ret = m5mols_sensor_power(info,
false);
884 static int m5mols_log_status(
struct v4l2_subdev *sd)
895 .log_status = m5mols_log_status,
903 struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
905 *format = m5mols_default_ffmt[0];
914 .
core = &m5mols_core_ops,
915 .pad = &m5mols_pad_ops,
916 .video = &m5mols_video_ops,
919 static irqreturn_t m5mols_irq_handler(
int irq,
void *data)
943 dev_err(&client->
dev,
"No valid RESET GPIO specified\n");
948 dev_err(&client->
dev,
"Interrupt not assigned\n");
961 dev_err(&client->
dev,
"Failed to request gpio: %d\n", ret);
968 dev_err(&client->
dev,
"Failed to get regulators: %d\n", ret);
990 dev_err(&client->
dev,
"Interrupt request failed: %d\n", ret);
994 info->
ffmt[0] = m5mols_default_ffmt[0];
995 info->
ffmt[1] = m5mols_default_ffmt[1];
997 ret = m5mols_sensor_power(info,
true);
1001 ret = m5mols_fw_start(sd);
1005 ret = m5mols_sensor_power(info,
false);
1023 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1043 static struct i2c_driver m5mols_i2c_driver = {
1047 .probe = m5mols_probe,
1049 .id_table = m5mols_id,