cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

m5mols_core.c (27185B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Driver for M-5MOLS 8M Pixel camera sensor with ISP
      4 *
      5 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
      6 * Author: HeungJun Kim <riverful.kim@samsung.com>
      7 *
      8 * Copyright (C) 2009 Samsung Electronics Co., Ltd.
      9 * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
     10 */
     11
     12#include <linux/i2c.h>
     13#include <linux/slab.h>
     14#include <linux/irq.h>
     15#include <linux/interrupt.h>
     16#include <linux/delay.h>
     17#include <linux/gpio/consumer.h>
     18#include <linux/regulator/consumer.h>
     19#include <linux/videodev2.h>
     20#include <linux/module.h>
     21#include <media/v4l2-ctrls.h>
     22#include <media/v4l2-device.h>
     23#include <media/v4l2-subdev.h>
     24#include <media/i2c/m5mols.h>
     25
     26#include "m5mols.h"
     27#include "m5mols_reg.h"
     28
     29int m5mols_debug;
     30module_param(m5mols_debug, int, 0644);
     31
     32#define MODULE_NAME		"M5MOLS"
     33#define M5MOLS_I2C_CHECK_RETRY	500
     34
     35/* The regulator consumer names for external voltage regulators */
     36static struct regulator_bulk_data supplies[] = {
     37	{
     38		.supply = "core",	/* ARM core power, 1.2V */
     39	}, {
     40		.supply	= "dig_18",	/* digital power 1, 1.8V */
     41	}, {
     42		.supply	= "d_sensor",	/* sensor power 1, 1.8V */
     43	}, {
     44		.supply	= "dig_28",	/* digital power 2, 2.8V */
     45	}, {
     46		.supply	= "a_sensor",	/* analog power */
     47	}, {
     48		.supply	= "dig_12",	/* digital power 3, 1.2V */
     49	},
     50};
     51
     52static struct v4l2_mbus_framefmt m5mols_default_ffmt[M5MOLS_RESTYPE_MAX] = {
     53	[M5MOLS_RESTYPE_MONITOR] = {
     54		.width		= 1920,
     55		.height		= 1080,
     56		.code		= MEDIA_BUS_FMT_VYUY8_2X8,
     57		.field		= V4L2_FIELD_NONE,
     58		.colorspace	= V4L2_COLORSPACE_JPEG,
     59	},
     60	[M5MOLS_RESTYPE_CAPTURE] = {
     61		.width		= 1920,
     62		.height		= 1080,
     63		.code		= MEDIA_BUS_FMT_JPEG_1X8,
     64		.field		= V4L2_FIELD_NONE,
     65		.colorspace	= V4L2_COLORSPACE_JPEG,
     66	},
     67};
     68#define SIZE_DEFAULT_FFMT	ARRAY_SIZE(m5mols_default_ffmt)
     69
     70static const struct m5mols_resolution m5mols_reg_res[] = {
     71	{ 0x01, M5MOLS_RESTYPE_MONITOR, 128, 96 },	/* SUB-QCIF */
     72	{ 0x03, M5MOLS_RESTYPE_MONITOR, 160, 120 },	/* QQVGA */
     73	{ 0x05, M5MOLS_RESTYPE_MONITOR, 176, 144 },	/* QCIF */
     74	{ 0x06, M5MOLS_RESTYPE_MONITOR, 176, 176 },
     75	{ 0x08, M5MOLS_RESTYPE_MONITOR, 240, 320 },	/* QVGA */
     76	{ 0x09, M5MOLS_RESTYPE_MONITOR, 320, 240 },	/* QVGA */
     77	{ 0x0c, M5MOLS_RESTYPE_MONITOR, 240, 400 },	/* WQVGA */
     78	{ 0x0d, M5MOLS_RESTYPE_MONITOR, 400, 240 },	/* WQVGA */
     79	{ 0x0e, M5MOLS_RESTYPE_MONITOR, 352, 288 },	/* CIF */
     80	{ 0x13, M5MOLS_RESTYPE_MONITOR, 480, 360 },
     81	{ 0x15, M5MOLS_RESTYPE_MONITOR, 640, 360 },	/* qHD */
     82	{ 0x17, M5MOLS_RESTYPE_MONITOR, 640, 480 },	/* VGA */
     83	{ 0x18, M5MOLS_RESTYPE_MONITOR, 720, 480 },
     84	{ 0x1a, M5MOLS_RESTYPE_MONITOR, 800, 480 },	/* WVGA */
     85	{ 0x1f, M5MOLS_RESTYPE_MONITOR, 800, 600 },	/* SVGA */
     86	{ 0x21, M5MOLS_RESTYPE_MONITOR, 1280, 720 },	/* HD */
     87	{ 0x25, M5MOLS_RESTYPE_MONITOR, 1920, 1080 },	/* 1080p */
     88	{ 0x29, M5MOLS_RESTYPE_MONITOR, 3264, 2448 },	/* 2.63fps 8M */
     89	{ 0x39, M5MOLS_RESTYPE_MONITOR, 800, 602 },	/* AHS_MON debug */
     90
     91	{ 0x02, M5MOLS_RESTYPE_CAPTURE, 320, 240 },	/* QVGA */
     92	{ 0x04, M5MOLS_RESTYPE_CAPTURE, 400, 240 },	/* WQVGA */
     93	{ 0x07, M5MOLS_RESTYPE_CAPTURE, 480, 360 },
     94	{ 0x08, M5MOLS_RESTYPE_CAPTURE, 640, 360 },	/* qHD */
     95	{ 0x09, M5MOLS_RESTYPE_CAPTURE, 640, 480 },	/* VGA */
     96	{ 0x0a, M5MOLS_RESTYPE_CAPTURE, 800, 480 },	/* WVGA */
     97	{ 0x10, M5MOLS_RESTYPE_CAPTURE, 1280, 720 },	/* HD */
     98	{ 0x14, M5MOLS_RESTYPE_CAPTURE, 1280, 960 },	/* 1M */
     99	{ 0x17, M5MOLS_RESTYPE_CAPTURE, 1600, 1200 },	/* 2M */
    100	{ 0x19, M5MOLS_RESTYPE_CAPTURE, 1920, 1080 },	/* Full-HD */
    101	{ 0x1a, M5MOLS_RESTYPE_CAPTURE, 2048, 1152 },	/* 3Mega */
    102	{ 0x1b, M5MOLS_RESTYPE_CAPTURE, 2048, 1536 },
    103	{ 0x1c, M5MOLS_RESTYPE_CAPTURE, 2560, 1440 },	/* 4Mega */
    104	{ 0x1d, M5MOLS_RESTYPE_CAPTURE, 2560, 1536 },
    105	{ 0x1f, M5MOLS_RESTYPE_CAPTURE, 2560, 1920 },	/* 5Mega */
    106	{ 0x21, M5MOLS_RESTYPE_CAPTURE, 3264, 1836 },	/* 6Mega */
    107	{ 0x22, M5MOLS_RESTYPE_CAPTURE, 3264, 1960 },
    108	{ 0x25, M5MOLS_RESTYPE_CAPTURE, 3264, 2448 },	/* 8Mega */
    109};
    110
    111/**
    112 * m5mols_swap_byte - an byte array to integer conversion function
    113 * @data: byte array
    114 * @length: size in bytes of I2C packet defined in the M-5MOLS datasheet
    115 *
    116 * Convert I2C data byte array with performing any required byte
    117 * reordering to assure proper values for each data type, regardless
    118 * of the architecture endianness.
    119 */
    120static u32 m5mols_swap_byte(u8 *data, u8 length)
    121{
    122	if (length == 1)
    123		return *data;
    124	else if (length == 2)
    125		return be16_to_cpu(*((__be16 *)data));
    126	else
    127		return be32_to_cpu(*((__be32 *)data));
    128}
    129
    130/**
    131 * m5mols_read -  I2C read function
    132 * @sd: sub-device, as pointed by struct v4l2_subdev
    133 * @size: desired size of I2C packet
    134 * @reg: combination of size, category and command for the I2C packet
    135 * @val: read value
    136 *
    137 * Returns 0 on success, or else negative errno.
    138 */
    139static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
    140{
    141	struct i2c_client *client = v4l2_get_subdevdata(sd);
    142	struct m5mols_info *info = to_m5mols(sd);
    143	u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1];
    144	u8 category = I2C_CATEGORY(reg);
    145	u8 cmd = I2C_COMMAND(reg);
    146	struct i2c_msg msg[2];
    147	u8 wbuf[5];
    148	int ret;
    149
    150	if (!client->adapter)
    151		return -ENODEV;
    152
    153	msg[0].addr = client->addr;
    154	msg[0].flags = 0;
    155	msg[0].len = 5;
    156	msg[0].buf = wbuf;
    157	wbuf[0] = 5;
    158	wbuf[1] = M5MOLS_BYTE_READ;
    159	wbuf[2] = category;
    160	wbuf[3] = cmd;
    161	wbuf[4] = size;
    162
    163	msg[1].addr = client->addr;
    164	msg[1].flags = I2C_M_RD;
    165	msg[1].len = size + 1;
    166	msg[1].buf = rbuf;
    167
    168	/* minimum stabilization time */
    169	usleep_range(200, 300);
    170
    171	ret = i2c_transfer(client->adapter, msg, 2);
    172
    173	if (ret == 2) {
    174		*val = m5mols_swap_byte(&rbuf[1], size);
    175		return 0;
    176	}
    177
    178	if (info->isp_ready)
    179		v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
    180			 size, category, cmd, ret);
    181
    182	return ret < 0 ? ret : -EIO;
    183}
    184
    185int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val)
    186{
    187	u32 val_32;
    188	int ret;
    189
    190	if (I2C_SIZE(reg) != 1) {
    191		v4l2_err(sd, "Wrong data size\n");
    192		return -EINVAL;
    193	}
    194
    195	ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
    196	if (ret)
    197		return ret;
    198
    199	*val = (u8)val_32;
    200	return ret;
    201}
    202
    203int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg, u16 *val)
    204{
    205	u32 val_32;
    206	int ret;
    207
    208	if (I2C_SIZE(reg) != 2) {
    209		v4l2_err(sd, "Wrong data size\n");
    210		return -EINVAL;
    211	}
    212
    213	ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
    214	if (ret)
    215		return ret;
    216
    217	*val = (u16)val_32;
    218	return ret;
    219}
    220
    221int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val)
    222{
    223	if (I2C_SIZE(reg) != 4) {
    224		v4l2_err(sd, "Wrong data size\n");
    225		return -EINVAL;
    226	}
    227
    228	return m5mols_read(sd, I2C_SIZE(reg), reg, val);
    229}
    230
    231/**
    232 * m5mols_write - I2C command write function
    233 * @sd: sub-device, as pointed by struct v4l2_subdev
    234 * @reg: combination of size, category and command for the I2C packet
    235 * @val: value to write
    236 *
    237 * Returns 0 on success, or else negative errno.
    238 */
    239int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
    240{
    241	struct i2c_client *client = v4l2_get_subdevdata(sd);
    242	struct m5mols_info *info = to_m5mols(sd);
    243	u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4];
    244	u8 category = I2C_CATEGORY(reg);
    245	u8 cmd = I2C_COMMAND(reg);
    246	u8 size	= I2C_SIZE(reg);
    247	u32 *buf = (u32 *)&wbuf[4];
    248	struct i2c_msg msg[1];
    249	int ret;
    250
    251	if (!client->adapter)
    252		return -ENODEV;
    253
    254	if (size != 1 && size != 2 && size != 4) {
    255		v4l2_err(sd, "Wrong data size\n");
    256		return -EINVAL;
    257	}
    258
    259	msg->addr = client->addr;
    260	msg->flags = 0;
    261	msg->len = (u16)size + 4;
    262	msg->buf = wbuf;
    263	wbuf[0] = size + 4;
    264	wbuf[1] = M5MOLS_BYTE_WRITE;
    265	wbuf[2] = category;
    266	wbuf[3] = cmd;
    267
    268	*buf = m5mols_swap_byte((u8 *)&val, size);
    269
    270	/* minimum stabilization time */
    271	usleep_range(200, 300);
    272
    273	ret = i2c_transfer(client->adapter, msg, 1);
    274	if (ret == 1)
    275		return 0;
    276
    277	if (info->isp_ready)
    278		v4l2_err(sd, "write failed: cat:%02x cmd:%02x ret:%d\n",
    279			 category, cmd, ret);
    280
    281	return ret < 0 ? ret : -EIO;
    282}
    283
    284/**
    285 * m5mols_busy_wait - Busy waiting with I2C register polling
    286 * @sd: sub-device, as pointed by struct v4l2_subdev
    287 * @reg: the I2C_REG() address of an 8-bit status register to check
    288 * @value: expected status register value
    289 * @mask: bit mask for the read status register value
    290 * @timeout: timeout in milliseconds, or -1 for default timeout
    291 *
    292 * The @reg register value is ORed with @mask before comparing with @value.
    293 *
    294 * Return: 0 if the requested condition became true within less than
    295 *         @timeout ms, or else negative errno.
    296 */
    297int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
    298		     int timeout)
    299{
    300	int ms = timeout < 0 ? M5MOLS_BUSY_WAIT_DEF_TIMEOUT : timeout;
    301	unsigned long end = jiffies + msecs_to_jiffies(ms);
    302	u8 status;
    303
    304	do {
    305		int ret = m5mols_read_u8(sd, reg, &status);
    306
    307		if (ret < 0 && !(mask & M5MOLS_I2C_RDY_WAIT_FL))
    308			return ret;
    309		if (!ret && (status & mask & 0xff) == (value & 0xff))
    310			return 0;
    311		usleep_range(100, 250);
    312	} while (ms > 0 && time_is_after_jiffies(end));
    313
    314	return -EBUSY;
    315}
    316
    317/**
    318 * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts
    319 * @sd: sub-device, as pointed by struct v4l2_subdev
    320 * @reg: combination of size, category and command for the I2C packet
    321 *
    322 * Before writing desired interrupt value the INT_FACTOR register should
    323 * be read to clear pending interrupts.
    324 */
    325int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
    326{
    327	struct m5mols_info *info = to_m5mols(sd);
    328	u8 mask = is_available_af(info) ? REG_INT_AF : 0;
    329	u8 dummy;
    330	int ret;
    331
    332	ret = m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &dummy);
    333	if (!ret)
    334		ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask);
    335	return ret;
    336}
    337
    338int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 irq_mask, u32 timeout)
    339{
    340	struct m5mols_info *info = to_m5mols(sd);
    341
    342	int ret = wait_event_interruptible_timeout(info->irq_waitq,
    343				atomic_add_unless(&info->irq_done, -1, 0),
    344				msecs_to_jiffies(timeout));
    345	if (ret <= 0)
    346		return ret ? ret : -ETIMEDOUT;
    347
    348	return m5mols_busy_wait(sd, SYSTEM_INT_FACTOR, irq_mask,
    349				M5MOLS_I2C_RDY_WAIT_FL | irq_mask, -1);
    350}
    351
    352/**
    353 * m5mols_reg_mode - Write the mode and check busy status
    354 * @sd: sub-device, as pointed by struct v4l2_subdev
    355 * @mode: the required operation mode
    356 *
    357 * It always accompanies a little delay changing the M-5MOLS mode, so it is
    358 * needed checking current busy status to guarantee right mode.
    359 */
    360static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
    361{
    362	int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
    363	if (ret < 0)
    364		return ret;
    365	return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff,
    366				M5MOLS_MODE_CHANGE_TIMEOUT);
    367}
    368
    369/**
    370 * m5mols_set_mode - set the M-5MOLS controller mode
    371 * @info: M-5MOLS driver data structure
    372 * @mode: the required operation mode
    373 *
    374 * The commands of M-5MOLS are grouped into specific modes. Each functionality
    375 * can be guaranteed only when the sensor is operating in mode which a command
    376 * belongs to.
    377 */
    378int m5mols_set_mode(struct m5mols_info *info, u8 mode)
    379{
    380	struct v4l2_subdev *sd = &info->sd;
    381	int ret = -EINVAL;
    382	u8 reg;
    383
    384	if (mode < REG_PARAMETER || mode > REG_CAPTURE)
    385		return ret;
    386
    387	ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, &reg);
    388	if (ret || reg == mode)
    389		return ret;
    390
    391	switch (reg) {
    392	case REG_PARAMETER:
    393		ret = m5mols_reg_mode(sd, REG_MONITOR);
    394		if (mode == REG_MONITOR)
    395			break;
    396		if (!ret)
    397			ret = m5mols_reg_mode(sd, REG_CAPTURE);
    398		break;
    399
    400	case REG_MONITOR:
    401		if (mode == REG_PARAMETER) {
    402			ret = m5mols_reg_mode(sd, REG_PARAMETER);
    403			break;
    404		}
    405
    406		ret = m5mols_reg_mode(sd, REG_CAPTURE);
    407		break;
    408
    409	case REG_CAPTURE:
    410		ret = m5mols_reg_mode(sd, REG_MONITOR);
    411		if (mode == REG_MONITOR)
    412			break;
    413		if (!ret)
    414			ret = m5mols_reg_mode(sd, REG_PARAMETER);
    415		break;
    416
    417	default:
    418		v4l2_warn(sd, "Wrong mode: %d\n", mode);
    419	}
    420
    421	if (!ret)
    422		info->mode = mode;
    423
    424	return ret;
    425}
    426
    427/**
    428 * m5mols_get_version - retrieve full revisions information of M-5MOLS
    429 * @sd: sub-device, as pointed by struct v4l2_subdev
    430 *
    431 * The version information includes revisions of hardware and firmware,
    432 * AutoFocus alghorithm version and the version string.
    433 */
    434static int m5mols_get_version(struct v4l2_subdev *sd)
    435{
    436	struct m5mols_info *info = to_m5mols(sd);
    437	struct m5mols_version *ver = &info->ver;
    438	u8 *str = ver->str;
    439	int i;
    440	int ret;
    441
    442	ret = m5mols_read_u8(sd, SYSTEM_VER_CUSTOMER, &ver->customer);
    443	if (!ret)
    444		ret = m5mols_read_u8(sd, SYSTEM_VER_PROJECT, &ver->project);
    445	if (!ret)
    446		ret = m5mols_read_u16(sd, SYSTEM_VER_FIRMWARE, &ver->fw);
    447	if (!ret)
    448		ret = m5mols_read_u16(sd, SYSTEM_VER_HARDWARE, &ver->hw);
    449	if (!ret)
    450		ret = m5mols_read_u16(sd, SYSTEM_VER_PARAMETER, &ver->param);
    451	if (!ret)
    452		ret = m5mols_read_u16(sd, SYSTEM_VER_AWB, &ver->awb);
    453	if (!ret)
    454		ret = m5mols_read_u8(sd, AF_VERSION, &ver->af);
    455	if (ret)
    456		return ret;
    457
    458	for (i = 0; i < VERSION_STRING_SIZE; i++) {
    459		ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &str[i]);
    460		if (ret)
    461			return ret;
    462	}
    463
    464	v4l2_info(sd, "Manufacturer\t[%s]\n",
    465			is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
    466			"Samsung Electro-Mechanics" :
    467			is_manufacturer(info, REG_SAMSUNG_OPTICS) ?
    468			"Samsung Fiber-Optics" :
    469			is_manufacturer(info, REG_SAMSUNG_TECHWIN) ?
    470			"Samsung Techwin" : "None");
    471	v4l2_info(sd, "Customer/Project\t[0x%02x/0x%02x]\n",
    472			info->ver.customer, info->ver.project);
    473
    474	if (!is_available_af(info))
    475		v4l2_info(sd, "No support Auto Focus on this firmware\n");
    476
    477	return ret;
    478}
    479
    480/**
    481 * __find_restype - Lookup M-5MOLS resolution type according to pixel code
    482 * @code: pixel code
    483 */
    484static enum m5mols_restype __find_restype(u32 code)
    485{
    486	enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR;
    487
    488	do {
    489		if (code == m5mols_default_ffmt[type].code)
    490			return type;
    491	} while (type++ != SIZE_DEFAULT_FFMT);
    492
    493	return 0;
    494}
    495
    496/**
    497 * __find_resolution - Lookup preset and type of M-5MOLS's resolution
    498 * @sd: sub-device, as pointed by struct v4l2_subdev
    499 * @mf: pixel format to find/negotiate the resolution preset for
    500 * @type: M-5MOLS resolution type
    501 * @resolution:	M-5MOLS resolution preset register value
    502 *
    503 * Find nearest resolution matching resolution preset and adjust mf
    504 * to supported values.
    505 */
    506static int __find_resolution(struct v4l2_subdev *sd,
    507			     struct v4l2_mbus_framefmt *mf,
    508			     enum m5mols_restype *type,
    509			     u32 *resolution)
    510{
    511	const struct m5mols_resolution *fsize = &m5mols_reg_res[0];
    512	const struct m5mols_resolution *match = NULL;
    513	enum m5mols_restype stype = __find_restype(mf->code);
    514	int i = ARRAY_SIZE(m5mols_reg_res);
    515	unsigned int min_err = ~0;
    516
    517	while (i--) {
    518		int err;
    519		if (stype == fsize->type) {
    520			err = abs(fsize->width - mf->width)
    521				+ abs(fsize->height - mf->height);
    522
    523			if (err < min_err) {
    524				min_err = err;
    525				match = fsize;
    526			}
    527		}
    528		fsize++;
    529	}
    530	if (match) {
    531		mf->width  = match->width;
    532		mf->height = match->height;
    533		*resolution = match->reg;
    534		*type = stype;
    535		return 0;
    536	}
    537
    538	return -EINVAL;
    539}
    540
    541static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info,
    542				struct v4l2_subdev_state *sd_state,
    543				enum v4l2_subdev_format_whence which,
    544				enum m5mols_restype type)
    545{
    546	if (which == V4L2_SUBDEV_FORMAT_TRY)
    547		return sd_state ? v4l2_subdev_get_try_format(&info->sd,
    548							     sd_state, 0) : NULL;
    549
    550	return &info->ffmt[type];
    551}
    552
    553static int m5mols_get_fmt(struct v4l2_subdev *sd,
    554			  struct v4l2_subdev_state *sd_state,
    555			  struct v4l2_subdev_format *fmt)
    556{
    557	struct m5mols_info *info = to_m5mols(sd);
    558	struct v4l2_mbus_framefmt *format;
    559	int ret = 0;
    560
    561	mutex_lock(&info->lock);
    562
    563	format = __find_format(info, sd_state, fmt->which, info->res_type);
    564	if (format)
    565		fmt->format = *format;
    566	else
    567		ret = -EINVAL;
    568
    569	mutex_unlock(&info->lock);
    570	return ret;
    571}
    572
    573static int m5mols_set_fmt(struct v4l2_subdev *sd,
    574			  struct v4l2_subdev_state *sd_state,
    575			  struct v4l2_subdev_format *fmt)
    576{
    577	struct m5mols_info *info = to_m5mols(sd);
    578	struct v4l2_mbus_framefmt *format = &fmt->format;
    579	struct v4l2_mbus_framefmt *sfmt;
    580	enum m5mols_restype type;
    581	u32 resolution = 0;
    582	int ret;
    583
    584	ret = __find_resolution(sd, format, &type, &resolution);
    585	if (ret < 0)
    586		return ret;
    587
    588	sfmt = __find_format(info, sd_state, fmt->which, type);
    589	if (!sfmt)
    590		return 0;
    591
    592	mutex_lock(&info->lock);
    593
    594	format->code = m5mols_default_ffmt[type].code;
    595	format->colorspace = V4L2_COLORSPACE_JPEG;
    596	format->field = V4L2_FIELD_NONE;
    597
    598	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
    599		*sfmt = *format;
    600		info->resolution = resolution;
    601		info->res_type = type;
    602	}
    603
    604	mutex_unlock(&info->lock);
    605	return ret;
    606}
    607
    608static int m5mols_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
    609				 struct v4l2_mbus_frame_desc *fd)
    610{
    611	struct m5mols_info *info = to_m5mols(sd);
    612
    613	if (pad != 0 || fd == NULL)
    614		return -EINVAL;
    615
    616	mutex_lock(&info->lock);
    617	/*
    618	 * .get_frame_desc is only used for compressed formats,
    619	 * thus we always return the capture frame parameters here.
    620	 */
    621	fd->entry[0].length = info->cap.buf_size;
    622	fd->entry[0].pixelcode = info->ffmt[M5MOLS_RESTYPE_CAPTURE].code;
    623	mutex_unlock(&info->lock);
    624
    625	fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
    626	fd->num_entries = 1;
    627
    628	return 0;
    629}
    630
    631static int m5mols_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
    632				 struct v4l2_mbus_frame_desc *fd)
    633{
    634	struct m5mols_info *info = to_m5mols(sd);
    635	struct v4l2_mbus_framefmt *mf = &info->ffmt[M5MOLS_RESTYPE_CAPTURE];
    636
    637	if (pad != 0 || fd == NULL)
    638		return -EINVAL;
    639
    640	fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
    641	fd->num_entries = 1;
    642	fd->entry[0].length = clamp_t(u32, fd->entry[0].length,
    643				      mf->width * mf->height,
    644				      M5MOLS_MAIN_JPEG_SIZE_MAX);
    645	mutex_lock(&info->lock);
    646	info->cap.buf_size = fd->entry[0].length;
    647	mutex_unlock(&info->lock);
    648
    649	return 0;
    650}
    651
    652
    653static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
    654				 struct v4l2_subdev_state *sd_state,
    655				 struct v4l2_subdev_mbus_code_enum *code)
    656{
    657	if (!code || code->index >= SIZE_DEFAULT_FFMT)
    658		return -EINVAL;
    659
    660	code->code = m5mols_default_ffmt[code->index].code;
    661
    662	return 0;
    663}
    664
    665static const struct v4l2_subdev_pad_ops m5mols_pad_ops = {
    666	.enum_mbus_code	= m5mols_enum_mbus_code,
    667	.get_fmt	= m5mols_get_fmt,
    668	.set_fmt	= m5mols_set_fmt,
    669	.get_frame_desc	= m5mols_get_frame_desc,
    670	.set_frame_desc	= m5mols_set_frame_desc,
    671};
    672
    673/**
    674 * m5mols_restore_controls - Apply current control values to the registers
    675 * @info: M-5MOLS driver data structure
    676 *
    677 * m5mols_do_scenemode() handles all parameters for which there is yet no
    678 * individual control. It should be replaced at some point by setting each
    679 * control individually, in required register set up order.
    680 */
    681int m5mols_restore_controls(struct m5mols_info *info)
    682{
    683	int ret;
    684
    685	if (info->ctrl_sync)
    686		return 0;
    687
    688	ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL);
    689	if (ret)
    690		return ret;
    691
    692	ret = v4l2_ctrl_handler_setup(&info->handle);
    693	info->ctrl_sync = !ret;
    694
    695	return ret;
    696}
    697
    698/**
    699 * m5mols_start_monitor - Start the monitor mode
    700 * @info: M-5MOLS driver data structure
    701 *
    702 * Before applying the controls setup the resolution and frame rate
    703 * in PARAMETER mode, and then switch over to MONITOR mode.
    704 */
    705static int m5mols_start_monitor(struct m5mols_info *info)
    706{
    707	struct v4l2_subdev *sd = &info->sd;
    708	int ret;
    709
    710	ret = m5mols_set_mode(info, REG_PARAMETER);
    711	if (!ret)
    712		ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution);
    713	if (!ret)
    714		ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30);
    715	if (!ret)
    716		ret = m5mols_set_mode(info, REG_MONITOR);
    717	if (!ret)
    718		ret = m5mols_restore_controls(info);
    719
    720	return ret;
    721}
    722
    723static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
    724{
    725	struct m5mols_info *info = to_m5mols(sd);
    726	u32 code;
    727	int ret;
    728
    729	mutex_lock(&info->lock);
    730	code = info->ffmt[info->res_type].code;
    731
    732	if (enable) {
    733		if (is_code(code, M5MOLS_RESTYPE_MONITOR))
    734			ret = m5mols_start_monitor(info);
    735		else if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
    736			ret = m5mols_start_capture(info);
    737		else
    738			ret = -EINVAL;
    739	} else {
    740		ret = m5mols_set_mode(info, REG_PARAMETER);
    741	}
    742
    743	mutex_unlock(&info->lock);
    744	return ret;
    745}
    746
    747static const struct v4l2_subdev_video_ops m5mols_video_ops = {
    748	.s_stream	= m5mols_s_stream,
    749};
    750
    751static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
    752{
    753	struct v4l2_subdev *sd = &info->sd;
    754	struct i2c_client *client = v4l2_get_subdevdata(sd);
    755	int ret;
    756
    757	if (info->power == enable)
    758		return 0;
    759
    760	if (enable) {
    761		if (info->set_power) {
    762			ret = info->set_power(&client->dev, 1);
    763			if (ret)
    764				return ret;
    765		}
    766
    767		ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
    768		if (ret) {
    769			if (info->set_power)
    770				info->set_power(&client->dev, 0);
    771			return ret;
    772		}
    773
    774		gpiod_set_value(info->reset, 0);
    775		info->power = 1;
    776
    777		return ret;
    778	}
    779
    780	ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
    781	if (ret)
    782		return ret;
    783
    784	if (info->set_power)
    785		info->set_power(&client->dev, 0);
    786
    787	gpiod_set_value(info->reset, 1);
    788
    789	info->isp_ready = 0;
    790	info->power = 0;
    791
    792	return ret;
    793}
    794
    795/* m5mols_update_fw - optional firmware update routine */
    796int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd,
    797		int (*set_power)(struct m5mols_info *, bool))
    798{
    799	return 0;
    800}
    801
    802/**
    803 * m5mols_fw_start - M-5MOLS internal ARM controller initialization
    804 * @sd: sub-device, as pointed by struct v4l2_subdev
    805 *
    806 * Execute the M-5MOLS internal ARM controller initialization sequence.
    807 * This function should be called after the supply voltage has been
    808 * applied and before any requests to the device are made.
    809 */
    810static int m5mols_fw_start(struct v4l2_subdev *sd)
    811{
    812	struct m5mols_info *info = to_m5mols(sd);
    813	int ret;
    814
    815	atomic_set(&info->irq_done, 0);
    816	/* Wait until I2C slave is initialized in Flash Writer mode */
    817	ret = m5mols_busy_wait(sd, FLASH_CAM_START, REG_IN_FLASH_MODE,
    818			       M5MOLS_I2C_RDY_WAIT_FL | 0xff, -1);
    819	if (!ret)
    820		ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
    821	if (!ret)
    822		ret = m5mols_wait_interrupt(sd, REG_INT_MODE, 2000);
    823	if (ret < 0)
    824		return ret;
    825
    826	info->isp_ready = 1;
    827
    828	ret = m5mols_get_version(sd);
    829	if (!ret)
    830		ret = m5mols_update_fw(sd, m5mols_sensor_power);
    831	if (ret)
    832		return ret;
    833
    834	v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n");
    835
    836	ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI);
    837	if (!ret)
    838		ret = m5mols_enable_interrupt(sd,
    839				REG_INT_AF | REG_INT_CAPTURE);
    840
    841	return ret;
    842}
    843
    844/* Execute the lens soft-landing algorithm */
    845static int m5mols_auto_focus_stop(struct m5mols_info *info)
    846{
    847	int ret;
    848
    849	ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
    850	if (!ret)
    851		ret = m5mols_write(&info->sd, AF_MODE, REG_AF_POWEROFF);
    852	if (!ret)
    853		ret = m5mols_busy_wait(&info->sd, SYSTEM_STATUS, REG_AF_IDLE,
    854				       0xff, -1);
    855	return ret;
    856}
    857
    858/**
    859 * m5mols_s_power - Main sensor power control function
    860 * @sd: sub-device, as pointed by struct v4l2_subdev
    861 * @on: if true, powers on the device; powers off otherwise.
    862 *
    863 * To prevent breaking the lens when the sensor is powered off the Soft-Landing
    864 * algorithm is called where available. The Soft-Landing algorithm availability
    865 * dependends on the firmware provider.
    866 */
    867static int m5mols_s_power(struct v4l2_subdev *sd, int on)
    868{
    869	struct m5mols_info *info = to_m5mols(sd);
    870	int ret;
    871
    872	mutex_lock(&info->lock);
    873
    874	if (on) {
    875		ret = m5mols_sensor_power(info, true);
    876		if (!ret)
    877			ret = m5mols_fw_start(sd);
    878	} else {
    879		if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
    880			ret = m5mols_set_mode(info, REG_MONITOR);
    881			if (!ret)
    882				ret = m5mols_auto_focus_stop(info);
    883			if (ret < 0)
    884				v4l2_warn(sd, "Soft landing lens failed\n");
    885		}
    886		ret = m5mols_sensor_power(info, false);
    887
    888		info->ctrl_sync = 0;
    889	}
    890
    891	mutex_unlock(&info->lock);
    892	return ret;
    893}
    894
    895static int m5mols_log_status(struct v4l2_subdev *sd)
    896{
    897	struct m5mols_info *info = to_m5mols(sd);
    898
    899	v4l2_ctrl_handler_log_status(&info->handle, sd->name);
    900
    901	return 0;
    902}
    903
    904static const struct v4l2_subdev_core_ops m5mols_core_ops = {
    905	.s_power	= m5mols_s_power,
    906	.log_status	= m5mols_log_status,
    907};
    908
    909/*
    910 * V4L2 subdev internal operations
    911 */
    912static int m5mols_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
    913{
    914	struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd,
    915								       fh->state,
    916								       0);
    917
    918	*format = m5mols_default_ffmt[0];
    919	return 0;
    920}
    921
    922static const struct v4l2_subdev_internal_ops m5mols_subdev_internal_ops = {
    923	.open		= m5mols_open,
    924};
    925
    926static const struct v4l2_subdev_ops m5mols_ops = {
    927	.core		= &m5mols_core_ops,
    928	.pad		= &m5mols_pad_ops,
    929	.video		= &m5mols_video_ops,
    930};
    931
    932static irqreturn_t m5mols_irq_handler(int irq, void *data)
    933{
    934	struct m5mols_info *info = to_m5mols(data);
    935
    936	atomic_set(&info->irq_done, 1);
    937	wake_up_interruptible(&info->irq_waitq);
    938
    939	return IRQ_HANDLED;
    940}
    941
    942static int m5mols_probe(struct i2c_client *client,
    943			const struct i2c_device_id *id)
    944{
    945	const struct m5mols_platform_data *pdata = client->dev.platform_data;
    946	struct m5mols_info *info;
    947	struct v4l2_subdev *sd;
    948	int ret;
    949
    950	if (pdata == NULL) {
    951		dev_err(&client->dev, "No platform data\n");
    952		return -EINVAL;
    953	}
    954
    955	if (!client->irq) {
    956		dev_err(&client->dev, "Interrupt not assigned\n");
    957		return -EINVAL;
    958	}
    959
    960	info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
    961	if (!info)
    962		return -ENOMEM;
    963
    964	/* This asserts reset, descriptor shall have polarity specified */
    965	info->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
    966	if (IS_ERR(info->reset))
    967		return PTR_ERR(info->reset);
    968	/* Notice: the "N" in M5MOLS_NRST implies active low */
    969	gpiod_set_consumer_name(info->reset, "M5MOLS_NRST");
    970
    971	info->pdata = pdata;
    972	info->set_power	= pdata->set_power;
    973
    974	ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies),
    975				      supplies);
    976	if (ret) {
    977		dev_err(&client->dev, "Failed to get regulators: %d\n", ret);
    978		return ret;
    979	}
    980
    981	sd = &info->sd;
    982	v4l2_i2c_subdev_init(sd, client, &m5mols_ops);
    983	/* Static name; NEVER use in new drivers! */
    984	strscpy(sd->name, MODULE_NAME, sizeof(sd->name));
    985	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
    986
    987	sd->internal_ops = &m5mols_subdev_internal_ops;
    988	info->pad.flags = MEDIA_PAD_FL_SOURCE;
    989	ret = media_entity_pads_init(&sd->entity, 1, &info->pad);
    990	if (ret < 0)
    991		return ret;
    992	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
    993
    994	init_waitqueue_head(&info->irq_waitq);
    995	mutex_init(&info->lock);
    996
    997	ret = devm_request_irq(&client->dev, client->irq, m5mols_irq_handler,
    998			       IRQF_TRIGGER_RISING, MODULE_NAME, sd);
    999	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;
   1018error:
   1019	media_entity_cleanup(&sd->entity);
   1020	return ret;
   1021}
   1022
   1023static 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
   1034static const struct i2c_device_id m5mols_id[] = {
   1035	{ MODULE_NAME, 0 },
   1036	{ },
   1037};
   1038MODULE_DEVICE_TABLE(i2c, m5mols_id);
   1039
   1040static 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
   1049module_i2c_driver(m5mols_i2c_driver);
   1050
   1051MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
   1052MODULE_AUTHOR("Dongsoo Kim <dongsoo45.kim@samsung.com>");
   1053MODULE_DESCRIPTION("Fujitsu M-5MOLS 8M Pixel camera driver");
   1054MODULE_LICENSE("GPL");