0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/i2c.h>
0013 #include <linux/slab.h>
0014 #include <linux/irq.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/delay.h>
0017 #include <linux/gpio/consumer.h>
0018 #include <linux/regulator/consumer.h>
0019 #include <linux/videodev2.h>
0020 #include <linux/module.h>
0021 #include <media/v4l2-ctrls.h>
0022 #include <media/v4l2-device.h>
0023 #include <media/v4l2-subdev.h>
0024 #include <media/i2c/m5mols.h>
0025
0026 #include "m5mols.h"
0027 #include "m5mols_reg.h"
0028
0029 int m5mols_debug;
0030 module_param(m5mols_debug, int, 0644);
0031
0032 #define MODULE_NAME "M5MOLS"
0033 #define M5MOLS_I2C_CHECK_RETRY 500
0034
0035
0036 static struct regulator_bulk_data supplies[] = {
0037 {
0038 .supply = "core",
0039 }, {
0040 .supply = "dig_18",
0041 }, {
0042 .supply = "d_sensor",
0043 }, {
0044 .supply = "dig_28",
0045 }, {
0046 .supply = "a_sensor",
0047 }, {
0048 .supply = "dig_12",
0049 },
0050 };
0051
0052 static struct v4l2_mbus_framefmt m5mols_default_ffmt[M5MOLS_RESTYPE_MAX] = {
0053 [M5MOLS_RESTYPE_MONITOR] = {
0054 .width = 1920,
0055 .height = 1080,
0056 .code = MEDIA_BUS_FMT_VYUY8_2X8,
0057 .field = V4L2_FIELD_NONE,
0058 .colorspace = V4L2_COLORSPACE_JPEG,
0059 },
0060 [M5MOLS_RESTYPE_CAPTURE] = {
0061 .width = 1920,
0062 .height = 1080,
0063 .code = MEDIA_BUS_FMT_JPEG_1X8,
0064 .field = V4L2_FIELD_NONE,
0065 .colorspace = V4L2_COLORSPACE_JPEG,
0066 },
0067 };
0068 #define SIZE_DEFAULT_FFMT ARRAY_SIZE(m5mols_default_ffmt)
0069
0070 static const struct m5mols_resolution m5mols_reg_res[] = {
0071 { 0x01, M5MOLS_RESTYPE_MONITOR, 128, 96 },
0072 { 0x03, M5MOLS_RESTYPE_MONITOR, 160, 120 },
0073 { 0x05, M5MOLS_RESTYPE_MONITOR, 176, 144 },
0074 { 0x06, M5MOLS_RESTYPE_MONITOR, 176, 176 },
0075 { 0x08, M5MOLS_RESTYPE_MONITOR, 240, 320 },
0076 { 0x09, M5MOLS_RESTYPE_MONITOR, 320, 240 },
0077 { 0x0c, M5MOLS_RESTYPE_MONITOR, 240, 400 },
0078 { 0x0d, M5MOLS_RESTYPE_MONITOR, 400, 240 },
0079 { 0x0e, M5MOLS_RESTYPE_MONITOR, 352, 288 },
0080 { 0x13, M5MOLS_RESTYPE_MONITOR, 480, 360 },
0081 { 0x15, M5MOLS_RESTYPE_MONITOR, 640, 360 },
0082 { 0x17, M5MOLS_RESTYPE_MONITOR, 640, 480 },
0083 { 0x18, M5MOLS_RESTYPE_MONITOR, 720, 480 },
0084 { 0x1a, M5MOLS_RESTYPE_MONITOR, 800, 480 },
0085 { 0x1f, M5MOLS_RESTYPE_MONITOR, 800, 600 },
0086 { 0x21, M5MOLS_RESTYPE_MONITOR, 1280, 720 },
0087 { 0x25, M5MOLS_RESTYPE_MONITOR, 1920, 1080 },
0088 { 0x29, M5MOLS_RESTYPE_MONITOR, 3264, 2448 },
0089 { 0x39, M5MOLS_RESTYPE_MONITOR, 800, 602 },
0090
0091 { 0x02, M5MOLS_RESTYPE_CAPTURE, 320, 240 },
0092 { 0x04, M5MOLS_RESTYPE_CAPTURE, 400, 240 },
0093 { 0x07, M5MOLS_RESTYPE_CAPTURE, 480, 360 },
0094 { 0x08, M5MOLS_RESTYPE_CAPTURE, 640, 360 },
0095 { 0x09, M5MOLS_RESTYPE_CAPTURE, 640, 480 },
0096 { 0x0a, M5MOLS_RESTYPE_CAPTURE, 800, 480 },
0097 { 0x10, M5MOLS_RESTYPE_CAPTURE, 1280, 720 },
0098 { 0x14, M5MOLS_RESTYPE_CAPTURE, 1280, 960 },
0099 { 0x17, M5MOLS_RESTYPE_CAPTURE, 1600, 1200 },
0100 { 0x19, M5MOLS_RESTYPE_CAPTURE, 1920, 1080 },
0101 { 0x1a, M5MOLS_RESTYPE_CAPTURE, 2048, 1152 },
0102 { 0x1b, M5MOLS_RESTYPE_CAPTURE, 2048, 1536 },
0103 { 0x1c, M5MOLS_RESTYPE_CAPTURE, 2560, 1440 },
0104 { 0x1d, M5MOLS_RESTYPE_CAPTURE, 2560, 1536 },
0105 { 0x1f, M5MOLS_RESTYPE_CAPTURE, 2560, 1920 },
0106 { 0x21, M5MOLS_RESTYPE_CAPTURE, 3264, 1836 },
0107 { 0x22, M5MOLS_RESTYPE_CAPTURE, 3264, 1960 },
0108 { 0x25, M5MOLS_RESTYPE_CAPTURE, 3264, 2448 },
0109 };
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 static u32 m5mols_swap_byte(u8 *data, u8 length)
0121 {
0122 if (length == 1)
0123 return *data;
0124 else if (length == 2)
0125 return be16_to_cpu(*((__be16 *)data));
0126 else
0127 return be32_to_cpu(*((__be32 *)data));
0128 }
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
0140 {
0141 struct i2c_client *client = v4l2_get_subdevdata(sd);
0142 struct m5mols_info *info = to_m5mols(sd);
0143 u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1];
0144 u8 category = I2C_CATEGORY(reg);
0145 u8 cmd = I2C_COMMAND(reg);
0146 struct i2c_msg msg[2];
0147 u8 wbuf[5];
0148 int ret;
0149
0150 if (!client->adapter)
0151 return -ENODEV;
0152
0153 msg[0].addr = client->addr;
0154 msg[0].flags = 0;
0155 msg[0].len = 5;
0156 msg[0].buf = wbuf;
0157 wbuf[0] = 5;
0158 wbuf[1] = M5MOLS_BYTE_READ;
0159 wbuf[2] = category;
0160 wbuf[3] = cmd;
0161 wbuf[4] = size;
0162
0163 msg[1].addr = client->addr;
0164 msg[1].flags = I2C_M_RD;
0165 msg[1].len = size + 1;
0166 msg[1].buf = rbuf;
0167
0168
0169 usleep_range(200, 300);
0170
0171 ret = i2c_transfer(client->adapter, msg, 2);
0172
0173 if (ret == 2) {
0174 *val = m5mols_swap_byte(&rbuf[1], size);
0175 return 0;
0176 }
0177
0178 if (info->isp_ready)
0179 v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
0180 size, category, cmd, ret);
0181
0182 return ret < 0 ? ret : -EIO;
0183 }
0184
0185 int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val)
0186 {
0187 u32 val_32;
0188 int ret;
0189
0190 if (I2C_SIZE(reg) != 1) {
0191 v4l2_err(sd, "Wrong data size\n");
0192 return -EINVAL;
0193 }
0194
0195 ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
0196 if (ret)
0197 return ret;
0198
0199 *val = (u8)val_32;
0200 return ret;
0201 }
0202
0203 int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg, u16 *val)
0204 {
0205 u32 val_32;
0206 int ret;
0207
0208 if (I2C_SIZE(reg) != 2) {
0209 v4l2_err(sd, "Wrong data size\n");
0210 return -EINVAL;
0211 }
0212
0213 ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
0214 if (ret)
0215 return ret;
0216
0217 *val = (u16)val_32;
0218 return ret;
0219 }
0220
0221 int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val)
0222 {
0223 if (I2C_SIZE(reg) != 4) {
0224 v4l2_err(sd, "Wrong data size\n");
0225 return -EINVAL;
0226 }
0227
0228 return m5mols_read(sd, I2C_SIZE(reg), reg, val);
0229 }
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239 int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
0240 {
0241 struct i2c_client *client = v4l2_get_subdevdata(sd);
0242 struct m5mols_info *info = to_m5mols(sd);
0243 u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4];
0244 u8 category = I2C_CATEGORY(reg);
0245 u8 cmd = I2C_COMMAND(reg);
0246 u8 size = I2C_SIZE(reg);
0247 u32 *buf = (u32 *)&wbuf[4];
0248 struct i2c_msg msg[1];
0249 int ret;
0250
0251 if (!client->adapter)
0252 return -ENODEV;
0253
0254 if (size != 1 && size != 2 && size != 4) {
0255 v4l2_err(sd, "Wrong data size\n");
0256 return -EINVAL;
0257 }
0258
0259 msg->addr = client->addr;
0260 msg->flags = 0;
0261 msg->len = (u16)size + 4;
0262 msg->buf = wbuf;
0263 wbuf[0] = size + 4;
0264 wbuf[1] = M5MOLS_BYTE_WRITE;
0265 wbuf[2] = category;
0266 wbuf[3] = cmd;
0267
0268 *buf = m5mols_swap_byte((u8 *)&val, size);
0269
0270
0271 usleep_range(200, 300);
0272
0273 ret = i2c_transfer(client->adapter, msg, 1);
0274 if (ret == 1)
0275 return 0;
0276
0277 if (info->isp_ready)
0278 v4l2_err(sd, "write failed: cat:%02x cmd:%02x ret:%d\n",
0279 category, cmd, ret);
0280
0281 return ret < 0 ? ret : -EIO;
0282 }
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297 int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
0298 int timeout)
0299 {
0300 int ms = timeout < 0 ? M5MOLS_BUSY_WAIT_DEF_TIMEOUT : timeout;
0301 unsigned long end = jiffies + msecs_to_jiffies(ms);
0302 u8 status;
0303
0304 do {
0305 int ret = m5mols_read_u8(sd, reg, &status);
0306
0307 if (ret < 0 && !(mask & M5MOLS_I2C_RDY_WAIT_FL))
0308 return ret;
0309 if (!ret && (status & mask & 0xff) == (value & 0xff))
0310 return 0;
0311 usleep_range(100, 250);
0312 } while (ms > 0 && time_is_after_jiffies(end));
0313
0314 return -EBUSY;
0315 }
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325 int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
0326 {
0327 struct m5mols_info *info = to_m5mols(sd);
0328 u8 mask = is_available_af(info) ? REG_INT_AF : 0;
0329 u8 dummy;
0330 int ret;
0331
0332 ret = m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &dummy);
0333 if (!ret)
0334 ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask);
0335 return ret;
0336 }
0337
0338 int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 irq_mask, u32 timeout)
0339 {
0340 struct m5mols_info *info = to_m5mols(sd);
0341
0342 int ret = wait_event_interruptible_timeout(info->irq_waitq,
0343 atomic_add_unless(&info->irq_done, -1, 0),
0344 msecs_to_jiffies(timeout));
0345 if (ret <= 0)
0346 return ret ? ret : -ETIMEDOUT;
0347
0348 return m5mols_busy_wait(sd, SYSTEM_INT_FACTOR, irq_mask,
0349 M5MOLS_I2C_RDY_WAIT_FL | irq_mask, -1);
0350 }
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360 static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
0361 {
0362 int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
0363 if (ret < 0)
0364 return ret;
0365 return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff,
0366 M5MOLS_MODE_CHANGE_TIMEOUT);
0367 }
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378 int m5mols_set_mode(struct m5mols_info *info, u8 mode)
0379 {
0380 struct v4l2_subdev *sd = &info->sd;
0381 int ret = -EINVAL;
0382 u8 reg;
0383
0384 if (mode < REG_PARAMETER || mode > REG_CAPTURE)
0385 return ret;
0386
0387 ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, ®);
0388 if (ret || reg == mode)
0389 return ret;
0390
0391 switch (reg) {
0392 case REG_PARAMETER:
0393 ret = m5mols_reg_mode(sd, REG_MONITOR);
0394 if (mode == REG_MONITOR)
0395 break;
0396 if (!ret)
0397 ret = m5mols_reg_mode(sd, REG_CAPTURE);
0398 break;
0399
0400 case REG_MONITOR:
0401 if (mode == REG_PARAMETER) {
0402 ret = m5mols_reg_mode(sd, REG_PARAMETER);
0403 break;
0404 }
0405
0406 ret = m5mols_reg_mode(sd, REG_CAPTURE);
0407 break;
0408
0409 case REG_CAPTURE:
0410 ret = m5mols_reg_mode(sd, REG_MONITOR);
0411 if (mode == REG_MONITOR)
0412 break;
0413 if (!ret)
0414 ret = m5mols_reg_mode(sd, REG_PARAMETER);
0415 break;
0416
0417 default:
0418 v4l2_warn(sd, "Wrong mode: %d\n", mode);
0419 }
0420
0421 if (!ret)
0422 info->mode = mode;
0423
0424 return ret;
0425 }
0426
0427
0428
0429
0430
0431
0432
0433
0434 static int m5mols_get_version(struct v4l2_subdev *sd)
0435 {
0436 struct m5mols_info *info = to_m5mols(sd);
0437 struct m5mols_version *ver = &info->ver;
0438 u8 *str = ver->str;
0439 int i;
0440 int ret;
0441
0442 ret = m5mols_read_u8(sd, SYSTEM_VER_CUSTOMER, &ver->customer);
0443 if (!ret)
0444 ret = m5mols_read_u8(sd, SYSTEM_VER_PROJECT, &ver->project);
0445 if (!ret)
0446 ret = m5mols_read_u16(sd, SYSTEM_VER_FIRMWARE, &ver->fw);
0447 if (!ret)
0448 ret = m5mols_read_u16(sd, SYSTEM_VER_HARDWARE, &ver->hw);
0449 if (!ret)
0450 ret = m5mols_read_u16(sd, SYSTEM_VER_PARAMETER, &ver->param);
0451 if (!ret)
0452 ret = m5mols_read_u16(sd, SYSTEM_VER_AWB, &ver->awb);
0453 if (!ret)
0454 ret = m5mols_read_u8(sd, AF_VERSION, &ver->af);
0455 if (ret)
0456 return ret;
0457
0458 for (i = 0; i < VERSION_STRING_SIZE; i++) {
0459 ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &str[i]);
0460 if (ret)
0461 return ret;
0462 }
0463
0464 v4l2_info(sd, "Manufacturer\t[%s]\n",
0465 is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
0466 "Samsung Electro-Mechanics" :
0467 is_manufacturer(info, REG_SAMSUNG_OPTICS) ?
0468 "Samsung Fiber-Optics" :
0469 is_manufacturer(info, REG_SAMSUNG_TECHWIN) ?
0470 "Samsung Techwin" : "None");
0471 v4l2_info(sd, "Customer/Project\t[0x%02x/0x%02x]\n",
0472 info->ver.customer, info->ver.project);
0473
0474 if (!is_available_af(info))
0475 v4l2_info(sd, "No support Auto Focus on this firmware\n");
0476
0477 return ret;
0478 }
0479
0480
0481
0482
0483
0484 static enum m5mols_restype __find_restype(u32 code)
0485 {
0486 enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR;
0487
0488 do {
0489 if (code == m5mols_default_ffmt[type].code)
0490 return type;
0491 } while (type++ != SIZE_DEFAULT_FFMT);
0492
0493 return 0;
0494 }
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506 static int __find_resolution(struct v4l2_subdev *sd,
0507 struct v4l2_mbus_framefmt *mf,
0508 enum m5mols_restype *type,
0509 u32 *resolution)
0510 {
0511 const struct m5mols_resolution *fsize = &m5mols_reg_res[0];
0512 const struct m5mols_resolution *match = NULL;
0513 enum m5mols_restype stype = __find_restype(mf->code);
0514 int i = ARRAY_SIZE(m5mols_reg_res);
0515 unsigned int min_err = ~0;
0516
0517 while (i--) {
0518 int err;
0519 if (stype == fsize->type) {
0520 err = abs(fsize->width - mf->width)
0521 + abs(fsize->height - mf->height);
0522
0523 if (err < min_err) {
0524 min_err = err;
0525 match = fsize;
0526 }
0527 }
0528 fsize++;
0529 }
0530 if (match) {
0531 mf->width = match->width;
0532 mf->height = match->height;
0533 *resolution = match->reg;
0534 *type = stype;
0535 return 0;
0536 }
0537
0538 return -EINVAL;
0539 }
0540
0541 static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info,
0542 struct v4l2_subdev_state *sd_state,
0543 enum v4l2_subdev_format_whence which,
0544 enum m5mols_restype type)
0545 {
0546 if (which == V4L2_SUBDEV_FORMAT_TRY)
0547 return sd_state ? v4l2_subdev_get_try_format(&info->sd,
0548 sd_state, 0) : NULL;
0549
0550 return &info->ffmt[type];
0551 }
0552
0553 static int m5mols_get_fmt(struct v4l2_subdev *sd,
0554 struct v4l2_subdev_state *sd_state,
0555 struct v4l2_subdev_format *fmt)
0556 {
0557 struct m5mols_info *info = to_m5mols(sd);
0558 struct v4l2_mbus_framefmt *format;
0559 int ret = 0;
0560
0561 mutex_lock(&info->lock);
0562
0563 format = __find_format(info, sd_state, fmt->which, info->res_type);
0564 if (format)
0565 fmt->format = *format;
0566 else
0567 ret = -EINVAL;
0568
0569 mutex_unlock(&info->lock);
0570 return ret;
0571 }
0572
0573 static int m5mols_set_fmt(struct v4l2_subdev *sd,
0574 struct v4l2_subdev_state *sd_state,
0575 struct v4l2_subdev_format *fmt)
0576 {
0577 struct m5mols_info *info = to_m5mols(sd);
0578 struct v4l2_mbus_framefmt *format = &fmt->format;
0579 struct v4l2_mbus_framefmt *sfmt;
0580 enum m5mols_restype type;
0581 u32 resolution = 0;
0582 int ret;
0583
0584 ret = __find_resolution(sd, format, &type, &resolution);
0585 if (ret < 0)
0586 return ret;
0587
0588 sfmt = __find_format(info, sd_state, fmt->which, type);
0589 if (!sfmt)
0590 return 0;
0591
0592 mutex_lock(&info->lock);
0593
0594 format->code = m5mols_default_ffmt[type].code;
0595 format->colorspace = V4L2_COLORSPACE_JPEG;
0596 format->field = V4L2_FIELD_NONE;
0597
0598 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
0599 *sfmt = *format;
0600 info->resolution = resolution;
0601 info->res_type = type;
0602 }
0603
0604 mutex_unlock(&info->lock);
0605 return ret;
0606 }
0607
0608 static int m5mols_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
0609 struct v4l2_mbus_frame_desc *fd)
0610 {
0611 struct m5mols_info *info = to_m5mols(sd);
0612
0613 if (pad != 0 || fd == NULL)
0614 return -EINVAL;
0615
0616 mutex_lock(&info->lock);
0617
0618
0619
0620
0621 fd->entry[0].length = info->cap.buf_size;
0622 fd->entry[0].pixelcode = info->ffmt[M5MOLS_RESTYPE_CAPTURE].code;
0623 mutex_unlock(&info->lock);
0624
0625 fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
0626 fd->num_entries = 1;
0627
0628 return 0;
0629 }
0630
0631 static int m5mols_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
0632 struct v4l2_mbus_frame_desc *fd)
0633 {
0634 struct m5mols_info *info = to_m5mols(sd);
0635 struct v4l2_mbus_framefmt *mf = &info->ffmt[M5MOLS_RESTYPE_CAPTURE];
0636
0637 if (pad != 0 || fd == NULL)
0638 return -EINVAL;
0639
0640 fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
0641 fd->num_entries = 1;
0642 fd->entry[0].length = clamp_t(u32, fd->entry[0].length,
0643 mf->width * mf->height,
0644 M5MOLS_MAIN_JPEG_SIZE_MAX);
0645 mutex_lock(&info->lock);
0646 info->cap.buf_size = fd->entry[0].length;
0647 mutex_unlock(&info->lock);
0648
0649 return 0;
0650 }
0651
0652
0653 static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
0654 struct v4l2_subdev_state *sd_state,
0655 struct v4l2_subdev_mbus_code_enum *code)
0656 {
0657 if (!code || code->index >= SIZE_DEFAULT_FFMT)
0658 return -EINVAL;
0659
0660 code->code = m5mols_default_ffmt[code->index].code;
0661
0662 return 0;
0663 }
0664
0665 static const struct v4l2_subdev_pad_ops m5mols_pad_ops = {
0666 .enum_mbus_code = m5mols_enum_mbus_code,
0667 .get_fmt = m5mols_get_fmt,
0668 .set_fmt = m5mols_set_fmt,
0669 .get_frame_desc = m5mols_get_frame_desc,
0670 .set_frame_desc = m5mols_set_frame_desc,
0671 };
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681 int m5mols_restore_controls(struct m5mols_info *info)
0682 {
0683 int ret;
0684
0685 if (info->ctrl_sync)
0686 return 0;
0687
0688 ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL);
0689 if (ret)
0690 return ret;
0691
0692 ret = v4l2_ctrl_handler_setup(&info->handle);
0693 info->ctrl_sync = !ret;
0694
0695 return ret;
0696 }
0697
0698
0699
0700
0701
0702
0703
0704
0705 static int m5mols_start_monitor(struct m5mols_info *info)
0706 {
0707 struct v4l2_subdev *sd = &info->sd;
0708 int ret;
0709
0710 ret = m5mols_set_mode(info, REG_PARAMETER);
0711 if (!ret)
0712 ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution);
0713 if (!ret)
0714 ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30);
0715 if (!ret)
0716 ret = m5mols_set_mode(info, REG_MONITOR);
0717 if (!ret)
0718 ret = m5mols_restore_controls(info);
0719
0720 return ret;
0721 }
0722
0723 static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
0724 {
0725 struct m5mols_info *info = to_m5mols(sd);
0726 u32 code;
0727 int ret;
0728
0729 mutex_lock(&info->lock);
0730 code = info->ffmt[info->res_type].code;
0731
0732 if (enable) {
0733 if (is_code(code, M5MOLS_RESTYPE_MONITOR))
0734 ret = m5mols_start_monitor(info);
0735 else if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
0736 ret = m5mols_start_capture(info);
0737 else
0738 ret = -EINVAL;
0739 } else {
0740 ret = m5mols_set_mode(info, REG_PARAMETER);
0741 }
0742
0743 mutex_unlock(&info->lock);
0744 return ret;
0745 }
0746
0747 static const struct v4l2_subdev_video_ops m5mols_video_ops = {
0748 .s_stream = m5mols_s_stream,
0749 };
0750
0751 static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
0752 {
0753 struct v4l2_subdev *sd = &info->sd;
0754 struct i2c_client *client = v4l2_get_subdevdata(sd);
0755 int ret;
0756
0757 if (info->power == enable)
0758 return 0;
0759
0760 if (enable) {
0761 if (info->set_power) {
0762 ret = info->set_power(&client->dev, 1);
0763 if (ret)
0764 return ret;
0765 }
0766
0767 ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
0768 if (ret) {
0769 if (info->set_power)
0770 info->set_power(&client->dev, 0);
0771 return ret;
0772 }
0773
0774 gpiod_set_value(info->reset, 0);
0775 info->power = 1;
0776
0777 return ret;
0778 }
0779
0780 ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
0781 if (ret)
0782 return ret;
0783
0784 if (info->set_power)
0785 info->set_power(&client->dev, 0);
0786
0787 gpiod_set_value(info->reset, 1);
0788
0789 info->isp_ready = 0;
0790 info->power = 0;
0791
0792 return ret;
0793 }
0794
0795
0796 int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd,
0797 int (*set_power)(struct m5mols_info *, bool))
0798 {
0799 return 0;
0800 }
0801
0802
0803
0804
0805
0806
0807
0808
0809
0810 static int m5mols_fw_start(struct v4l2_subdev *sd)
0811 {
0812 struct m5mols_info *info = to_m5mols(sd);
0813 int ret;
0814
0815 atomic_set(&info->irq_done, 0);
0816
0817 ret = m5mols_busy_wait(sd, FLASH_CAM_START, REG_IN_FLASH_MODE,
0818 M5MOLS_I2C_RDY_WAIT_FL | 0xff, -1);
0819 if (!ret)
0820 ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
0821 if (!ret)
0822 ret = m5mols_wait_interrupt(sd, REG_INT_MODE, 2000);
0823 if (ret < 0)
0824 return ret;
0825
0826 info->isp_ready = 1;
0827
0828 ret = m5mols_get_version(sd);
0829 if (!ret)
0830 ret = m5mols_update_fw(sd, m5mols_sensor_power);
0831 if (ret)
0832 return ret;
0833
0834 v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n");
0835
0836 ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI);
0837 if (!ret)
0838 ret = m5mols_enable_interrupt(sd,
0839 REG_INT_AF | REG_INT_CAPTURE);
0840
0841 return ret;
0842 }
0843
0844
0845 static int m5mols_auto_focus_stop(struct m5mols_info *info)
0846 {
0847 int ret;
0848
0849 ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
0850 if (!ret)
0851 ret = m5mols_write(&info->sd, AF_MODE, REG_AF_POWEROFF);
0852 if (!ret)
0853 ret = m5mols_busy_wait(&info->sd, SYSTEM_STATUS, REG_AF_IDLE,
0854 0xff, -1);
0855 return ret;
0856 }
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867 static int m5mols_s_power(struct v4l2_subdev *sd, int on)
0868 {
0869 struct m5mols_info *info = to_m5mols(sd);
0870 int ret;
0871
0872 mutex_lock(&info->lock);
0873
0874 if (on) {
0875 ret = m5mols_sensor_power(info, true);
0876 if (!ret)
0877 ret = m5mols_fw_start(sd);
0878 } else {
0879 if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
0880 ret = m5mols_set_mode(info, REG_MONITOR);
0881 if (!ret)
0882 ret = m5mols_auto_focus_stop(info);
0883 if (ret < 0)
0884 v4l2_warn(sd, "Soft landing lens failed\n");
0885 }
0886 ret = m5mols_sensor_power(info, false);
0887
0888 info->ctrl_sync = 0;
0889 }
0890
0891 mutex_unlock(&info->lock);
0892 return ret;
0893 }
0894
0895 static int m5mols_log_status(struct v4l2_subdev *sd)
0896 {
0897 struct m5mols_info *info = to_m5mols(sd);
0898
0899 v4l2_ctrl_handler_log_status(&info->handle, sd->name);
0900
0901 return 0;
0902 }
0903
0904 static const struct v4l2_subdev_core_ops m5mols_core_ops = {
0905 .s_power = m5mols_s_power,
0906 .log_status = m5mols_log_status,
0907 };
0908
0909
0910
0911
0912 static int m5mols_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
0913 {
0914 struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd,
0915 fh->state,
0916 0);
0917
0918 *format = m5mols_default_ffmt[0];
0919 return 0;
0920 }
0921
0922 static const struct v4l2_subdev_internal_ops m5mols_subdev_internal_ops = {
0923 .open = m5mols_open,
0924 };
0925
0926 static const struct v4l2_subdev_ops m5mols_ops = {
0927 .core = &m5mols_core_ops,
0928 .pad = &m5mols_pad_ops,
0929 .video = &m5mols_video_ops,
0930 };
0931
0932 static irqreturn_t m5mols_irq_handler(int irq, void *data)
0933 {
0934 struct m5mols_info *info = to_m5mols(data);
0935
0936 atomic_set(&info->irq_done, 1);
0937 wake_up_interruptible(&info->irq_waitq);
0938
0939 return IRQ_HANDLED;
0940 }
0941
0942 static int m5mols_probe(struct i2c_client *client,
0943 const struct i2c_device_id *id)
0944 {
0945 const struct m5mols_platform_data *pdata = client->dev.platform_data;
0946 struct m5mols_info *info;
0947 struct v4l2_subdev *sd;
0948 int ret;
0949
0950 if (pdata == NULL) {
0951 dev_err(&client->dev, "No platform data\n");
0952 return -EINVAL;
0953 }
0954
0955 if (!client->irq) {
0956 dev_err(&client->dev, "Interrupt not assigned\n");
0957 return -EINVAL;
0958 }
0959
0960 info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
0961 if (!info)
0962 return -ENOMEM;
0963
0964
0965 info->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
0966 if (IS_ERR(info->reset))
0967 return PTR_ERR(info->reset);
0968
0969 gpiod_set_consumer_name(info->reset, "M5MOLS_NRST");
0970
0971 info->pdata = pdata;
0972 info->set_power = pdata->set_power;
0973
0974 ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies),
0975 supplies);
0976 if (ret) {
0977 dev_err(&client->dev, "Failed to get regulators: %d\n", ret);
0978 return ret;
0979 }
0980
0981 sd = &info->sd;
0982 v4l2_i2c_subdev_init(sd, client, &m5mols_ops);
0983
0984 strscpy(sd->name, MODULE_NAME, sizeof(sd->name));
0985 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
0986
0987 sd->internal_ops = &m5mols_subdev_internal_ops;
0988 info->pad.flags = MEDIA_PAD_FL_SOURCE;
0989 ret = media_entity_pads_init(&sd->entity, 1, &info->pad);
0990 if (ret < 0)
0991 return ret;
0992 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
0993
0994 init_waitqueue_head(&info->irq_waitq);
0995 mutex_init(&info->lock);
0996
0997 ret = devm_request_irq(&client->dev, client->irq, m5mols_irq_handler,
0998 IRQF_TRIGGER_RISING, MODULE_NAME, sd);
0999 if (ret) {
1000 dev_err(&client->dev, "Interrupt request failed: %d\n", ret);
1001 goto error;
1002 }
1003 info->res_type = M5MOLS_RESTYPE_MONITOR;
1004 info->ffmt[0] = m5mols_default_ffmt[0];
1005 info->ffmt[1] = m5mols_default_ffmt[1];
1006
1007 ret = m5mols_sensor_power(info, true);
1008 if (ret)
1009 goto error;
1010
1011 ret = m5mols_fw_start(sd);
1012 if (!ret)
1013 ret = m5mols_init_controls(sd);
1014
1015 ret = m5mols_sensor_power(info, false);
1016 if (!ret)
1017 return 0;
1018 error:
1019 media_entity_cleanup(&sd->entity);
1020 return ret;
1021 }
1022
1023 static int m5mols_remove(struct i2c_client *client)
1024 {
1025 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1026
1027 v4l2_device_unregister_subdev(sd);
1028 v4l2_ctrl_handler_free(sd->ctrl_handler);
1029 media_entity_cleanup(&sd->entity);
1030
1031 return 0;
1032 }
1033
1034 static const struct i2c_device_id m5mols_id[] = {
1035 { MODULE_NAME, 0 },
1036 { },
1037 };
1038 MODULE_DEVICE_TABLE(i2c, m5mols_id);
1039
1040 static struct i2c_driver m5mols_i2c_driver = {
1041 .driver = {
1042 .name = MODULE_NAME,
1043 },
1044 .probe = m5mols_probe,
1045 .remove = m5mols_remove,
1046 .id_table = m5mols_id,
1047 };
1048
1049 module_i2c_driver(m5mols_i2c_driver);
1050
1051 MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
1052 MODULE_AUTHOR("Dongsoo Kim <dongsoo45.kim@samsung.com>");
1053 MODULE_DESCRIPTION("Fujitsu M-5MOLS 8M Pixel camera driver");
1054 MODULE_LICENSE("GPL");