Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Driver for M-5MOLS 8M Pixel camera sensor with ISP
0004  *
0005  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
0006  * Author: HeungJun Kim <riverful.kim@samsung.com>
0007  *
0008  * Copyright (C) 2009 Samsung Electronics Co., Ltd.
0009  * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
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 /* The regulator consumer names for external voltage regulators */
0036 static struct regulator_bulk_data supplies[] = {
0037     {
0038         .supply = "core",   /* ARM core power, 1.2V */
0039     }, {
0040         .supply = "dig_18", /* digital power 1, 1.8V */
0041     }, {
0042         .supply = "d_sensor",   /* sensor power 1, 1.8V */
0043     }, {
0044         .supply = "dig_28", /* digital power 2, 2.8V */
0045     }, {
0046         .supply = "a_sensor",   /* analog power */
0047     }, {
0048         .supply = "dig_12", /* digital power 3, 1.2V */
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 },  /* SUB-QCIF */
0072     { 0x03, M5MOLS_RESTYPE_MONITOR, 160, 120 }, /* QQVGA */
0073     { 0x05, M5MOLS_RESTYPE_MONITOR, 176, 144 }, /* QCIF */
0074     { 0x06, M5MOLS_RESTYPE_MONITOR, 176, 176 },
0075     { 0x08, M5MOLS_RESTYPE_MONITOR, 240, 320 }, /* QVGA */
0076     { 0x09, M5MOLS_RESTYPE_MONITOR, 320, 240 }, /* QVGA */
0077     { 0x0c, M5MOLS_RESTYPE_MONITOR, 240, 400 }, /* WQVGA */
0078     { 0x0d, M5MOLS_RESTYPE_MONITOR, 400, 240 }, /* WQVGA */
0079     { 0x0e, M5MOLS_RESTYPE_MONITOR, 352, 288 }, /* CIF */
0080     { 0x13, M5MOLS_RESTYPE_MONITOR, 480, 360 },
0081     { 0x15, M5MOLS_RESTYPE_MONITOR, 640, 360 }, /* qHD */
0082     { 0x17, M5MOLS_RESTYPE_MONITOR, 640, 480 }, /* VGA */
0083     { 0x18, M5MOLS_RESTYPE_MONITOR, 720, 480 },
0084     { 0x1a, M5MOLS_RESTYPE_MONITOR, 800, 480 }, /* WVGA */
0085     { 0x1f, M5MOLS_RESTYPE_MONITOR, 800, 600 }, /* SVGA */
0086     { 0x21, M5MOLS_RESTYPE_MONITOR, 1280, 720 },    /* HD */
0087     { 0x25, M5MOLS_RESTYPE_MONITOR, 1920, 1080 },   /* 1080p */
0088     { 0x29, M5MOLS_RESTYPE_MONITOR, 3264, 2448 },   /* 2.63fps 8M */
0089     { 0x39, M5MOLS_RESTYPE_MONITOR, 800, 602 }, /* AHS_MON debug */
0090 
0091     { 0x02, M5MOLS_RESTYPE_CAPTURE, 320, 240 }, /* QVGA */
0092     { 0x04, M5MOLS_RESTYPE_CAPTURE, 400, 240 }, /* WQVGA */
0093     { 0x07, M5MOLS_RESTYPE_CAPTURE, 480, 360 },
0094     { 0x08, M5MOLS_RESTYPE_CAPTURE, 640, 360 }, /* qHD */
0095     { 0x09, M5MOLS_RESTYPE_CAPTURE, 640, 480 }, /* VGA */
0096     { 0x0a, M5MOLS_RESTYPE_CAPTURE, 800, 480 }, /* WVGA */
0097     { 0x10, M5MOLS_RESTYPE_CAPTURE, 1280, 720 },    /* HD */
0098     { 0x14, M5MOLS_RESTYPE_CAPTURE, 1280, 960 },    /* 1M */
0099     { 0x17, M5MOLS_RESTYPE_CAPTURE, 1600, 1200 },   /* 2M */
0100     { 0x19, M5MOLS_RESTYPE_CAPTURE, 1920, 1080 },   /* Full-HD */
0101     { 0x1a, M5MOLS_RESTYPE_CAPTURE, 2048, 1152 },   /* 3Mega */
0102     { 0x1b, M5MOLS_RESTYPE_CAPTURE, 2048, 1536 },
0103     { 0x1c, M5MOLS_RESTYPE_CAPTURE, 2560, 1440 },   /* 4Mega */
0104     { 0x1d, M5MOLS_RESTYPE_CAPTURE, 2560, 1536 },
0105     { 0x1f, M5MOLS_RESTYPE_CAPTURE, 2560, 1920 },   /* 5Mega */
0106     { 0x21, M5MOLS_RESTYPE_CAPTURE, 3264, 1836 },   /* 6Mega */
0107     { 0x22, M5MOLS_RESTYPE_CAPTURE, 3264, 1960 },
0108     { 0x25, M5MOLS_RESTYPE_CAPTURE, 3264, 2448 },   /* 8Mega */
0109 };
0110 
0111 /**
0112  * m5mols_swap_byte - an byte array to integer conversion function
0113  * @data: byte array
0114  * @length: size in bytes of I2C packet defined in the M-5MOLS datasheet
0115  *
0116  * Convert I2C data byte array with performing any required byte
0117  * reordering to assure proper values for each data type, regardless
0118  * of the architecture endianness.
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  * m5mols_read -  I2C read function
0132  * @sd: sub-device, as pointed by struct v4l2_subdev
0133  * @size: desired size of I2C packet
0134  * @reg: combination of size, category and command for the I2C packet
0135  * @val: read value
0136  *
0137  * Returns 0 on success, or else negative errno.
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     /* minimum stabilization time */
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  * m5mols_write - I2C command write function
0233  * @sd: sub-device, as pointed by struct v4l2_subdev
0234  * @reg: combination of size, category and command for the I2C packet
0235  * @val: value to write
0236  *
0237  * Returns 0 on success, or else negative errno.
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     /* minimum stabilization time */
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  * m5mols_busy_wait - Busy waiting with I2C register polling
0286  * @sd: sub-device, as pointed by struct v4l2_subdev
0287  * @reg: the I2C_REG() address of an 8-bit status register to check
0288  * @value: expected status register value
0289  * @mask: bit mask for the read status register value
0290  * @timeout: timeout in milliseconds, or -1 for default timeout
0291  *
0292  * The @reg register value is ORed with @mask before comparing with @value.
0293  *
0294  * Return: 0 if the requested condition became true within less than
0295  *         @timeout ms, or else negative errno.
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  * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts
0319  * @sd: sub-device, as pointed by struct v4l2_subdev
0320  * @reg: combination of size, category and command for the I2C packet
0321  *
0322  * Before writing desired interrupt value the INT_FACTOR register should
0323  * be read to clear pending interrupts.
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  * m5mols_reg_mode - Write the mode and check busy status
0354  * @sd: sub-device, as pointed by struct v4l2_subdev
0355  * @mode: the required operation mode
0356  *
0357  * It always accompanies a little delay changing the M-5MOLS mode, so it is
0358  * needed checking current busy status to guarantee right mode.
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  * m5mols_set_mode - set the M-5MOLS controller mode
0371  * @info: M-5MOLS driver data structure
0372  * @mode: the required operation mode
0373  *
0374  * The commands of M-5MOLS are grouped into specific modes. Each functionality
0375  * can be guaranteed only when the sensor is operating in mode which a command
0376  * belongs to.
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, &reg);
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  * m5mols_get_version - retrieve full revisions information of M-5MOLS
0429  * @sd: sub-device, as pointed by struct v4l2_subdev
0430  *
0431  * The version information includes revisions of hardware and firmware,
0432  * AutoFocus alghorithm version and the version string.
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  * __find_restype - Lookup M-5MOLS resolution type according to pixel code
0482  * @code: pixel code
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  * __find_resolution - Lookup preset and type of M-5MOLS's resolution
0498  * @sd: sub-device, as pointed by struct v4l2_subdev
0499  * @mf: pixel format to find/negotiate the resolution preset for
0500  * @type: M-5MOLS resolution type
0501  * @resolution: M-5MOLS resolution preset register value
0502  *
0503  * Find nearest resolution matching resolution preset and adjust mf
0504  * to supported values.
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      * .get_frame_desc is only used for compressed formats,
0619      * thus we always return the capture frame parameters here.
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  * m5mols_restore_controls - Apply current control values to the registers
0675  * @info: M-5MOLS driver data structure
0676  *
0677  * m5mols_do_scenemode() handles all parameters for which there is yet no
0678  * individual control. It should be replaced at some point by setting each
0679  * control individually, in required register set up order.
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  * m5mols_start_monitor - Start the monitor mode
0700  * @info: M-5MOLS driver data structure
0701  *
0702  * Before applying the controls setup the resolution and frame rate
0703  * in PARAMETER mode, and then switch over to MONITOR mode.
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 /* m5mols_update_fw - optional firmware update routine */
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  * m5mols_fw_start - M-5MOLS internal ARM controller initialization
0804  * @sd: sub-device, as pointed by struct v4l2_subdev
0805  *
0806  * Execute the M-5MOLS internal ARM controller initialization sequence.
0807  * This function should be called after the supply voltage has been
0808  * applied and before any requests to the device are made.
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     /* Wait until I2C slave is initialized in Flash Writer mode */
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 /* Execute the lens soft-landing algorithm */
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  * m5mols_s_power - Main sensor power control function
0860  * @sd: sub-device, as pointed by struct v4l2_subdev
0861  * @on: if true, powers on the device; powers off otherwise.
0862  *
0863  * To prevent breaking the lens when the sensor is powered off the Soft-Landing
0864  * algorithm is called where available. The Soft-Landing algorithm availability
0865  * dependends on the firmware provider.
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  * V4L2 subdev internal operations
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     /* This asserts reset, descriptor shall have polarity specified */
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     /* Notice: the "N" in M5MOLS_NRST implies active low */
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     /* Static name; NEVER use in new drivers! */
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");