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

s5k6aa.c (44486B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Driver for Samsung S5K6AAFX SXGA 1/6" 1.3M CMOS Image Sensor
      4 * with embedded SoC ISP.
      5 *
      6 * Copyright (C) 2011, Samsung Electronics Co., Ltd.
      7 * Sylwester Nawrocki <s.nawrocki@samsung.com>
      8 *
      9 * Based on a driver authored by Dongsoo Nathaniel Kim.
     10 * Copyright (C) 2009, Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
     11 */
     12
     13#include <linux/clk.h>
     14#include <linux/delay.h>
     15#include <linux/gpio.h>
     16#include <linux/i2c.h>
     17#include <linux/media.h>
     18#include <linux/module.h>
     19#include <linux/regulator/consumer.h>
     20#include <linux/slab.h>
     21
     22#include <media/media-entity.h>
     23#include <media/v4l2-ctrls.h>
     24#include <media/v4l2-device.h>
     25#include <media/v4l2-subdev.h>
     26#include <media/v4l2-mediabus.h>
     27#include <media/i2c/s5k6aa.h>
     28
     29static int debug;
     30module_param(debug, int, 0644);
     31
     32#define DRIVER_NAME			"S5K6AA"
     33
     34/* The token to indicate array termination */
     35#define S5K6AA_TERM			0xffff
     36#define S5K6AA_OUT_WIDTH_DEF		640
     37#define S5K6AA_OUT_HEIGHT_DEF		480
     38#define S5K6AA_WIN_WIDTH_MAX		1280
     39#define S5K6AA_WIN_HEIGHT_MAX		1024
     40#define S5K6AA_WIN_WIDTH_MIN		8
     41#define S5K6AA_WIN_HEIGHT_MIN		8
     42
     43/*
     44 * H/W register Interface (0xD0000000 - 0xD0000FFF)
     45 */
     46#define AHB_MSB_ADDR_PTR		0xfcfc
     47#define GEN_REG_OFFSH			0xd000
     48#define REG_CMDWR_ADDRH			0x0028
     49#define REG_CMDWR_ADDRL			0x002a
     50#define REG_CMDRD_ADDRH			0x002c
     51#define REG_CMDRD_ADDRL			0x002e
     52#define REG_CMDBUF0_ADDR		0x0f12
     53#define REG_CMDBUF1_ADDR		0x0f10
     54
     55/*
     56 * Host S/W Register interface (0x70000000 - 0x70002000)
     57 * The value of the two most significant address bytes is 0x7000,
     58 * (HOST_SWIF_OFFS_H). The register addresses below specify 2 LSBs.
     59 */
     60#define HOST_SWIF_OFFSH			0x7000
     61
     62/* Initialization parameters */
     63/* Master clock frequency in KHz */
     64#define REG_I_INCLK_FREQ_L		0x01b8
     65#define REG_I_INCLK_FREQ_H		0x01ba
     66#define  MIN_MCLK_FREQ_KHZ		6000U
     67#define  MAX_MCLK_FREQ_KHZ		27000U
     68#define REG_I_USE_NPVI_CLOCKS		0x01c6
     69#define REG_I_USE_NMIPI_CLOCKS		0x01c8
     70
     71/* Clock configurations, n = 0..2. REG_I_* frequency unit is 4 kHz. */
     72#define REG_I_OPCLK_4KHZ(n)		((n) * 6 + 0x01cc)
     73#define REG_I_MIN_OUTRATE_4KHZ(n)	((n) * 6 + 0x01ce)
     74#define REG_I_MAX_OUTRATE_4KHZ(n)	((n) * 6 + 0x01d0)
     75#define  SYS_PLL_OUT_FREQ		(48000000 / 4000)
     76#define  PCLK_FREQ_MIN			(24000000 / 4000)
     77#define  PCLK_FREQ_MAX			(48000000 / 4000)
     78#define REG_I_INIT_PARAMS_UPDATED	0x01e0
     79#define REG_I_ERROR_INFO		0x01e2
     80
     81/* General purpose parameters */
     82#define REG_USER_BRIGHTNESS		0x01e4
     83#define REG_USER_CONTRAST		0x01e6
     84#define REG_USER_SATURATION		0x01e8
     85#define REG_USER_SHARPBLUR		0x01ea
     86
     87#define REG_G_SPEC_EFFECTS		0x01ee
     88#define REG_G_ENABLE_PREV		0x01f0
     89#define REG_G_ENABLE_PREV_CHG		0x01f2
     90#define REG_G_NEW_CFG_SYNC		0x01f8
     91#define REG_G_PREVZOOM_IN_WIDTH		0x020a
     92#define REG_G_PREVZOOM_IN_HEIGHT	0x020c
     93#define REG_G_PREVZOOM_IN_XOFFS		0x020e
     94#define REG_G_PREVZOOM_IN_YOFFS		0x0210
     95#define REG_G_INPUTS_CHANGE_REQ		0x021a
     96#define REG_G_ACTIVE_PREV_CFG		0x021c
     97#define REG_G_PREV_CFG_CHG		0x021e
     98#define REG_G_PREV_OPEN_AFTER_CH	0x0220
     99#define REG_G_PREV_CFG_ERROR		0x0222
    100
    101/* Preview control section. n = 0...4. */
    102#define PREG(n, x)			((n) * 0x26 + x)
    103#define REG_P_OUT_WIDTH(n)		PREG(n, 0x0242)
    104#define REG_P_OUT_HEIGHT(n)		PREG(n, 0x0244)
    105#define REG_P_FMT(n)			PREG(n, 0x0246)
    106#define REG_P_MAX_OUT_RATE(n)		PREG(n, 0x0248)
    107#define REG_P_MIN_OUT_RATE(n)		PREG(n, 0x024a)
    108#define REG_P_PVI_MASK(n)		PREG(n, 0x024c)
    109#define REG_P_CLK_INDEX(n)		PREG(n, 0x024e)
    110#define REG_P_FR_RATE_TYPE(n)		PREG(n, 0x0250)
    111#define  FR_RATE_DYNAMIC		0
    112#define  FR_RATE_FIXED			1
    113#define  FR_RATE_FIXED_ACCURATE		2
    114#define REG_P_FR_RATE_Q_TYPE(n)		PREG(n, 0x0252)
    115#define  FR_RATE_Q_BEST_FRRATE		1 /* Binning enabled */
    116#define  FR_RATE_Q_BEST_QUALITY		2 /* Binning disabled */
    117/* Frame period in 0.1 ms units */
    118#define REG_P_MAX_FR_TIME(n)		PREG(n, 0x0254)
    119#define REG_P_MIN_FR_TIME(n)		PREG(n, 0x0256)
    120/* Conversion to REG_P_[MAX/MIN]_FR_TIME value; __t: time in us */
    121#define  US_TO_FR_TIME(__t)		((__t) / 100)
    122#define  S5K6AA_MIN_FR_TIME		33300  /* us */
    123#define  S5K6AA_MAX_FR_TIME		650000 /* us */
    124#define  S5K6AA_MAX_HIGHRES_FR_TIME	666    /* x100 us */
    125/* The below 5 registers are for "device correction" values */
    126#define REG_P_COLORTEMP(n)		PREG(n, 0x025e)
    127#define REG_P_PREV_MIRROR(n)		PREG(n, 0x0262)
    128
    129/* Extended image property controls */
    130/* Exposure time in 10 us units */
    131#define REG_SF_USR_EXPOSURE_L		0x03c6
    132#define REG_SF_USR_EXPOSURE_H		0x03c8
    133#define REG_SF_USR_EXPOSURE_CHG		0x03ca
    134#define REG_SF_USR_TOT_GAIN		0x03cc
    135#define REG_SF_USR_TOT_GAIN_CHG		0x03ce
    136#define REG_SF_RGAIN			0x03d0
    137#define REG_SF_RGAIN_CHG		0x03d2
    138#define REG_SF_GGAIN			0x03d4
    139#define REG_SF_GGAIN_CHG		0x03d6
    140#define REG_SF_BGAIN			0x03d8
    141#define REG_SF_BGAIN_CHG		0x03da
    142#define REG_SF_FLICKER_QUANT		0x03dc
    143#define REG_SF_FLICKER_QUANT_CHG	0x03de
    144
    145/* Output interface (parallel/MIPI) setup */
    146#define REG_OIF_EN_MIPI_LANES		0x03fa
    147#define REG_OIF_EN_PACKETS		0x03fc
    148#define REG_OIF_CFG_CHG			0x03fe
    149
    150/* Auto-algorithms enable mask */
    151#define REG_DBG_AUTOALG_EN		0x0400
    152#define  AALG_ALL_EN_MASK		(1 << 0)
    153#define  AALG_AE_EN_MASK		(1 << 1)
    154#define  AALG_DIVLEI_EN_MASK		(1 << 2)
    155#define  AALG_WB_EN_MASK		(1 << 3)
    156#define  AALG_FLICKER_EN_MASK		(1 << 5)
    157#define  AALG_FIT_EN_MASK		(1 << 6)
    158#define  AALG_WRHW_EN_MASK		(1 << 7)
    159
    160/* Firmware revision information */
    161#define REG_FW_APIVER			0x012e
    162#define  S5K6AAFX_FW_APIVER		0x0001
    163#define REG_FW_REVISION			0x0130
    164
    165/* For now we use only one user configuration register set */
    166#define S5K6AA_MAX_PRESETS		1
    167
    168static const char * const s5k6aa_supply_names[] = {
    169	"vdd_core",	/* Digital core supply 1.5V (1.4V to 1.6V) */
    170	"vdda",		/* Analog power supply 2.8V (2.6V to 3.0V) */
    171	"vdd_reg",	/* Regulator input power 1.8V (1.7V to 1.9V)
    172			   or 2.8V (2.6V to 3.0) */
    173	"vddio",	/* I/O supply 1.8V (1.65V to 1.95V)
    174			   or 2.8V (2.5V to 3.1V) */
    175};
    176#define S5K6AA_NUM_SUPPLIES ARRAY_SIZE(s5k6aa_supply_names)
    177
    178enum s5k6aa_gpio_id {
    179	STBY,
    180	RSET,
    181	GPIO_NUM,
    182};
    183
    184struct s5k6aa_regval {
    185	u16 addr;
    186	u16 val;
    187};
    188
    189struct s5k6aa_pixfmt {
    190	u32 code;
    191	u32 colorspace;
    192	/* REG_P_FMT(x) register value */
    193	u16 reg_p_fmt;
    194};
    195
    196struct s5k6aa_preset {
    197	/* output pixel format and resolution */
    198	struct v4l2_mbus_framefmt mbus_fmt;
    199	u8 clk_id;
    200	u8 index;
    201};
    202
    203struct s5k6aa_ctrls {
    204	struct v4l2_ctrl_handler handler;
    205	/* Auto / manual white balance cluster */
    206	struct v4l2_ctrl *awb;
    207	struct v4l2_ctrl *gain_red;
    208	struct v4l2_ctrl *gain_blue;
    209	struct v4l2_ctrl *gain_green;
    210	/* Mirror cluster */
    211	struct v4l2_ctrl *hflip;
    212	struct v4l2_ctrl *vflip;
    213	/* Auto exposure / manual exposure and gain cluster */
    214	struct v4l2_ctrl *auto_exp;
    215	struct v4l2_ctrl *exposure;
    216	struct v4l2_ctrl *gain;
    217};
    218
    219struct s5k6aa_interval {
    220	u16 reg_fr_time;
    221	struct v4l2_fract interval;
    222	/* Maximum rectangle for the interval */
    223	struct v4l2_frmsize_discrete size;
    224};
    225
    226struct s5k6aa {
    227	struct v4l2_subdev sd;
    228	struct media_pad pad;
    229
    230	enum v4l2_mbus_type bus_type;
    231	u8 mipi_lanes;
    232
    233	int (*s_power)(int enable);
    234	struct regulator_bulk_data supplies[S5K6AA_NUM_SUPPLIES];
    235	struct s5k6aa_gpio gpio[GPIO_NUM];
    236
    237	/* external master clock frequency */
    238	unsigned long mclk_frequency;
    239	/* ISP internal master clock frequency */
    240	u16 clk_fop;
    241	/* output pixel clock frequency range */
    242	u16 pclk_fmin;
    243	u16 pclk_fmax;
    244
    245	unsigned int inv_hflip:1;
    246	unsigned int inv_vflip:1;
    247
    248	/* protects the struct members below */
    249	struct mutex lock;
    250
    251	/* sensor matrix scan window */
    252	struct v4l2_rect ccd_rect;
    253
    254	struct s5k6aa_ctrls ctrls;
    255	struct s5k6aa_preset presets[S5K6AA_MAX_PRESETS];
    256	struct s5k6aa_preset *preset;
    257	const struct s5k6aa_interval *fiv;
    258
    259	unsigned int streaming:1;
    260	unsigned int apply_cfg:1;
    261	unsigned int apply_crop:1;
    262	unsigned int power;
    263};
    264
    265static struct s5k6aa_regval s5k6aa_analog_config[] = {
    266	/* Analog settings */
    267	{ 0x112a, 0x0000 }, { 0x1132, 0x0000 },
    268	{ 0x113e, 0x0000 }, { 0x115c, 0x0000 },
    269	{ 0x1164, 0x0000 }, { 0x1174, 0x0000 },
    270	{ 0x1178, 0x0000 }, { 0x077a, 0x0000 },
    271	{ 0x077c, 0x0000 }, { 0x077e, 0x0000 },
    272	{ 0x0780, 0x0000 }, { 0x0782, 0x0000 },
    273	{ 0x0784, 0x0000 }, { 0x0786, 0x0000 },
    274	{ 0x0788, 0x0000 }, { 0x07a2, 0x0000 },
    275	{ 0x07a4, 0x0000 }, { 0x07a6, 0x0000 },
    276	{ 0x07a8, 0x0000 }, { 0x07b6, 0x0000 },
    277	{ 0x07b8, 0x0002 }, { 0x07ba, 0x0004 },
    278	{ 0x07bc, 0x0004 }, { 0x07be, 0x0005 },
    279	{ 0x07c0, 0x0005 }, { S5K6AA_TERM, 0 },
    280};
    281
    282/* TODO: Add RGB888 and Bayer format */
    283static const struct s5k6aa_pixfmt s5k6aa_formats[] = {
    284	{ MEDIA_BUS_FMT_YUYV8_2X8,	V4L2_COLORSPACE_JPEG,	5 },
    285	/* range 16-240 */
    286	{ MEDIA_BUS_FMT_YUYV8_2X8,	V4L2_COLORSPACE_REC709,	6 },
    287	{ MEDIA_BUS_FMT_RGB565_2X8_BE,	V4L2_COLORSPACE_JPEG,	0 },
    288};
    289
    290static const struct s5k6aa_interval s5k6aa_intervals[] = {
    291	{ 1000, {10000, 1000000}, {1280, 1024} }, /* 10 fps */
    292	{ 666,  {15000, 1000000}, {1280, 1024} }, /* 15 fps */
    293	{ 500,  {20000, 1000000}, {1280, 720} },  /* 20 fps */
    294	{ 400,  {25000, 1000000}, {640, 480} },   /* 25 fps */
    295	{ 333,  {33300, 1000000}, {640, 480} },   /* 30 fps */
    296};
    297
    298#define S5K6AA_INTERVAL_DEF_INDEX 1 /* 15 fps */
    299
    300static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
    301{
    302	return &container_of(ctrl->handler, struct s5k6aa, ctrls.handler)->sd;
    303}
    304
    305static inline struct s5k6aa *to_s5k6aa(struct v4l2_subdev *sd)
    306{
    307	return container_of(sd, struct s5k6aa, sd);
    308}
    309
    310/* Set initial values for all preview presets */
    311static void s5k6aa_presets_data_init(struct s5k6aa *s5k6aa)
    312{
    313	struct s5k6aa_preset *preset = &s5k6aa->presets[0];
    314	int i;
    315
    316	for (i = 0; i < S5K6AA_MAX_PRESETS; i++) {
    317		preset->mbus_fmt.width	= S5K6AA_OUT_WIDTH_DEF;
    318		preset->mbus_fmt.height	= S5K6AA_OUT_HEIGHT_DEF;
    319		preset->mbus_fmt.code	= s5k6aa_formats[0].code;
    320		preset->index		= i;
    321		preset->clk_id		= 0;
    322		preset++;
    323	}
    324
    325	s5k6aa->fiv = &s5k6aa_intervals[S5K6AA_INTERVAL_DEF_INDEX];
    326	s5k6aa->preset = &s5k6aa->presets[0];
    327}
    328
    329static int s5k6aa_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
    330{
    331	u8 wbuf[2] = {addr >> 8, addr & 0xFF};
    332	struct i2c_msg msg[2];
    333	u8 rbuf[2];
    334	int ret;
    335
    336	msg[0].addr = client->addr;
    337	msg[0].flags = 0;
    338	msg[0].len = 2;
    339	msg[0].buf = wbuf;
    340
    341	msg[1].addr = client->addr;
    342	msg[1].flags = I2C_M_RD;
    343	msg[1].len = 2;
    344	msg[1].buf = rbuf;
    345
    346	ret = i2c_transfer(client->adapter, msg, 2);
    347	*val = be16_to_cpu(*((__be16 *)rbuf));
    348
    349	v4l2_dbg(3, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
    350
    351	return ret == 2 ? 0 : ret;
    352}
    353
    354static int s5k6aa_i2c_write(struct i2c_client *client, u16 addr, u16 val)
    355{
    356	u8 buf[4] = {addr >> 8, addr & 0xFF, val >> 8, val & 0xFF};
    357
    358	int ret = i2c_master_send(client, buf, 4);
    359	v4l2_dbg(3, debug, client, "i2c_write: 0x%04X : 0x%04x\n", addr, val);
    360
    361	return ret == 4 ? 0 : ret;
    362}
    363
    364/* The command register write, assumes Command_Wr_addH = 0x7000. */
    365static int s5k6aa_write(struct i2c_client *c, u16 addr, u16 val)
    366{
    367	int ret = s5k6aa_i2c_write(c, REG_CMDWR_ADDRL, addr);
    368	if (ret)
    369		return ret;
    370	return s5k6aa_i2c_write(c, REG_CMDBUF0_ADDR, val);
    371}
    372
    373/* The command register read, assumes Command_Rd_addH = 0x7000. */
    374static int s5k6aa_read(struct i2c_client *client, u16 addr, u16 *val)
    375{
    376	int ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRL, addr);
    377	if (ret)
    378		return ret;
    379	return s5k6aa_i2c_read(client, REG_CMDBUF0_ADDR, val);
    380}
    381
    382static int s5k6aa_write_array(struct v4l2_subdev *sd,
    383			      const struct s5k6aa_regval *msg)
    384{
    385	struct i2c_client *client = v4l2_get_subdevdata(sd);
    386	u16 addr_incr = 0;
    387	int ret = 0;
    388
    389	while (msg->addr != S5K6AA_TERM) {
    390		if (addr_incr != 2)
    391			ret = s5k6aa_i2c_write(client, REG_CMDWR_ADDRL,
    392					       msg->addr);
    393		if (ret)
    394			break;
    395		ret = s5k6aa_i2c_write(client, REG_CMDBUF0_ADDR, msg->val);
    396		if (ret)
    397			break;
    398		/* Assume that msg->addr is always less than 0xfffc */
    399		addr_incr = (msg + 1)->addr - msg->addr;
    400		msg++;
    401	}
    402
    403	return ret;
    404}
    405
    406/* Configure the AHB high address bytes for GTG registers access */
    407static int s5k6aa_set_ahb_address(struct i2c_client *client)
    408{
    409	int ret = s5k6aa_i2c_write(client, AHB_MSB_ADDR_PTR, GEN_REG_OFFSH);
    410	if (ret)
    411		return ret;
    412	ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRH, HOST_SWIF_OFFSH);
    413	if (ret)
    414		return ret;
    415	return s5k6aa_i2c_write(client, REG_CMDWR_ADDRH, HOST_SWIF_OFFSH);
    416}
    417
    418/**
    419 * s5k6aa_configure_pixel_clocks - apply ISP main clock/PLL configuration
    420 * @s5k6aa: pointer to &struct s5k6aa describing the device
    421 *
    422 * Configure the internal ISP PLL for the required output frequency.
    423 * Locking: called with s5k6aa.lock mutex held.
    424 */
    425static int s5k6aa_configure_pixel_clocks(struct s5k6aa *s5k6aa)
    426{
    427	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
    428	unsigned long fmclk = s5k6aa->mclk_frequency / 1000;
    429	u16 status;
    430	int ret;
    431
    432	if (WARN(fmclk < MIN_MCLK_FREQ_KHZ || fmclk > MAX_MCLK_FREQ_KHZ,
    433		 "Invalid clock frequency: %ld\n", fmclk))
    434		return -EINVAL;
    435
    436	s5k6aa->pclk_fmin = PCLK_FREQ_MIN;
    437	s5k6aa->pclk_fmax = PCLK_FREQ_MAX;
    438	s5k6aa->clk_fop = SYS_PLL_OUT_FREQ;
    439
    440	/* External input clock frequency in kHz */
    441	ret = s5k6aa_write(c, REG_I_INCLK_FREQ_H, fmclk >> 16);
    442	if (!ret)
    443		ret = s5k6aa_write(c, REG_I_INCLK_FREQ_L, fmclk & 0xFFFF);
    444	if (!ret)
    445		ret = s5k6aa_write(c, REG_I_USE_NPVI_CLOCKS, 1);
    446	/* Internal PLL frequency */
    447	if (!ret)
    448		ret = s5k6aa_write(c, REG_I_OPCLK_4KHZ(0), s5k6aa->clk_fop);
    449	if (!ret)
    450		ret = s5k6aa_write(c, REG_I_MIN_OUTRATE_4KHZ(0),
    451				   s5k6aa->pclk_fmin);
    452	if (!ret)
    453		ret = s5k6aa_write(c, REG_I_MAX_OUTRATE_4KHZ(0),
    454				   s5k6aa->pclk_fmax);
    455	if (!ret)
    456		ret = s5k6aa_write(c, REG_I_INIT_PARAMS_UPDATED, 1);
    457	if (!ret)
    458		ret = s5k6aa_read(c, REG_I_ERROR_INFO, &status);
    459
    460	return ret ? ret : (status ? -EINVAL : 0);
    461}
    462
    463/* Set horizontal and vertical image flipping */
    464static int s5k6aa_set_mirror(struct s5k6aa *s5k6aa, int horiz_flip)
    465{
    466	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
    467	int index = s5k6aa->preset->index;
    468
    469	unsigned int vflip = s5k6aa->ctrls.vflip->val ^ s5k6aa->inv_vflip;
    470	unsigned int flip = (horiz_flip ^ s5k6aa->inv_hflip) | (vflip << 1);
    471
    472	return s5k6aa_write(client, REG_P_PREV_MIRROR(index), flip);
    473}
    474
    475/* Configure auto/manual white balance and R/G/B gains */
    476static int s5k6aa_set_awb(struct s5k6aa *s5k6aa, int awb)
    477{
    478	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
    479	struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
    480	u16 reg;
    481
    482	int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &reg);
    483
    484	if (!ret && !awb) {
    485		ret = s5k6aa_write(c, REG_SF_RGAIN, ctrls->gain_red->val);
    486		if (!ret)
    487			ret = s5k6aa_write(c, REG_SF_RGAIN_CHG, 1);
    488		if (ret)
    489			return ret;
    490
    491		ret = s5k6aa_write(c, REG_SF_GGAIN, ctrls->gain_green->val);
    492		if (!ret)
    493			ret = s5k6aa_write(c, REG_SF_GGAIN_CHG, 1);
    494		if (ret)
    495			return ret;
    496
    497		ret = s5k6aa_write(c, REG_SF_BGAIN, ctrls->gain_blue->val);
    498		if (!ret)
    499			ret = s5k6aa_write(c, REG_SF_BGAIN_CHG, 1);
    500	}
    501	if (!ret) {
    502		reg = awb ? reg | AALG_WB_EN_MASK : reg & ~AALG_WB_EN_MASK;
    503		ret = s5k6aa_write(c, REG_DBG_AUTOALG_EN, reg);
    504	}
    505
    506	return ret;
    507}
    508
    509/* Program FW with exposure time, 'exposure' in us units */
    510static int s5k6aa_set_user_exposure(struct i2c_client *client, int exposure)
    511{
    512	unsigned int time = exposure / 10;
    513
    514	int ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_L, time & 0xffff);
    515	if (!ret)
    516		ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_H, time >> 16);
    517	if (ret)
    518		return ret;
    519	return s5k6aa_write(client, REG_SF_USR_EXPOSURE_CHG, 1);
    520}
    521
    522static int s5k6aa_set_user_gain(struct i2c_client *client, int gain)
    523{
    524	int ret = s5k6aa_write(client, REG_SF_USR_TOT_GAIN, gain);
    525	if (ret)
    526		return ret;
    527	return s5k6aa_write(client, REG_SF_USR_TOT_GAIN_CHG, 1);
    528}
    529
    530/* Set auto/manual exposure and total gain */
    531static int s5k6aa_set_auto_exposure(struct s5k6aa *s5k6aa, int value)
    532{
    533	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
    534	unsigned int exp_time = s5k6aa->ctrls.exposure->val;
    535	u16 auto_alg;
    536
    537	int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &auto_alg);
    538	if (ret)
    539		return ret;
    540
    541	v4l2_dbg(1, debug, c, "man_exp: %d, auto_exp: %d, a_alg: 0x%x\n",
    542		 exp_time, value, auto_alg);
    543
    544	if (value == V4L2_EXPOSURE_AUTO) {
    545		auto_alg |= AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK;
    546	} else {
    547		ret = s5k6aa_set_user_exposure(c, exp_time);
    548		if (ret)
    549			return ret;
    550		ret = s5k6aa_set_user_gain(c, s5k6aa->ctrls.gain->val);
    551		if (ret)
    552			return ret;
    553		auto_alg &= ~(AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK);
    554	}
    555
    556	return s5k6aa_write(c, REG_DBG_AUTOALG_EN, auto_alg);
    557}
    558
    559static int s5k6aa_set_anti_flicker(struct s5k6aa *s5k6aa, int value)
    560{
    561	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
    562	u16 auto_alg;
    563	int ret;
    564
    565	ret = s5k6aa_read(client, REG_DBG_AUTOALG_EN, &auto_alg);
    566	if (ret)
    567		return ret;
    568
    569	if (value == V4L2_CID_POWER_LINE_FREQUENCY_AUTO) {
    570		auto_alg |= AALG_FLICKER_EN_MASK;
    571	} else {
    572		auto_alg &= ~AALG_FLICKER_EN_MASK;
    573		/* The V4L2_CID_LINE_FREQUENCY control values match
    574		 * the register values */
    575		ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT, value);
    576		if (ret)
    577			return ret;
    578		ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT_CHG, 1);
    579		if (ret)
    580			return ret;
    581	}
    582
    583	return s5k6aa_write(client, REG_DBG_AUTOALG_EN, auto_alg);
    584}
    585
    586static int s5k6aa_set_colorfx(struct s5k6aa *s5k6aa, int val)
    587{
    588	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
    589	static const struct v4l2_control colorfx[] = {
    590		{ V4L2_COLORFX_NONE,	 0 },
    591		{ V4L2_COLORFX_BW,	 1 },
    592		{ V4L2_COLORFX_NEGATIVE, 2 },
    593		{ V4L2_COLORFX_SEPIA,	 3 },
    594		{ V4L2_COLORFX_SKY_BLUE, 4 },
    595		{ V4L2_COLORFX_SKETCH,	 5 },
    596	};
    597	int i;
    598
    599	for (i = 0; i < ARRAY_SIZE(colorfx); i++) {
    600		if (colorfx[i].id == val)
    601			return s5k6aa_write(client, REG_G_SPEC_EFFECTS,
    602					    colorfx[i].value);
    603	}
    604	return -EINVAL;
    605}
    606
    607static int s5k6aa_preview_config_status(struct i2c_client *client)
    608{
    609	u16 error = 0;
    610	int ret = s5k6aa_read(client, REG_G_PREV_CFG_ERROR, &error);
    611
    612	v4l2_dbg(1, debug, client, "error: 0x%x (%d)\n", error, ret);
    613	return ret ? ret : (error ? -EINVAL : 0);
    614}
    615
    616static int s5k6aa_get_pixfmt_index(struct s5k6aa *s5k6aa,
    617				   struct v4l2_mbus_framefmt *mf)
    618{
    619	unsigned int i;
    620
    621	for (i = 0; i < ARRAY_SIZE(s5k6aa_formats); i++)
    622		if (mf->colorspace == s5k6aa_formats[i].colorspace &&
    623		    mf->code == s5k6aa_formats[i].code)
    624			return i;
    625	return 0;
    626}
    627
    628static int s5k6aa_set_output_framefmt(struct s5k6aa *s5k6aa,
    629				      struct s5k6aa_preset *preset)
    630{
    631	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
    632	int fmt_index = s5k6aa_get_pixfmt_index(s5k6aa, &preset->mbus_fmt);
    633	int ret;
    634
    635	ret = s5k6aa_write(client, REG_P_OUT_WIDTH(preset->index),
    636			   preset->mbus_fmt.width);
    637	if (!ret)
    638		ret = s5k6aa_write(client, REG_P_OUT_HEIGHT(preset->index),
    639				   preset->mbus_fmt.height);
    640	if (!ret)
    641		ret = s5k6aa_write(client, REG_P_FMT(preset->index),
    642				   s5k6aa_formats[fmt_index].reg_p_fmt);
    643	return ret;
    644}
    645
    646static int s5k6aa_set_input_params(struct s5k6aa *s5k6aa)
    647{
    648	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
    649	struct v4l2_rect *r = &s5k6aa->ccd_rect;
    650	int ret;
    651
    652	ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_WIDTH, r->width);
    653	if (!ret)
    654		ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_HEIGHT, r->height);
    655	if (!ret)
    656		ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_XOFFS, r->left);
    657	if (!ret)
    658		ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_YOFFS, r->top);
    659	if (!ret)
    660		ret = s5k6aa_write(c, REG_G_INPUTS_CHANGE_REQ, 1);
    661	if (!ret)
    662		s5k6aa->apply_crop = 0;
    663
    664	return ret;
    665}
    666
    667/**
    668 * s5k6aa_configure_video_bus - configure the video output interface
    669 * @s5k6aa: pointer to &struct s5k6aa describing the device
    670 * @bus_type: video bus type: parallel or MIPI-CSI
    671 * @nlanes: number of MIPI lanes to be used (MIPI-CSI only)
    672 *
    673 * Note: Only parallel bus operation has been tested.
    674 */
    675static int s5k6aa_configure_video_bus(struct s5k6aa *s5k6aa,
    676				      enum v4l2_mbus_type bus_type, int nlanes)
    677{
    678	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
    679	u16 cfg = 0;
    680	int ret;
    681
    682	/*
    683	 * TODO: The sensor is supposed to support BT.601 and BT.656
    684	 * but there is nothing indicating how to switch between both
    685	 * in the datasheet. For now default BT.601 interface is assumed.
    686	 */
    687	if (bus_type == V4L2_MBUS_CSI2_DPHY)
    688		cfg = nlanes;
    689	else if (bus_type != V4L2_MBUS_PARALLEL)
    690		return -EINVAL;
    691
    692	ret = s5k6aa_write(client, REG_OIF_EN_MIPI_LANES, cfg);
    693	if (ret)
    694		return ret;
    695	return s5k6aa_write(client, REG_OIF_CFG_CHG, 1);
    696}
    697
    698/* This function should be called when switching to new user configuration set*/
    699static int s5k6aa_new_config_sync(struct i2c_client *client, int timeout,
    700				  int cid)
    701{
    702	unsigned long end = jiffies + msecs_to_jiffies(timeout);
    703	u16 reg = 1;
    704	int ret;
    705
    706	ret = s5k6aa_write(client, REG_G_ACTIVE_PREV_CFG, cid);
    707	if (!ret)
    708		ret = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
    709	if (!ret)
    710		ret = s5k6aa_write(client, REG_G_NEW_CFG_SYNC, 1);
    711	if (timeout == 0)
    712		return ret;
    713
    714	while (ret >= 0 && time_is_after_jiffies(end)) {
    715		ret = s5k6aa_read(client, REG_G_NEW_CFG_SYNC, &reg);
    716		if (!reg)
    717			return 0;
    718		usleep_range(1000, 5000);
    719	}
    720	return ret ? ret : -ETIMEDOUT;
    721}
    722
    723/**
    724 * s5k6aa_set_prev_config - write user preview register set
    725 * @s5k6aa: pointer to &struct s5k6aa describing the device
    726 * @preset: s5kaa preset to be applied
    727 *
    728 * Configure output resolution and color format, pixel clock
    729 * frequency range, device frame rate type and frame period range.
    730 */
    731static int s5k6aa_set_prev_config(struct s5k6aa *s5k6aa,
    732				  struct s5k6aa_preset *preset)
    733{
    734	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
    735	int idx = preset->index;
    736	u16 frame_rate_q;
    737	int ret;
    738
    739	if (s5k6aa->fiv->reg_fr_time >= S5K6AA_MAX_HIGHRES_FR_TIME)
    740		frame_rate_q = FR_RATE_Q_BEST_FRRATE;
    741	else
    742		frame_rate_q = FR_RATE_Q_BEST_QUALITY;
    743
    744	ret = s5k6aa_set_output_framefmt(s5k6aa, preset);
    745	if (!ret)
    746		ret = s5k6aa_write(client, REG_P_MAX_OUT_RATE(idx),
    747				   s5k6aa->pclk_fmax);
    748	if (!ret)
    749		ret = s5k6aa_write(client, REG_P_MIN_OUT_RATE(idx),
    750				   s5k6aa->pclk_fmin);
    751	if (!ret)
    752		ret = s5k6aa_write(client, REG_P_CLK_INDEX(idx),
    753				   preset->clk_id);
    754	if (!ret)
    755		ret = s5k6aa_write(client, REG_P_FR_RATE_TYPE(idx),
    756				   FR_RATE_DYNAMIC);
    757	if (!ret)
    758		ret = s5k6aa_write(client, REG_P_FR_RATE_Q_TYPE(idx),
    759				   frame_rate_q);
    760	if (!ret)
    761		ret = s5k6aa_write(client, REG_P_MAX_FR_TIME(idx),
    762				   s5k6aa->fiv->reg_fr_time + 33);
    763	if (!ret)
    764		ret = s5k6aa_write(client, REG_P_MIN_FR_TIME(idx),
    765				   s5k6aa->fiv->reg_fr_time - 33);
    766	if (!ret)
    767		ret = s5k6aa_new_config_sync(client, 250, idx);
    768	if (!ret)
    769		ret = s5k6aa_preview_config_status(client);
    770	if (!ret)
    771		s5k6aa->apply_cfg = 0;
    772
    773	v4l2_dbg(1, debug, client, "Frame interval: %d +/- 3.3ms. (%d)\n",
    774		 s5k6aa->fiv->reg_fr_time, ret);
    775	return ret;
    776}
    777
    778/**
    779 * s5k6aa_initialize_isp - basic ISP MCU initialization
    780 * @sd: pointer to V4L2 sub-device descriptor
    781 *
    782 * Configure AHB addresses for registers read/write; configure PLLs for
    783 * required output pixel clock. The ISP power supply needs to be already
    784 * enabled, with an optional H/W reset.
    785 * Locking: called with s5k6aa.lock mutex held.
    786 */
    787static int s5k6aa_initialize_isp(struct v4l2_subdev *sd)
    788{
    789	struct i2c_client *client = v4l2_get_subdevdata(sd);
    790	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
    791	int ret;
    792
    793	s5k6aa->apply_crop = 1;
    794	s5k6aa->apply_cfg = 1;
    795	msleep(100);
    796
    797	ret = s5k6aa_set_ahb_address(client);
    798	if (ret)
    799		return ret;
    800	ret = s5k6aa_configure_video_bus(s5k6aa, s5k6aa->bus_type,
    801					 s5k6aa->mipi_lanes);
    802	if (ret)
    803		return ret;
    804	ret = s5k6aa_write_array(sd, s5k6aa_analog_config);
    805	if (ret)
    806		return ret;
    807	msleep(20);
    808
    809	return s5k6aa_configure_pixel_clocks(s5k6aa);
    810}
    811
    812static int s5k6aa_gpio_set_value(struct s5k6aa *priv, int id, u32 val)
    813{
    814	if (!gpio_is_valid(priv->gpio[id].gpio))
    815		return 0;
    816	gpio_set_value(priv->gpio[id].gpio, !!val);
    817	return 1;
    818}
    819
    820static int s5k6aa_gpio_assert(struct s5k6aa *priv, int id)
    821{
    822	return s5k6aa_gpio_set_value(priv, id, priv->gpio[id].level);
    823}
    824
    825static int s5k6aa_gpio_deassert(struct s5k6aa *priv, int id)
    826{
    827	return s5k6aa_gpio_set_value(priv, id, !priv->gpio[id].level);
    828}
    829
    830static int __s5k6aa_power_on(struct s5k6aa *s5k6aa)
    831{
    832	int ret;
    833
    834	ret = regulator_bulk_enable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
    835	if (ret)
    836		return ret;
    837	if (s5k6aa_gpio_deassert(s5k6aa, STBY))
    838		usleep_range(150, 200);
    839
    840	if (s5k6aa->s_power)
    841		ret = s5k6aa->s_power(1);
    842	usleep_range(4000, 5000);
    843
    844	if (s5k6aa_gpio_deassert(s5k6aa, RSET))
    845		msleep(20);
    846
    847	return ret;
    848}
    849
    850static int __s5k6aa_power_off(struct s5k6aa *s5k6aa)
    851{
    852	int ret;
    853
    854	if (s5k6aa_gpio_assert(s5k6aa, RSET))
    855		usleep_range(100, 150);
    856
    857	if (s5k6aa->s_power) {
    858		ret = s5k6aa->s_power(0);
    859		if (ret)
    860			return ret;
    861	}
    862	if (s5k6aa_gpio_assert(s5k6aa, STBY))
    863		usleep_range(50, 100);
    864	s5k6aa->streaming = 0;
    865
    866	return regulator_bulk_disable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
    867}
    868
    869/*
    870 * V4L2 subdev core and video operations
    871 */
    872static int s5k6aa_set_power(struct v4l2_subdev *sd, int on)
    873{
    874	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
    875	int ret = 0;
    876
    877	mutex_lock(&s5k6aa->lock);
    878
    879	if (s5k6aa->power == !on) {
    880		if (on) {
    881			ret = __s5k6aa_power_on(s5k6aa);
    882			if (!ret)
    883				ret = s5k6aa_initialize_isp(sd);
    884		} else {
    885			ret = __s5k6aa_power_off(s5k6aa);
    886		}
    887
    888		if (!ret)
    889			s5k6aa->power += on ? 1 : -1;
    890	}
    891
    892	mutex_unlock(&s5k6aa->lock);
    893
    894	if (!on || ret || s5k6aa->power != 1)
    895		return ret;
    896
    897	return v4l2_ctrl_handler_setup(sd->ctrl_handler);
    898}
    899
    900static int __s5k6aa_stream(struct s5k6aa *s5k6aa, int enable)
    901{
    902	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
    903	int ret = 0;
    904
    905	ret = s5k6aa_write(client, REG_G_ENABLE_PREV, enable);
    906	if (!ret)
    907		ret = s5k6aa_write(client, REG_G_ENABLE_PREV_CHG, 1);
    908	if (!ret)
    909		s5k6aa->streaming = enable;
    910
    911	return ret;
    912}
    913
    914static int s5k6aa_s_stream(struct v4l2_subdev *sd, int on)
    915{
    916	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
    917	int ret = 0;
    918
    919	mutex_lock(&s5k6aa->lock);
    920
    921	if (s5k6aa->streaming == !on) {
    922		if (!ret && s5k6aa->apply_cfg)
    923			ret = s5k6aa_set_prev_config(s5k6aa, s5k6aa->preset);
    924		if (s5k6aa->apply_crop)
    925			ret = s5k6aa_set_input_params(s5k6aa);
    926		if (!ret)
    927			ret = __s5k6aa_stream(s5k6aa, !!on);
    928	}
    929	mutex_unlock(&s5k6aa->lock);
    930
    931	return ret;
    932}
    933
    934static int s5k6aa_g_frame_interval(struct v4l2_subdev *sd,
    935				   struct v4l2_subdev_frame_interval *fi)
    936{
    937	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
    938
    939	mutex_lock(&s5k6aa->lock);
    940	fi->interval = s5k6aa->fiv->interval;
    941	mutex_unlock(&s5k6aa->lock);
    942
    943	return 0;
    944}
    945
    946static int __s5k6aa_set_frame_interval(struct s5k6aa *s5k6aa,
    947				       struct v4l2_subdev_frame_interval *fi)
    948{
    949	struct v4l2_mbus_framefmt *mbus_fmt = &s5k6aa->preset->mbus_fmt;
    950	const struct s5k6aa_interval *fiv = &s5k6aa_intervals[0];
    951	unsigned int err, min_err = UINT_MAX;
    952	unsigned int i, fr_time;
    953
    954	if (fi->interval.denominator == 0)
    955		return -EINVAL;
    956
    957	fr_time = fi->interval.numerator * 10000 / fi->interval.denominator;
    958
    959	for (i = 0; i < ARRAY_SIZE(s5k6aa_intervals); i++) {
    960		const struct s5k6aa_interval *iv = &s5k6aa_intervals[i];
    961
    962		if (mbus_fmt->width > iv->size.width ||
    963		    mbus_fmt->height > iv->size.height)
    964			continue;
    965
    966		err = abs(iv->reg_fr_time - fr_time);
    967		if (err < min_err) {
    968			fiv = iv;
    969			min_err = err;
    970		}
    971	}
    972	s5k6aa->fiv = fiv;
    973
    974	v4l2_dbg(1, debug, &s5k6aa->sd, "Changed frame interval to %d us\n",
    975		 fiv->reg_fr_time * 100);
    976	return 0;
    977}
    978
    979static int s5k6aa_s_frame_interval(struct v4l2_subdev *sd,
    980				   struct v4l2_subdev_frame_interval *fi)
    981{
    982	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
    983	int ret;
    984
    985	v4l2_dbg(1, debug, sd, "Setting %d/%d frame interval\n",
    986		 fi->interval.numerator, fi->interval.denominator);
    987
    988	mutex_lock(&s5k6aa->lock);
    989	ret = __s5k6aa_set_frame_interval(s5k6aa, fi);
    990	s5k6aa->apply_cfg = 1;
    991
    992	mutex_unlock(&s5k6aa->lock);
    993	return ret;
    994}
    995
    996/*
    997 * V4L2 subdev pad level and video operations
    998 */
    999static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd,
   1000			      struct v4l2_subdev_state *sd_state,
   1001			      struct v4l2_subdev_frame_interval_enum *fie)
   1002{
   1003	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
   1004	const struct s5k6aa_interval *fi;
   1005	int ret = 0;
   1006
   1007	if (fie->index >= ARRAY_SIZE(s5k6aa_intervals))
   1008		return -EINVAL;
   1009
   1010	v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN,
   1011			      S5K6AA_WIN_WIDTH_MAX, 1,
   1012			      &fie->height, S5K6AA_WIN_HEIGHT_MIN,
   1013			      S5K6AA_WIN_HEIGHT_MAX, 1, 0);
   1014
   1015	mutex_lock(&s5k6aa->lock);
   1016	fi = &s5k6aa_intervals[fie->index];
   1017	if (fie->width > fi->size.width || fie->height > fi->size.height)
   1018		ret = -EINVAL;
   1019	else
   1020		fie->interval = fi->interval;
   1021	mutex_unlock(&s5k6aa->lock);
   1022
   1023	return ret;
   1024}
   1025
   1026static int s5k6aa_enum_mbus_code(struct v4l2_subdev *sd,
   1027				 struct v4l2_subdev_state *sd_state,
   1028				 struct v4l2_subdev_mbus_code_enum *code)
   1029{
   1030	if (code->index >= ARRAY_SIZE(s5k6aa_formats))
   1031		return -EINVAL;
   1032
   1033	code->code = s5k6aa_formats[code->index].code;
   1034	return 0;
   1035}
   1036
   1037static int s5k6aa_enum_frame_size(struct v4l2_subdev *sd,
   1038				  struct v4l2_subdev_state *sd_state,
   1039				  struct v4l2_subdev_frame_size_enum *fse)
   1040{
   1041	int i = ARRAY_SIZE(s5k6aa_formats);
   1042
   1043	if (fse->index > 0)
   1044		return -EINVAL;
   1045
   1046	while (--i)
   1047		if (fse->code == s5k6aa_formats[i].code)
   1048			break;
   1049
   1050	fse->code = s5k6aa_formats[i].code;
   1051	fse->min_width  = S5K6AA_WIN_WIDTH_MIN;
   1052	fse->max_width  = S5K6AA_WIN_WIDTH_MAX;
   1053	fse->max_height = S5K6AA_WIN_HEIGHT_MIN;
   1054	fse->min_height = S5K6AA_WIN_HEIGHT_MAX;
   1055
   1056	return 0;
   1057}
   1058
   1059static struct v4l2_rect *
   1060__s5k6aa_get_crop_rect(struct s5k6aa *s5k6aa,
   1061		       struct v4l2_subdev_state *sd_state,
   1062		       enum v4l2_subdev_format_whence which)
   1063{
   1064	if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
   1065		return &s5k6aa->ccd_rect;
   1066
   1067	WARN_ON(which != V4L2_SUBDEV_FORMAT_TRY);
   1068	return v4l2_subdev_get_try_crop(&s5k6aa->sd, sd_state, 0);
   1069}
   1070
   1071static void s5k6aa_try_format(struct s5k6aa *s5k6aa,
   1072			      struct v4l2_mbus_framefmt *mf)
   1073{
   1074	unsigned int index;
   1075
   1076	v4l_bound_align_image(&mf->width, S5K6AA_WIN_WIDTH_MIN,
   1077			      S5K6AA_WIN_WIDTH_MAX, 1,
   1078			      &mf->height, S5K6AA_WIN_HEIGHT_MIN,
   1079			      S5K6AA_WIN_HEIGHT_MAX, 1, 0);
   1080
   1081	if (mf->colorspace != V4L2_COLORSPACE_JPEG &&
   1082	    mf->colorspace != V4L2_COLORSPACE_REC709)
   1083		mf->colorspace = V4L2_COLORSPACE_JPEG;
   1084
   1085	index = s5k6aa_get_pixfmt_index(s5k6aa, mf);
   1086
   1087	mf->colorspace	= s5k6aa_formats[index].colorspace;
   1088	mf->code	= s5k6aa_formats[index].code;
   1089	mf->field	= V4L2_FIELD_NONE;
   1090}
   1091
   1092static int s5k6aa_get_fmt(struct v4l2_subdev *sd,
   1093			  struct v4l2_subdev_state *sd_state,
   1094			  struct v4l2_subdev_format *fmt)
   1095{
   1096	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
   1097	struct v4l2_mbus_framefmt *mf;
   1098
   1099	memset(fmt->reserved, 0, sizeof(fmt->reserved));
   1100
   1101	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
   1102		mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
   1103		fmt->format = *mf;
   1104		return 0;
   1105	}
   1106
   1107	mutex_lock(&s5k6aa->lock);
   1108	fmt->format = s5k6aa->preset->mbus_fmt;
   1109	mutex_unlock(&s5k6aa->lock);
   1110
   1111	return 0;
   1112}
   1113
   1114static int s5k6aa_set_fmt(struct v4l2_subdev *sd,
   1115			  struct v4l2_subdev_state *sd_state,
   1116			  struct v4l2_subdev_format *fmt)
   1117{
   1118	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
   1119	struct s5k6aa_preset *preset = s5k6aa->preset;
   1120	struct v4l2_mbus_framefmt *mf;
   1121	struct v4l2_rect *crop;
   1122	int ret = 0;
   1123
   1124	mutex_lock(&s5k6aa->lock);
   1125	s5k6aa_try_format(s5k6aa, &fmt->format);
   1126
   1127	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
   1128		mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
   1129		crop = v4l2_subdev_get_try_crop(sd, sd_state, 0);
   1130	} else {
   1131		if (s5k6aa->streaming) {
   1132			ret = -EBUSY;
   1133		} else {
   1134			mf = &preset->mbus_fmt;
   1135			crop = &s5k6aa->ccd_rect;
   1136			s5k6aa->apply_cfg = 1;
   1137		}
   1138	}
   1139
   1140	if (ret == 0) {
   1141		struct v4l2_subdev_frame_interval fiv = {
   1142			.interval = {0, 1}
   1143		};
   1144
   1145		*mf = fmt->format;
   1146		/*
   1147		 * Make sure the crop window is valid, i.e. its size is
   1148		 * greater than the output window, as the ISP supports
   1149		 * only down-scaling.
   1150		 */
   1151		crop->width = clamp_t(unsigned int, crop->width, mf->width,
   1152				      S5K6AA_WIN_WIDTH_MAX);
   1153		crop->height = clamp_t(unsigned int, crop->height, mf->height,
   1154				       S5K6AA_WIN_HEIGHT_MAX);
   1155		crop->left = clamp_t(unsigned int, crop->left, 0,
   1156				     S5K6AA_WIN_WIDTH_MAX - crop->width);
   1157		crop->top  = clamp_t(unsigned int, crop->top, 0,
   1158				     S5K6AA_WIN_HEIGHT_MAX - crop->height);
   1159
   1160		/* Reset to minimum possible frame interval */
   1161		ret = __s5k6aa_set_frame_interval(s5k6aa, &fiv);
   1162	}
   1163	mutex_unlock(&s5k6aa->lock);
   1164
   1165	return ret;
   1166}
   1167
   1168static int s5k6aa_get_selection(struct v4l2_subdev *sd,
   1169				struct v4l2_subdev_state *sd_state,
   1170				struct v4l2_subdev_selection *sel)
   1171{
   1172	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
   1173	struct v4l2_rect *rect;
   1174
   1175	if (sel->target != V4L2_SEL_TGT_CROP)
   1176		return -EINVAL;
   1177
   1178	memset(sel->reserved, 0, sizeof(sel->reserved));
   1179
   1180	mutex_lock(&s5k6aa->lock);
   1181	rect = __s5k6aa_get_crop_rect(s5k6aa, sd_state, sel->which);
   1182	sel->r = *rect;
   1183	mutex_unlock(&s5k6aa->lock);
   1184
   1185	v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n",
   1186		 rect->left, rect->top, rect->width, rect->height);
   1187
   1188	return 0;
   1189}
   1190
   1191static int s5k6aa_set_selection(struct v4l2_subdev *sd,
   1192				struct v4l2_subdev_state *sd_state,
   1193				struct v4l2_subdev_selection *sel)
   1194{
   1195	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
   1196	struct v4l2_mbus_framefmt *mf;
   1197	unsigned int max_x, max_y;
   1198	struct v4l2_rect *crop_r;
   1199
   1200	if (sel->target != V4L2_SEL_TGT_CROP)
   1201		return -EINVAL;
   1202
   1203	mutex_lock(&s5k6aa->lock);
   1204	crop_r = __s5k6aa_get_crop_rect(s5k6aa, sd_state, sel->which);
   1205
   1206	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
   1207		mf = &s5k6aa->preset->mbus_fmt;
   1208		s5k6aa->apply_crop = 1;
   1209	} else {
   1210		mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
   1211	}
   1212	v4l_bound_align_image(&sel->r.width, mf->width,
   1213			      S5K6AA_WIN_WIDTH_MAX, 1,
   1214			      &sel->r.height, mf->height,
   1215			      S5K6AA_WIN_HEIGHT_MAX, 1, 0);
   1216
   1217	max_x = (S5K6AA_WIN_WIDTH_MAX - sel->r.width) & ~1;
   1218	max_y = (S5K6AA_WIN_HEIGHT_MAX - sel->r.height) & ~1;
   1219
   1220	sel->r.left = clamp_t(unsigned int, sel->r.left, 0, max_x);
   1221	sel->r.top  = clamp_t(unsigned int, sel->r.top, 0, max_y);
   1222
   1223	*crop_r = sel->r;
   1224
   1225	mutex_unlock(&s5k6aa->lock);
   1226
   1227	v4l2_dbg(1, debug, sd, "Set crop rectangle: (%d,%d)/%dx%d\n",
   1228		 crop_r->left, crop_r->top, crop_r->width, crop_r->height);
   1229
   1230	return 0;
   1231}
   1232
   1233static const struct v4l2_subdev_pad_ops s5k6aa_pad_ops = {
   1234	.enum_mbus_code		= s5k6aa_enum_mbus_code,
   1235	.enum_frame_size	= s5k6aa_enum_frame_size,
   1236	.enum_frame_interval	= s5k6aa_enum_frame_interval,
   1237	.get_fmt		= s5k6aa_get_fmt,
   1238	.set_fmt		= s5k6aa_set_fmt,
   1239	.get_selection		= s5k6aa_get_selection,
   1240	.set_selection		= s5k6aa_set_selection,
   1241};
   1242
   1243static const struct v4l2_subdev_video_ops s5k6aa_video_ops = {
   1244	.g_frame_interval	= s5k6aa_g_frame_interval,
   1245	.s_frame_interval	= s5k6aa_s_frame_interval,
   1246	.s_stream		= s5k6aa_s_stream,
   1247};
   1248
   1249/*
   1250 * V4L2 subdev controls
   1251 */
   1252
   1253static int s5k6aa_s_ctrl(struct v4l2_ctrl *ctrl)
   1254{
   1255	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
   1256	struct i2c_client *client = v4l2_get_subdevdata(sd);
   1257	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
   1258	int idx, err = 0;
   1259
   1260	v4l2_dbg(1, debug, sd, "ctrl: 0x%x, value: %d\n", ctrl->id, ctrl->val);
   1261
   1262	mutex_lock(&s5k6aa->lock);
   1263	/*
   1264	 * If the device is not powered up by the host driver do
   1265	 * not apply any controls to H/W at this time. Instead
   1266	 * the controls will be restored right after power-up.
   1267	 */
   1268	if (s5k6aa->power == 0)
   1269		goto unlock;
   1270	idx = s5k6aa->preset->index;
   1271
   1272	switch (ctrl->id) {
   1273	case V4L2_CID_AUTO_WHITE_BALANCE:
   1274		err = s5k6aa_set_awb(s5k6aa, ctrl->val);
   1275		break;
   1276
   1277	case V4L2_CID_BRIGHTNESS:
   1278		err = s5k6aa_write(client, REG_USER_BRIGHTNESS, ctrl->val);
   1279		break;
   1280
   1281	case V4L2_CID_COLORFX:
   1282		err = s5k6aa_set_colorfx(s5k6aa, ctrl->val);
   1283		break;
   1284
   1285	case V4L2_CID_CONTRAST:
   1286		err = s5k6aa_write(client, REG_USER_CONTRAST, ctrl->val);
   1287		break;
   1288
   1289	case V4L2_CID_EXPOSURE_AUTO:
   1290		err = s5k6aa_set_auto_exposure(s5k6aa, ctrl->val);
   1291		break;
   1292
   1293	case V4L2_CID_HFLIP:
   1294		err = s5k6aa_set_mirror(s5k6aa, ctrl->val);
   1295		if (err)
   1296			break;
   1297		err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
   1298		break;
   1299
   1300	case V4L2_CID_POWER_LINE_FREQUENCY:
   1301		err = s5k6aa_set_anti_flicker(s5k6aa, ctrl->val);
   1302		break;
   1303
   1304	case V4L2_CID_SATURATION:
   1305		err = s5k6aa_write(client, REG_USER_SATURATION, ctrl->val);
   1306		break;
   1307
   1308	case V4L2_CID_SHARPNESS:
   1309		err = s5k6aa_write(client, REG_USER_SHARPBLUR, ctrl->val);
   1310		break;
   1311
   1312	case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
   1313		err = s5k6aa_write(client, REG_P_COLORTEMP(idx), ctrl->val);
   1314		if (err)
   1315			break;
   1316		err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
   1317		break;
   1318	}
   1319unlock:
   1320	mutex_unlock(&s5k6aa->lock);
   1321	return err;
   1322}
   1323
   1324static const struct v4l2_ctrl_ops s5k6aa_ctrl_ops = {
   1325	.s_ctrl	= s5k6aa_s_ctrl,
   1326};
   1327
   1328static int s5k6aa_log_status(struct v4l2_subdev *sd)
   1329{
   1330	v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
   1331	return 0;
   1332}
   1333
   1334#define V4L2_CID_RED_GAIN	(V4L2_CTRL_CLASS_CAMERA | 0x1001)
   1335#define V4L2_CID_GREEN_GAIN	(V4L2_CTRL_CLASS_CAMERA | 0x1002)
   1336#define V4L2_CID_BLUE_GAIN	(V4L2_CTRL_CLASS_CAMERA | 0x1003)
   1337
   1338static const struct v4l2_ctrl_config s5k6aa_ctrls[] = {
   1339	{
   1340		.ops	= &s5k6aa_ctrl_ops,
   1341		.id	= V4L2_CID_RED_GAIN,
   1342		.type	= V4L2_CTRL_TYPE_INTEGER,
   1343		.name	= "Gain, Red",
   1344		.min	= 0,
   1345		.max	= 256,
   1346		.def	= 127,
   1347		.step	= 1,
   1348	}, {
   1349		.ops	= &s5k6aa_ctrl_ops,
   1350		.id	= V4L2_CID_GREEN_GAIN,
   1351		.type	= V4L2_CTRL_TYPE_INTEGER,
   1352		.name	= "Gain, Green",
   1353		.min	= 0,
   1354		.max	= 256,
   1355		.def	= 127,
   1356		.step	= 1,
   1357	}, {
   1358		.ops	= &s5k6aa_ctrl_ops,
   1359		.id	= V4L2_CID_BLUE_GAIN,
   1360		.type	= V4L2_CTRL_TYPE_INTEGER,
   1361		.name	= "Gain, Blue",
   1362		.min	= 0,
   1363		.max	= 256,
   1364		.def	= 127,
   1365		.step	= 1,
   1366	},
   1367};
   1368
   1369static int s5k6aa_initialize_ctrls(struct s5k6aa *s5k6aa)
   1370{
   1371	const struct v4l2_ctrl_ops *ops = &s5k6aa_ctrl_ops;
   1372	struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
   1373	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
   1374
   1375	int ret = v4l2_ctrl_handler_init(hdl, 16);
   1376	if (ret)
   1377		return ret;
   1378	/* Auto white balance cluster */
   1379	ctrls->awb = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE,
   1380				       0, 1, 1, 1);
   1381	ctrls->gain_red = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[0], NULL);
   1382	ctrls->gain_green = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[1], NULL);
   1383	ctrls->gain_blue = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[2], NULL);
   1384	v4l2_ctrl_auto_cluster(4, &ctrls->awb, 0, false);
   1385
   1386	ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
   1387	ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
   1388	v4l2_ctrl_cluster(2, &ctrls->hflip);
   1389
   1390	ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
   1391				V4L2_CID_EXPOSURE_AUTO,
   1392				V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO);
   1393	/* Exposure time: x 1 us */
   1394	ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
   1395					    0, 6000000U, 1, 100000U);
   1396	/* Total gain: 256 <=> 1x */
   1397	ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
   1398					0, 256, 1, 256);
   1399	v4l2_ctrl_auto_cluster(3, &ctrls->auto_exp, 0, false);
   1400
   1401	v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_POWER_LINE_FREQUENCY,
   1402			       V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
   1403			       V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
   1404
   1405	v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_COLORFX,
   1406			       V4L2_COLORFX_SKY_BLUE, ~0x6f, V4L2_COLORFX_NONE);
   1407
   1408	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_WHITE_BALANCE_TEMPERATURE,
   1409			  0, 256, 1, 0);
   1410
   1411	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0);
   1412	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -127, 127, 1, 0);
   1413	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0);
   1414	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -127, 127, 1, 0);
   1415
   1416	if (hdl->error) {
   1417		ret = hdl->error;
   1418		v4l2_ctrl_handler_free(hdl);
   1419		return ret;
   1420	}
   1421
   1422	s5k6aa->sd.ctrl_handler = hdl;
   1423	return 0;
   1424}
   1425
   1426/*
   1427 * V4L2 subdev internal operations
   1428 */
   1429static int s5k6aa_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
   1430{
   1431	struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd,
   1432								       fh->state,
   1433								       0);
   1434	struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
   1435
   1436	format->colorspace = s5k6aa_formats[0].colorspace;
   1437	format->code = s5k6aa_formats[0].code;
   1438	format->width = S5K6AA_OUT_WIDTH_DEF;
   1439	format->height = S5K6AA_OUT_HEIGHT_DEF;
   1440	format->field = V4L2_FIELD_NONE;
   1441
   1442	crop->width = S5K6AA_WIN_WIDTH_MAX;
   1443	crop->height = S5K6AA_WIN_HEIGHT_MAX;
   1444	crop->left = 0;
   1445	crop->top = 0;
   1446
   1447	return 0;
   1448}
   1449
   1450static int s5k6aa_check_fw_revision(struct s5k6aa *s5k6aa)
   1451{
   1452	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
   1453	u16 api_ver = 0, fw_rev = 0;
   1454
   1455	int ret = s5k6aa_set_ahb_address(client);
   1456
   1457	if (!ret)
   1458		ret = s5k6aa_read(client, REG_FW_APIVER, &api_ver);
   1459	if (!ret)
   1460		ret = s5k6aa_read(client, REG_FW_REVISION, &fw_rev);
   1461	if (ret) {
   1462		v4l2_err(&s5k6aa->sd, "FW revision check failed!\n");
   1463		return ret;
   1464	}
   1465
   1466	v4l2_info(&s5k6aa->sd, "FW API ver.: 0x%X, FW rev.: 0x%X\n",
   1467		  api_ver, fw_rev);
   1468
   1469	return api_ver == S5K6AAFX_FW_APIVER ? 0 : -ENODEV;
   1470}
   1471
   1472static int s5k6aa_registered(struct v4l2_subdev *sd)
   1473{
   1474	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
   1475	int ret;
   1476
   1477	mutex_lock(&s5k6aa->lock);
   1478	ret = __s5k6aa_power_on(s5k6aa);
   1479	if (!ret) {
   1480		msleep(100);
   1481		ret = s5k6aa_check_fw_revision(s5k6aa);
   1482		__s5k6aa_power_off(s5k6aa);
   1483	}
   1484	mutex_unlock(&s5k6aa->lock);
   1485
   1486	return ret;
   1487}
   1488
   1489static const struct v4l2_subdev_internal_ops s5k6aa_subdev_internal_ops = {
   1490	.registered = s5k6aa_registered,
   1491	.open = s5k6aa_open,
   1492};
   1493
   1494static const struct v4l2_subdev_core_ops s5k6aa_core_ops = {
   1495	.s_power = s5k6aa_set_power,
   1496	.log_status = s5k6aa_log_status,
   1497};
   1498
   1499static const struct v4l2_subdev_ops s5k6aa_subdev_ops = {
   1500	.core = &s5k6aa_core_ops,
   1501	.pad = &s5k6aa_pad_ops,
   1502	.video = &s5k6aa_video_ops,
   1503};
   1504
   1505/*
   1506 * GPIO setup
   1507 */
   1508
   1509static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa,
   1510				  const struct s5k6aa_platform_data *pdata)
   1511{
   1512	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
   1513	const struct s5k6aa_gpio *gpio;
   1514	unsigned long flags;
   1515	int ret;
   1516
   1517	s5k6aa->gpio[STBY].gpio = -EINVAL;
   1518	s5k6aa->gpio[RSET].gpio  = -EINVAL;
   1519
   1520	gpio = &pdata->gpio_stby;
   1521	if (gpio_is_valid(gpio->gpio)) {
   1522		flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
   1523		      | GPIOF_EXPORT;
   1524		ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags,
   1525					    "S5K6AA_STBY");
   1526		if (ret < 0)
   1527			return ret;
   1528
   1529		s5k6aa->gpio[STBY] = *gpio;
   1530	}
   1531
   1532	gpio = &pdata->gpio_reset;
   1533	if (gpio_is_valid(gpio->gpio)) {
   1534		flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
   1535		      | GPIOF_EXPORT;
   1536		ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags,
   1537					    "S5K6AA_RST");
   1538		if (ret < 0)
   1539			return ret;
   1540
   1541		s5k6aa->gpio[RSET] = *gpio;
   1542	}
   1543
   1544	return 0;
   1545}
   1546
   1547static int s5k6aa_probe(struct i2c_client *client,
   1548			const struct i2c_device_id *id)
   1549{
   1550	const struct s5k6aa_platform_data *pdata = client->dev.platform_data;
   1551	struct v4l2_subdev *sd;
   1552	struct s5k6aa *s5k6aa;
   1553	int i, ret;
   1554
   1555	if (pdata == NULL) {
   1556		dev_err(&client->dev, "Platform data not specified\n");
   1557		return -EINVAL;
   1558	}
   1559
   1560	if (pdata->mclk_frequency == 0) {
   1561		dev_err(&client->dev, "MCLK frequency not specified\n");
   1562		return -EINVAL;
   1563	}
   1564
   1565	s5k6aa = devm_kzalloc(&client->dev, sizeof(*s5k6aa), GFP_KERNEL);
   1566	if (!s5k6aa)
   1567		return -ENOMEM;
   1568
   1569	mutex_init(&s5k6aa->lock);
   1570
   1571	s5k6aa->mclk_frequency = pdata->mclk_frequency;
   1572	s5k6aa->bus_type = pdata->bus_type;
   1573	s5k6aa->mipi_lanes = pdata->nlanes;
   1574	s5k6aa->s_power	= pdata->set_power;
   1575	s5k6aa->inv_hflip = pdata->horiz_flip;
   1576	s5k6aa->inv_vflip = pdata->vert_flip;
   1577
   1578	sd = &s5k6aa->sd;
   1579	v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops);
   1580	/* Static name; NEVER use in new drivers! */
   1581	strscpy(sd->name, DRIVER_NAME, sizeof(sd->name));
   1582
   1583	sd->internal_ops = &s5k6aa_subdev_internal_ops;
   1584	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
   1585
   1586	s5k6aa->pad.flags = MEDIA_PAD_FL_SOURCE;
   1587	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
   1588	ret = media_entity_pads_init(&sd->entity, 1, &s5k6aa->pad);
   1589	if (ret)
   1590		return ret;
   1591
   1592	ret = s5k6aa_configure_gpios(s5k6aa, pdata);
   1593	if (ret)
   1594		goto out_err;
   1595
   1596	for (i = 0; i < S5K6AA_NUM_SUPPLIES; i++)
   1597		s5k6aa->supplies[i].supply = s5k6aa_supply_names[i];
   1598
   1599	ret = devm_regulator_bulk_get(&client->dev, S5K6AA_NUM_SUPPLIES,
   1600				 s5k6aa->supplies);
   1601	if (ret) {
   1602		dev_err(&client->dev, "Failed to get regulators\n");
   1603		goto out_err;
   1604	}
   1605
   1606	ret = s5k6aa_initialize_ctrls(s5k6aa);
   1607	if (ret)
   1608		goto out_err;
   1609
   1610	s5k6aa_presets_data_init(s5k6aa);
   1611
   1612	s5k6aa->ccd_rect.width = S5K6AA_WIN_WIDTH_MAX;
   1613	s5k6aa->ccd_rect.height	= S5K6AA_WIN_HEIGHT_MAX;
   1614	s5k6aa->ccd_rect.left = 0;
   1615	s5k6aa->ccd_rect.top = 0;
   1616
   1617	return 0;
   1618
   1619out_err:
   1620	media_entity_cleanup(&s5k6aa->sd.entity);
   1621	return ret;
   1622}
   1623
   1624static int s5k6aa_remove(struct i2c_client *client)
   1625{
   1626	struct v4l2_subdev *sd = i2c_get_clientdata(client);
   1627
   1628	v4l2_device_unregister_subdev(sd);
   1629	v4l2_ctrl_handler_free(sd->ctrl_handler);
   1630	media_entity_cleanup(&sd->entity);
   1631
   1632	return 0;
   1633}
   1634
   1635static const struct i2c_device_id s5k6aa_id[] = {
   1636	{ DRIVER_NAME, 0 },
   1637	{ },
   1638};
   1639MODULE_DEVICE_TABLE(i2c, s5k6aa_id);
   1640
   1641
   1642static struct i2c_driver s5k6aa_i2c_driver = {
   1643	.driver = {
   1644		.name = DRIVER_NAME
   1645	},
   1646	.probe		= s5k6aa_probe,
   1647	.remove		= s5k6aa_remove,
   1648	.id_table	= s5k6aa_id,
   1649};
   1650
   1651module_i2c_driver(s5k6aa_i2c_driver);
   1652
   1653MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver");
   1654MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
   1655MODULE_LICENSE("GPL");