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

ov7740.c (28110B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (c) 2017 Microchip Corporation.
      3
      4#include <linux/clk.h>
      5#include <linux/delay.h>
      6#include <linux/gpio/consumer.h>
      7#include <linux/i2c.h>
      8#include <linux/module.h>
      9#include <linux/pm_runtime.h>
     10#include <linux/regmap.h>
     11#include <media/v4l2-ctrls.h>
     12#include <media/v4l2-event.h>
     13#include <media/v4l2-image-sizes.h>
     14#include <media/v4l2-subdev.h>
     15
     16#define REG_OUTSIZE_LSB 0x34
     17
     18/* OV7740 register tables */
     19#define REG_GAIN	0x00	/* Gain lower 8 bits (rest in vref) */
     20#define REG_BGAIN	0x01	/* blue gain */
     21#define REG_RGAIN	0x02	/* red gain */
     22#define REG_GGAIN	0x03	/* green gain */
     23#define REG_REG04	0x04	/* analog setting, don't change*/
     24#define REG_BAVG	0x05	/* b channel average */
     25#define REG_GAVG	0x06	/* g channel average */
     26#define REG_RAVG	0x07	/* r channel average */
     27
     28#define REG_REG0C	0x0C	/* filp enable */
     29#define REG0C_IMG_FLIP		0x80
     30#define REG0C_IMG_MIRROR	0x40
     31
     32#define REG_REG0E	0x0E	/* blc line */
     33#define REG_HAEC	0x0F	/* auto exposure cntrl */
     34#define REG_AEC		0x10	/* auto exposure cntrl */
     35
     36#define REG_CLK		0x11	/* Clock control */
     37#define REG_REG55	0x55	/* Clock PLL DIV/PreDiv */
     38
     39#define REG_REG12	0x12
     40
     41#define REG_REG13	0x13	/* auto/manual AGC, AEC, Write Balance*/
     42#define REG13_AEC_EN	0x01
     43#define REG13_AGC_EN	0x04
     44
     45#define REG_REG14	0x14
     46#define REG_CTRL15	0x15
     47#define REG15_GAIN_MSB	0x03
     48
     49#define REG_REG16	0x16
     50
     51#define REG_MIDH	0x1C	/* manufacture id byte */
     52#define REG_MIDL	0x1D	/* manufacture id byre */
     53#define REG_PIDH	0x0A	/* Product ID MSB */
     54#define REG_PIDL	0x0B	/* Product ID LSB */
     55
     56#define REG_84		0x84	/* lots of stuff */
     57#define REG_REG38	0x38	/* sub-addr */
     58
     59#define REG_AHSTART	0x17	/* Horiz start high bits */
     60#define REG_AHSIZE	0x18
     61#define REG_AVSTART	0x19	/* Vert start high bits */
     62#define REG_AVSIZE	0x1A
     63#define REG_PSHFT	0x1b	/* Pixel delay after HREF */
     64
     65#define REG_HOUTSIZE	0x31
     66#define REG_VOUTSIZE	0x32
     67#define REG_HVSIZEOFF	0x33
     68#define REG_REG34	0x34	/* DSP output size H/V LSB*/
     69
     70#define REG_ISP_CTRL00	0x80
     71#define ISPCTRL00_AWB_EN	0x10
     72#define ISPCTRL00_AWB_GAIN_EN	0x04
     73
     74#define	REG_YGAIN	0xE2	/* ygain for contrast control */
     75
     76#define	REG_YBRIGHT	  0xE3
     77#define	REG_SGNSET	  0xE4
     78#define	SGNSET_YBRIGHT_MASK	  0x08
     79
     80#define REG_USAT	0xDD
     81#define REG_VSAT	0xDE
     82
     83
     84struct ov7740 {
     85	struct v4l2_subdev subdev;
     86#if defined(CONFIG_MEDIA_CONTROLLER)
     87	struct media_pad pad;
     88#endif
     89	struct v4l2_mbus_framefmt format;
     90	const struct ov7740_pixfmt *fmt;  /* Current format */
     91	const struct ov7740_framesize *frmsize;
     92	struct regmap *regmap;
     93	struct clk *xvclk;
     94	struct v4l2_ctrl_handler ctrl_handler;
     95	struct {
     96		/* gain cluster */
     97		struct v4l2_ctrl *auto_gain;
     98		struct v4l2_ctrl *gain;
     99	};
    100	struct {
    101		struct v4l2_ctrl *auto_wb;
    102		struct v4l2_ctrl *blue_balance;
    103		struct v4l2_ctrl *red_balance;
    104	};
    105	struct {
    106		struct v4l2_ctrl *hflip;
    107		struct v4l2_ctrl *vflip;
    108	};
    109	struct {
    110		/* exposure cluster */
    111		struct v4l2_ctrl *auto_exposure;
    112		struct v4l2_ctrl *exposure;
    113	};
    114	struct {
    115		/* saturation/hue cluster */
    116		struct v4l2_ctrl *saturation;
    117		struct v4l2_ctrl *hue;
    118	};
    119	struct v4l2_ctrl *brightness;
    120	struct v4l2_ctrl *contrast;
    121
    122	struct mutex mutex;	/* To serialize asynchronus callbacks */
    123	bool streaming;		/* Streaming on/off */
    124
    125	struct gpio_desc *resetb_gpio;
    126	struct gpio_desc *pwdn_gpio;
    127};
    128
    129struct ov7740_pixfmt {
    130	u32 mbus_code;
    131	enum v4l2_colorspace colorspace;
    132	const struct reg_sequence *regs;
    133	u32 reg_num;
    134};
    135
    136struct ov7740_framesize {
    137	u16 width;
    138	u16 height;
    139	const struct reg_sequence *regs;
    140	u32 reg_num;
    141};
    142
    143static const struct reg_sequence ov7740_vga[] = {
    144	{0x55, 0x40},
    145	{0x11, 0x02},
    146
    147	{0xd5, 0x10},
    148	{0x0c, 0x12},
    149	{0x0d, 0x34},
    150	{0x17, 0x25},
    151	{0x18, 0xa0},
    152	{0x19, 0x03},
    153	{0x1a, 0xf0},
    154	{0x1b, 0x89},
    155	{0x22, 0x03},
    156	{0x29, 0x18},
    157	{0x2b, 0xf8},
    158	{0x2c, 0x01},
    159	{REG_HOUTSIZE, 0xa0},
    160	{REG_VOUTSIZE, 0xf0},
    161	{0x33, 0xc4},
    162	{REG_OUTSIZE_LSB, 0x0},
    163	{0x35, 0x05},
    164	{0x04, 0x60},
    165	{0x27, 0x80},
    166	{0x3d, 0x0f},
    167	{0x3e, 0x80},
    168	{0x3f, 0x40},
    169	{0x40, 0x7f},
    170	{0x41, 0x6a},
    171	{0x42, 0x29},
    172	{0x44, 0x22},
    173	{0x45, 0x41},
    174	{0x47, 0x02},
    175	{0x49, 0x64},
    176	{0x4a, 0xa1},
    177	{0x4b, 0x40},
    178	{0x4c, 0x1a},
    179	{0x4d, 0x50},
    180	{0x4e, 0x13},
    181	{0x64, 0x00},
    182	{0x67, 0x88},
    183	{0x68, 0x1a},
    184
    185	{0x14, 0x28},
    186	{0x24, 0x3c},
    187	{0x25, 0x30},
    188	{0x26, 0x72},
    189	{0x50, 0x97},
    190	{0x51, 0x1f},
    191	{0x52, 0x00},
    192	{0x53, 0x00},
    193	{0x20, 0x00},
    194	{0x21, 0xcf},
    195	{0x50, 0x4b},
    196	{0x38, 0x14},
    197	{0xe9, 0x00},
    198	{0x56, 0x55},
    199	{0x57, 0xff},
    200	{0x58, 0xff},
    201	{0x59, 0xff},
    202	{0x5f, 0x04},
    203	{0xec, 0x00},
    204	{0x13, 0xff},
    205
    206	{0x81, 0x3f},
    207	{0x82, 0x32},
    208	{0x38, 0x11},
    209	{0x84, 0x70},
    210	{0x85, 0x00},
    211	{0x86, 0x03},
    212	{0x87, 0x01},
    213	{0x88, 0x05},
    214	{0x89, 0x30},
    215	{0x8d, 0x30},
    216	{0x8f, 0x85},
    217	{0x93, 0x30},
    218	{0x95, 0x85},
    219	{0x99, 0x30},
    220	{0x9b, 0x85},
    221
    222	{0x9c, 0x08},
    223	{0x9d, 0x12},
    224	{0x9e, 0x23},
    225	{0x9f, 0x45},
    226	{0xa0, 0x55},
    227	{0xa1, 0x64},
    228	{0xa2, 0x72},
    229	{0xa3, 0x7f},
    230	{0xa4, 0x8b},
    231	{0xa5, 0x95},
    232	{0xa6, 0xa7},
    233	{0xa7, 0xb5},
    234	{0xa8, 0xcb},
    235	{0xa9, 0xdd},
    236	{0xaa, 0xec},
    237	{0xab, 0x1a},
    238
    239	{0xce, 0x78},
    240	{0xcf, 0x6e},
    241	{0xd0, 0x0a},
    242	{0xd1, 0x0c},
    243	{0xd2, 0x84},
    244	{0xd3, 0x90},
    245	{0xd4, 0x1e},
    246
    247	{0x5a, 0x24},
    248	{0x5b, 0x1f},
    249	{0x5c, 0x88},
    250	{0x5d, 0x60},
    251
    252	{0xac, 0x6e},
    253	{0xbe, 0xff},
    254	{0xbf, 0x00},
    255
    256	{0x0f, 0x1d},
    257	{0x0f, 0x1f},
    258};
    259
    260static const struct ov7740_framesize ov7740_framesizes[] = {
    261	{
    262		.width		= VGA_WIDTH,
    263		.height		= VGA_HEIGHT,
    264		.regs		= ov7740_vga,
    265		.reg_num	= ARRAY_SIZE(ov7740_vga),
    266	},
    267};
    268
    269#ifdef CONFIG_VIDEO_ADV_DEBUG
    270static int ov7740_get_register(struct v4l2_subdev *sd,
    271			       struct v4l2_dbg_register *reg)
    272{
    273	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
    274	struct regmap *regmap = ov7740->regmap;
    275	unsigned int val = 0;
    276	int ret;
    277
    278	ret = regmap_read(regmap, reg->reg & 0xff, &val);
    279	reg->val = val;
    280	reg->size = 1;
    281
    282	return ret;
    283}
    284
    285static int ov7740_set_register(struct v4l2_subdev *sd,
    286			       const struct v4l2_dbg_register *reg)
    287{
    288	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
    289	struct regmap *regmap = ov7740->regmap;
    290
    291	regmap_write(regmap, reg->reg & 0xff, reg->val & 0xff);
    292
    293	return 0;
    294}
    295#endif
    296
    297static int ov7740_set_power(struct ov7740 *ov7740, int on)
    298{
    299	int ret;
    300
    301	if (on) {
    302		ret = clk_prepare_enable(ov7740->xvclk);
    303		if (ret)
    304			return ret;
    305
    306		if (ov7740->pwdn_gpio)
    307			gpiod_direction_output(ov7740->pwdn_gpio, 0);
    308
    309		if (ov7740->resetb_gpio) {
    310			gpiod_set_value(ov7740->resetb_gpio, 1);
    311			usleep_range(500, 1000);
    312			gpiod_set_value(ov7740->resetb_gpio, 0);
    313			usleep_range(3000, 5000);
    314		}
    315	} else {
    316		clk_disable_unprepare(ov7740->xvclk);
    317
    318		if (ov7740->pwdn_gpio)
    319			gpiod_direction_output(ov7740->pwdn_gpio, 0);
    320	}
    321
    322	return 0;
    323}
    324
    325static const struct v4l2_subdev_core_ops ov7740_subdev_core_ops = {
    326	.log_status = v4l2_ctrl_subdev_log_status,
    327#ifdef CONFIG_VIDEO_ADV_DEBUG
    328	.g_register = ov7740_get_register,
    329	.s_register = ov7740_set_register,
    330#endif
    331	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
    332	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
    333};
    334
    335static int ov7740_set_white_balance(struct ov7740 *ov7740, int awb)
    336{
    337	struct regmap *regmap = ov7740->regmap;
    338	unsigned int value;
    339	int ret;
    340
    341	ret = regmap_read(regmap, REG_ISP_CTRL00, &value);
    342	if (!ret) {
    343		if (awb)
    344			value |= (ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
    345		else
    346			value &= ~(ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
    347		ret = regmap_write(regmap, REG_ISP_CTRL00, value);
    348		if (ret)
    349			return ret;
    350	}
    351
    352	if (!awb) {
    353		ret = regmap_write(regmap, REG_BGAIN,
    354				   ov7740->blue_balance->val);
    355		if (ret)
    356			return ret;
    357
    358		ret = regmap_write(regmap, REG_RGAIN, ov7740->red_balance->val);
    359		if (ret)
    360			return ret;
    361	}
    362
    363	return 0;
    364}
    365
    366static int ov7740_set_saturation(struct regmap *regmap, int value)
    367{
    368	int ret;
    369
    370	ret = regmap_write(regmap, REG_USAT, (unsigned char)value);
    371	if (ret)
    372		return ret;
    373
    374	return regmap_write(regmap, REG_VSAT, (unsigned char)value);
    375}
    376
    377static int ov7740_set_gain(struct regmap *regmap, int value)
    378{
    379	int ret;
    380
    381	ret = regmap_write(regmap, REG_GAIN, value & 0xff);
    382	if (ret)
    383		return ret;
    384
    385	ret = regmap_update_bits(regmap, REG_CTRL15,
    386				 REG15_GAIN_MSB, (value >> 8) & 0x3);
    387	if (!ret)
    388		ret = regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
    389
    390	return ret;
    391}
    392
    393static int ov7740_set_autogain(struct regmap *regmap, int value)
    394{
    395	unsigned int reg;
    396	int ret;
    397
    398	ret = regmap_read(regmap, REG_REG13, &reg);
    399	if (ret)
    400		return ret;
    401	if (value)
    402		reg |= REG13_AGC_EN;
    403	else
    404		reg &= ~REG13_AGC_EN;
    405	return regmap_write(regmap, REG_REG13, reg);
    406}
    407
    408static int ov7740_set_brightness(struct regmap *regmap, int value)
    409{
    410	/* Turn off AEC/AGC */
    411	regmap_update_bits(regmap, REG_REG13, REG13_AEC_EN, 0);
    412	regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
    413
    414	if (value >= 0) {
    415		regmap_write(regmap, REG_YBRIGHT, (unsigned char)value);
    416		regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 0);
    417	} else{
    418		regmap_write(regmap, REG_YBRIGHT, (unsigned char)(-value));
    419		regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 1);
    420	}
    421
    422	return 0;
    423}
    424
    425static int ov7740_set_contrast(struct regmap *regmap, int value)
    426{
    427	return regmap_write(regmap, REG_YGAIN, (unsigned char)value);
    428}
    429
    430static int ov7740_get_gain(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl)
    431{
    432	struct regmap *regmap = ov7740->regmap;
    433	unsigned int value0, value1;
    434	int ret;
    435
    436	if (!ctrl->val)
    437		return 0;
    438
    439	ret = regmap_read(regmap, REG_GAIN, &value0);
    440	if (ret)
    441		return ret;
    442	ret = regmap_read(regmap, REG_CTRL15, &value1);
    443	if (ret)
    444		return ret;
    445
    446	ov7740->gain->val = (value1 << 8) | (value0 & 0xff);
    447
    448	return 0;
    449}
    450
    451static int ov7740_get_exp(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl)
    452{
    453	struct regmap *regmap = ov7740->regmap;
    454	unsigned int value0, value1;
    455	int ret;
    456
    457	if (ctrl->val == V4L2_EXPOSURE_MANUAL)
    458		return 0;
    459
    460	ret = regmap_read(regmap, REG_AEC, &value0);
    461	if (ret)
    462		return ret;
    463	ret = regmap_read(regmap, REG_HAEC, &value1);
    464	if (ret)
    465		return ret;
    466
    467	ov7740->exposure->val = (value1 << 8) | (value0 & 0xff);
    468
    469	return 0;
    470}
    471
    472static int ov7740_set_exp(struct regmap *regmap, int value)
    473{
    474	int ret;
    475
    476	/* Turn off AEC/AGC */
    477	ret = regmap_update_bits(regmap, REG_REG13,
    478				 REG13_AEC_EN | REG13_AGC_EN, 0);
    479	if (ret)
    480		return ret;
    481
    482	ret = regmap_write(regmap, REG_AEC, (unsigned char)value);
    483	if (ret)
    484		return ret;
    485
    486	return regmap_write(regmap, REG_HAEC, (unsigned char)(value >> 8));
    487}
    488
    489static int ov7740_set_autoexp(struct regmap *regmap,
    490			      enum v4l2_exposure_auto_type value)
    491{
    492	unsigned int reg;
    493	int ret;
    494
    495	ret = regmap_read(regmap, REG_REG13, &reg);
    496	if (!ret) {
    497		if (value == V4L2_EXPOSURE_AUTO)
    498			reg |= (REG13_AEC_EN | REG13_AGC_EN);
    499		else
    500			reg &= ~(REG13_AEC_EN | REG13_AGC_EN);
    501		ret = regmap_write(regmap, REG_REG13, reg);
    502	}
    503
    504	return ret;
    505}
    506
    507
    508static int ov7740_get_volatile_ctrl(struct v4l2_ctrl *ctrl)
    509{
    510	struct ov7740 *ov7740 = container_of(ctrl->handler,
    511					     struct ov7740, ctrl_handler);
    512	int ret;
    513
    514	switch (ctrl->id) {
    515	case V4L2_CID_AUTOGAIN:
    516		ret = ov7740_get_gain(ov7740, ctrl);
    517		break;
    518	case V4L2_CID_EXPOSURE_AUTO:
    519		ret = ov7740_get_exp(ov7740, ctrl);
    520		break;
    521	default:
    522		ret = -EINVAL;
    523		break;
    524	}
    525	return ret;
    526}
    527
    528static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl)
    529{
    530	struct ov7740 *ov7740 = container_of(ctrl->handler,
    531					     struct ov7740, ctrl_handler);
    532	struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
    533	struct regmap *regmap = ov7740->regmap;
    534	int ret;
    535	u8 val;
    536
    537	if (!pm_runtime_get_if_in_use(&client->dev))
    538		return 0;
    539
    540	switch (ctrl->id) {
    541	case V4L2_CID_AUTO_WHITE_BALANCE:
    542		ret = ov7740_set_white_balance(ov7740, ctrl->val);
    543		break;
    544	case V4L2_CID_SATURATION:
    545		ret = ov7740_set_saturation(regmap, ctrl->val);
    546		break;
    547	case V4L2_CID_BRIGHTNESS:
    548		ret = ov7740_set_brightness(regmap, ctrl->val);
    549		break;
    550	case V4L2_CID_CONTRAST:
    551		ret = ov7740_set_contrast(regmap, ctrl->val);
    552		break;
    553	case V4L2_CID_VFLIP:
    554		val = ctrl->val ? REG0C_IMG_FLIP : 0x00;
    555		ret = regmap_update_bits(regmap, REG_REG0C,
    556					 REG0C_IMG_FLIP, val);
    557		break;
    558	case V4L2_CID_HFLIP:
    559		val = ctrl->val ? REG0C_IMG_MIRROR : 0x00;
    560		ret = regmap_update_bits(regmap, REG_REG0C,
    561					 REG0C_IMG_MIRROR, val);
    562		break;
    563	case V4L2_CID_AUTOGAIN:
    564		if (!ctrl->val)
    565			ret = ov7740_set_gain(regmap, ov7740->gain->val);
    566		else
    567			ret = ov7740_set_autogain(regmap, ctrl->val);
    568		break;
    569
    570	case V4L2_CID_EXPOSURE_AUTO:
    571		if (ctrl->val == V4L2_EXPOSURE_MANUAL)
    572			ret = ov7740_set_exp(regmap, ov7740->exposure->val);
    573		else
    574			ret = ov7740_set_autoexp(regmap, ctrl->val);
    575		break;
    576	default:
    577		ret = -EINVAL;
    578		break;
    579	}
    580
    581	pm_runtime_put(&client->dev);
    582
    583	return ret;
    584}
    585
    586static const struct v4l2_ctrl_ops ov7740_ctrl_ops = {
    587	.g_volatile_ctrl = ov7740_get_volatile_ctrl,
    588	.s_ctrl = ov7740_set_ctrl,
    589};
    590
    591static int ov7740_start_streaming(struct ov7740 *ov7740)
    592{
    593	int ret;
    594
    595	if (ov7740->fmt) {
    596		ret = regmap_multi_reg_write(ov7740->regmap,
    597					     ov7740->fmt->regs,
    598					     ov7740->fmt->reg_num);
    599		if (ret)
    600			return ret;
    601	}
    602
    603	if (ov7740->frmsize) {
    604		ret = regmap_multi_reg_write(ov7740->regmap,
    605					     ov7740->frmsize->regs,
    606					     ov7740->frmsize->reg_num);
    607		if (ret)
    608			return ret;
    609	}
    610
    611	return __v4l2_ctrl_handler_setup(ov7740->subdev.ctrl_handler);
    612}
    613
    614static int ov7740_set_stream(struct v4l2_subdev *sd, int enable)
    615{
    616	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
    617	struct i2c_client *client = v4l2_get_subdevdata(sd);
    618	int ret = 0;
    619
    620	mutex_lock(&ov7740->mutex);
    621	if (ov7740->streaming == enable) {
    622		mutex_unlock(&ov7740->mutex);
    623		return 0;
    624	}
    625
    626	if (enable) {
    627		ret = pm_runtime_resume_and_get(&client->dev);
    628		if (ret < 0)
    629			goto err_unlock;
    630
    631		ret = ov7740_start_streaming(ov7740);
    632		if (ret)
    633			goto err_rpm_put;
    634	} else {
    635		pm_runtime_put(&client->dev);
    636	}
    637
    638	ov7740->streaming = enable;
    639
    640	mutex_unlock(&ov7740->mutex);
    641	return ret;
    642
    643err_rpm_put:
    644	pm_runtime_put(&client->dev);
    645err_unlock:
    646	mutex_unlock(&ov7740->mutex);
    647	return ret;
    648}
    649
    650static int ov7740_g_frame_interval(struct v4l2_subdev *sd,
    651				   struct v4l2_subdev_frame_interval *ival)
    652{
    653	struct v4l2_fract *tpf = &ival->interval;
    654
    655
    656	tpf->numerator = 1;
    657	tpf->denominator = 60;
    658
    659	return 0;
    660}
    661
    662static int ov7740_s_frame_interval(struct v4l2_subdev *sd,
    663				   struct v4l2_subdev_frame_interval *ival)
    664{
    665	struct v4l2_fract *tpf = &ival->interval;
    666
    667
    668	tpf->numerator = 1;
    669	tpf->denominator = 60;
    670
    671	return 0;
    672}
    673
    674static const struct v4l2_subdev_video_ops ov7740_subdev_video_ops = {
    675	.s_stream = ov7740_set_stream,
    676	.s_frame_interval = ov7740_s_frame_interval,
    677	.g_frame_interval = ov7740_g_frame_interval,
    678};
    679
    680static const struct reg_sequence ov7740_format_yuyv[] = {
    681	{0x12, 0x00},
    682	{0x36, 0x3f},
    683	{0x80, 0x7f},
    684	{0x83, 0x01},
    685};
    686
    687static const struct reg_sequence ov7740_format_bggr8[] = {
    688	{0x36, 0x2f},
    689	{0x80, 0x01},
    690	{0x83, 0x04},
    691};
    692
    693static const struct ov7740_pixfmt ov7740_formats[] = {
    694	{
    695		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
    696		.colorspace = V4L2_COLORSPACE_SRGB,
    697		.regs = ov7740_format_yuyv,
    698		.reg_num = ARRAY_SIZE(ov7740_format_yuyv),
    699	},
    700	{
    701		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
    702		.colorspace = V4L2_COLORSPACE_SRGB,
    703		.regs = ov7740_format_bggr8,
    704		.reg_num = ARRAY_SIZE(ov7740_format_bggr8),
    705	}
    706};
    707#define N_OV7740_FMTS ARRAY_SIZE(ov7740_formats)
    708
    709static int ov7740_enum_mbus_code(struct v4l2_subdev *sd,
    710				 struct v4l2_subdev_state *sd_state,
    711				 struct v4l2_subdev_mbus_code_enum *code)
    712{
    713	if (code->pad || code->index >= N_OV7740_FMTS)
    714		return -EINVAL;
    715
    716	code->code = ov7740_formats[code->index].mbus_code;
    717
    718	return 0;
    719}
    720
    721static int ov7740_enum_frame_interval(struct v4l2_subdev *sd,
    722				struct v4l2_subdev_state *sd_state,
    723				struct v4l2_subdev_frame_interval_enum *fie)
    724{
    725	if (fie->pad)
    726		return -EINVAL;
    727
    728	if (fie->index >= 1)
    729		return -EINVAL;
    730
    731	if ((fie->width != VGA_WIDTH) || (fie->height != VGA_HEIGHT))
    732		return -EINVAL;
    733
    734	fie->interval.numerator = 1;
    735	fie->interval.denominator = 60;
    736
    737	return 0;
    738}
    739
    740static int ov7740_enum_frame_size(struct v4l2_subdev *sd,
    741				  struct v4l2_subdev_state *sd_state,
    742				  struct v4l2_subdev_frame_size_enum *fse)
    743{
    744	if (fse->pad)
    745		return -EINVAL;
    746
    747	if (fse->index > 0)
    748		return -EINVAL;
    749
    750	fse->min_width = fse->max_width = VGA_WIDTH;
    751	fse->min_height = fse->max_height = VGA_HEIGHT;
    752
    753	return 0;
    754}
    755
    756static int ov7740_try_fmt_internal(struct v4l2_subdev *sd,
    757				   struct v4l2_mbus_framefmt *fmt,
    758				   const struct ov7740_pixfmt **ret_fmt,
    759				   const struct ov7740_framesize **ret_frmsize)
    760{
    761	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
    762	const struct ov7740_framesize *fsize = &ov7740_framesizes[0];
    763	int index, i;
    764
    765	for (index = 0; index < N_OV7740_FMTS; index++) {
    766		if (ov7740_formats[index].mbus_code == fmt->code)
    767			break;
    768	}
    769	if (index >= N_OV7740_FMTS) {
    770		/* default to first format */
    771		index = 0;
    772		fmt->code = ov7740_formats[0].mbus_code;
    773	}
    774	if (ret_fmt != NULL)
    775		*ret_fmt = ov7740_formats + index;
    776
    777	for (i = 0; i < ARRAY_SIZE(ov7740_framesizes); i++) {
    778		if ((fsize->width >= fmt->width) &&
    779		    (fsize->height >= fmt->height)) {
    780			fmt->width = fsize->width;
    781			fmt->height = fsize->height;
    782			break;
    783		}
    784
    785		fsize++;
    786	}
    787	if (i >= ARRAY_SIZE(ov7740_framesizes)) {
    788		fsize = &ov7740_framesizes[0];
    789		fmt->width = fsize->width;
    790		fmt->height = fsize->height;
    791	}
    792	if (ret_frmsize != NULL)
    793		*ret_frmsize = fsize;
    794
    795	fmt->field = V4L2_FIELD_NONE;
    796	fmt->colorspace = ov7740_formats[index].colorspace;
    797
    798	ov7740->format = *fmt;
    799
    800	return 0;
    801}
    802
    803static int ov7740_set_fmt(struct v4l2_subdev *sd,
    804			  struct v4l2_subdev_state *sd_state,
    805			  struct v4l2_subdev_format *format)
    806{
    807	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
    808	const struct ov7740_pixfmt *ovfmt;
    809	const struct ov7740_framesize *fsize;
    810#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
    811	struct v4l2_mbus_framefmt *mbus_fmt;
    812#endif
    813	int ret;
    814
    815	mutex_lock(&ov7740->mutex);
    816	if (format->pad) {
    817		ret = -EINVAL;
    818		goto error;
    819	}
    820
    821	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
    822		ret = ov7740_try_fmt_internal(sd, &format->format, NULL, NULL);
    823		if (ret)
    824			goto error;
    825#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
    826		mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state,
    827						      format->pad);
    828		*mbus_fmt = format->format;
    829#endif
    830		mutex_unlock(&ov7740->mutex);
    831		return 0;
    832	}
    833
    834	ret = ov7740_try_fmt_internal(sd, &format->format, &ovfmt, &fsize);
    835	if (ret)
    836		goto error;
    837
    838	ov7740->fmt = ovfmt;
    839	ov7740->frmsize = fsize;
    840
    841	mutex_unlock(&ov7740->mutex);
    842	return 0;
    843
    844error:
    845	mutex_unlock(&ov7740->mutex);
    846	return ret;
    847}
    848
    849static int ov7740_get_fmt(struct v4l2_subdev *sd,
    850			  struct v4l2_subdev_state *sd_state,
    851			  struct v4l2_subdev_format *format)
    852{
    853	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
    854#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
    855	struct v4l2_mbus_framefmt *mbus_fmt;
    856#endif
    857	int ret = 0;
    858
    859	mutex_lock(&ov7740->mutex);
    860	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
    861#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
    862		mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
    863		format->format = *mbus_fmt;
    864		ret = 0;
    865#else
    866		ret = -EINVAL;
    867#endif
    868	} else {
    869		format->format = ov7740->format;
    870	}
    871	mutex_unlock(&ov7740->mutex);
    872
    873	return ret;
    874}
    875
    876static const struct v4l2_subdev_pad_ops ov7740_subdev_pad_ops = {
    877	.enum_frame_interval = ov7740_enum_frame_interval,
    878	.enum_frame_size = ov7740_enum_frame_size,
    879	.enum_mbus_code = ov7740_enum_mbus_code,
    880	.get_fmt = ov7740_get_fmt,
    881	.set_fmt = ov7740_set_fmt,
    882};
    883
    884static const struct v4l2_subdev_ops ov7740_subdev_ops = {
    885	.core	= &ov7740_subdev_core_ops,
    886	.video	= &ov7740_subdev_video_ops,
    887	.pad	= &ov7740_subdev_pad_ops,
    888};
    889
    890static void ov7740_get_default_format(struct v4l2_subdev *sd,
    891				      struct v4l2_mbus_framefmt *format)
    892{
    893	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
    894
    895	format->width = ov7740->frmsize->width;
    896	format->height = ov7740->frmsize->height;
    897	format->colorspace = ov7740->fmt->colorspace;
    898	format->code = ov7740->fmt->mbus_code;
    899	format->field = V4L2_FIELD_NONE;
    900}
    901
    902#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
    903static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
    904{
    905	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
    906	struct v4l2_mbus_framefmt *format =
    907				v4l2_subdev_get_try_format(sd, fh->state, 0);
    908
    909	mutex_lock(&ov7740->mutex);
    910	ov7740_get_default_format(sd, format);
    911	mutex_unlock(&ov7740->mutex);
    912
    913	return 0;
    914}
    915
    916static const struct v4l2_subdev_internal_ops ov7740_subdev_internal_ops = {
    917	.open = ov7740_open,
    918};
    919#endif
    920
    921static int ov7740_probe_dt(struct i2c_client *client,
    922			   struct ov7740 *ov7740)
    923{
    924	ov7740->resetb_gpio = devm_gpiod_get_optional(&client->dev, "reset",
    925			GPIOD_OUT_HIGH);
    926	if (IS_ERR(ov7740->resetb_gpio)) {
    927		dev_info(&client->dev, "can't get %s GPIO\n", "reset");
    928		return PTR_ERR(ov7740->resetb_gpio);
    929	}
    930
    931	ov7740->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
    932			GPIOD_OUT_LOW);
    933	if (IS_ERR(ov7740->pwdn_gpio)) {
    934		dev_info(&client->dev, "can't get %s GPIO\n", "powerdown");
    935		return PTR_ERR(ov7740->pwdn_gpio);
    936	}
    937
    938	return 0;
    939}
    940
    941static int ov7740_detect(struct ov7740 *ov7740)
    942{
    943	struct regmap *regmap = ov7740->regmap;
    944	unsigned int midh, midl, pidh, pidl;
    945	int ret;
    946
    947	ret = regmap_read(regmap, REG_MIDH, &midh);
    948	if (ret)
    949		return ret;
    950	if (midh != 0x7f)
    951		return -ENODEV;
    952
    953	ret = regmap_read(regmap, REG_MIDL, &midl);
    954	if (ret)
    955		return ret;
    956	if (midl != 0xa2)
    957		return -ENODEV;
    958
    959	ret = regmap_read(regmap, REG_PIDH, &pidh);
    960	if (ret)
    961		return ret;
    962	if (pidh != 0x77)
    963		return -ENODEV;
    964
    965	ret = regmap_read(regmap, REG_PIDL, &pidl);
    966	if (ret)
    967		return ret;
    968	if ((pidl != 0x40) && (pidl != 0x41) && (pidl != 0x42))
    969		return -ENODEV;
    970
    971	return 0;
    972}
    973
    974static int ov7740_init_controls(struct ov7740 *ov7740)
    975{
    976	struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
    977	struct v4l2_ctrl_handler *ctrl_hdlr = &ov7740->ctrl_handler;
    978	int ret;
    979
    980	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
    981	if (ret < 0)
    982		return ret;
    983
    984	ctrl_hdlr->lock = &ov7740->mutex;
    985	ov7740->auto_wb = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
    986					  V4L2_CID_AUTO_WHITE_BALANCE,
    987					  0, 1, 1, 1);
    988	ov7740->blue_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
    989					       V4L2_CID_BLUE_BALANCE,
    990					       0, 0xff, 1, 0x80);
    991	ov7740->red_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
    992					      V4L2_CID_RED_BALANCE,
    993					      0, 0xff, 1, 0x80);
    994
    995	ov7740->brightness = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
    996					     V4L2_CID_BRIGHTNESS,
    997					     -255, 255, 1, 0);
    998	ov7740->contrast = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
    999					   V4L2_CID_CONTRAST,
   1000					   0, 127, 1, 0x20);
   1001	ov7740->saturation = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
   1002			  V4L2_CID_SATURATION, 0, 256, 1, 0x80);
   1003	ov7740->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
   1004					V4L2_CID_HFLIP, 0, 1, 1, 0);
   1005	ov7740->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
   1006					V4L2_CID_VFLIP, 0, 1, 1, 0);
   1007
   1008	ov7740->gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
   1009				       V4L2_CID_GAIN, 0, 1023, 1, 500);
   1010
   1011	ov7740->auto_gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
   1012					    V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
   1013
   1014	ov7740->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
   1015					   V4L2_CID_EXPOSURE, 0, 65535, 1, 500);
   1016
   1017	ov7740->auto_exposure = v4l2_ctrl_new_std_menu(ctrl_hdlr,
   1018					&ov7740_ctrl_ops,
   1019					V4L2_CID_EXPOSURE_AUTO,
   1020					V4L2_EXPOSURE_MANUAL, 0,
   1021					V4L2_EXPOSURE_AUTO);
   1022
   1023	v4l2_ctrl_auto_cluster(3, &ov7740->auto_wb, 0, false);
   1024	v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true);
   1025	v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure,
   1026			       V4L2_EXPOSURE_MANUAL, true);
   1027
   1028	if (ctrl_hdlr->error) {
   1029		ret = ctrl_hdlr->error;
   1030		dev_err(&client->dev, "controls initialisation failed (%d)\n",
   1031			ret);
   1032		goto error;
   1033	}
   1034
   1035	ret = v4l2_ctrl_handler_setup(ctrl_hdlr);
   1036	if (ret) {
   1037		dev_err(&client->dev, "%s control init failed (%d)\n",
   1038			__func__, ret);
   1039		goto error;
   1040	}
   1041
   1042	ov7740->subdev.ctrl_handler = ctrl_hdlr;
   1043	return 0;
   1044
   1045error:
   1046	v4l2_ctrl_handler_free(ctrl_hdlr);
   1047	mutex_destroy(&ov7740->mutex);
   1048	return ret;
   1049}
   1050
   1051static void ov7740_free_controls(struct ov7740 *ov7740)
   1052{
   1053	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
   1054	mutex_destroy(&ov7740->mutex);
   1055}
   1056
   1057#define OV7740_MAX_REGISTER     0xff
   1058static const struct regmap_config ov7740_regmap_config = {
   1059	.reg_bits	= 8,
   1060	.val_bits	= 8,
   1061	.max_register	= OV7740_MAX_REGISTER,
   1062};
   1063
   1064static int ov7740_probe(struct i2c_client *client)
   1065{
   1066	struct ov7740 *ov7740;
   1067	struct v4l2_subdev *sd;
   1068	int ret;
   1069
   1070	ov7740 = devm_kzalloc(&client->dev, sizeof(*ov7740), GFP_KERNEL);
   1071	if (!ov7740)
   1072		return -ENOMEM;
   1073
   1074	ov7740->xvclk = devm_clk_get(&client->dev, "xvclk");
   1075	if (IS_ERR(ov7740->xvclk)) {
   1076		ret = PTR_ERR(ov7740->xvclk);
   1077		dev_err(&client->dev,
   1078			"OV7740: fail to get xvclk: %d\n", ret);
   1079		return ret;
   1080	}
   1081
   1082	ret = ov7740_probe_dt(client, ov7740);
   1083	if (ret)
   1084		return ret;
   1085
   1086	ov7740->regmap = devm_regmap_init_sccb(client, &ov7740_regmap_config);
   1087	if (IS_ERR(ov7740->regmap)) {
   1088		ret = PTR_ERR(ov7740->regmap);
   1089		dev_err(&client->dev, "Failed to allocate register map: %d\n",
   1090			ret);
   1091		return ret;
   1092	}
   1093
   1094	sd = &ov7740->subdev;
   1095	v4l2_i2c_subdev_init(sd, client, &ov7740_subdev_ops);
   1096
   1097#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
   1098	sd->internal_ops = &ov7740_subdev_internal_ops;
   1099	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
   1100#endif
   1101
   1102#if defined(CONFIG_MEDIA_CONTROLLER)
   1103	ov7740->pad.flags = MEDIA_PAD_FL_SOURCE;
   1104	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
   1105	ret = media_entity_pads_init(&sd->entity, 1, &ov7740->pad);
   1106	if (ret)
   1107		return ret;
   1108#endif
   1109
   1110	ret = ov7740_set_power(ov7740, 1);
   1111	if (ret)
   1112		return ret;
   1113
   1114	pm_runtime_set_active(&client->dev);
   1115	pm_runtime_enable(&client->dev);
   1116
   1117	ret = ov7740_detect(ov7740);
   1118	if (ret)
   1119		goto error_detect;
   1120
   1121	mutex_init(&ov7740->mutex);
   1122
   1123	ret = ov7740_init_controls(ov7740);
   1124	if (ret)
   1125		goto error_init_controls;
   1126
   1127	v4l_info(client, "chip found @ 0x%02x (%s)\n",
   1128			client->addr << 1, client->adapter->name);
   1129
   1130	ov7740->fmt = &ov7740_formats[0];
   1131	ov7740->frmsize = &ov7740_framesizes[0];
   1132
   1133	ov7740_get_default_format(sd, &ov7740->format);
   1134
   1135	ret = v4l2_async_register_subdev(sd);
   1136	if (ret)
   1137		goto error_async_register;
   1138
   1139	pm_runtime_idle(&client->dev);
   1140
   1141	return 0;
   1142
   1143error_async_register:
   1144	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
   1145error_init_controls:
   1146	ov7740_free_controls(ov7740);
   1147error_detect:
   1148	pm_runtime_disable(&client->dev);
   1149	pm_runtime_set_suspended(&client->dev);
   1150	ov7740_set_power(ov7740, 0);
   1151	media_entity_cleanup(&ov7740->subdev.entity);
   1152
   1153	return ret;
   1154}
   1155
   1156static int ov7740_remove(struct i2c_client *client)
   1157{
   1158	struct v4l2_subdev *sd = i2c_get_clientdata(client);
   1159	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
   1160
   1161	mutex_destroy(&ov7740->mutex);
   1162	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
   1163	media_entity_cleanup(&ov7740->subdev.entity);
   1164	v4l2_async_unregister_subdev(sd);
   1165	ov7740_free_controls(ov7740);
   1166
   1167	pm_runtime_get_sync(&client->dev);
   1168	pm_runtime_disable(&client->dev);
   1169	pm_runtime_set_suspended(&client->dev);
   1170	pm_runtime_put_noidle(&client->dev);
   1171
   1172	ov7740_set_power(ov7740, 0);
   1173	return 0;
   1174}
   1175
   1176static int __maybe_unused ov7740_runtime_suspend(struct device *dev)
   1177{
   1178	struct v4l2_subdev *sd = dev_get_drvdata(dev);
   1179	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
   1180
   1181	ov7740_set_power(ov7740, 0);
   1182
   1183	return 0;
   1184}
   1185
   1186static int __maybe_unused ov7740_runtime_resume(struct device *dev)
   1187{
   1188	struct v4l2_subdev *sd = dev_get_drvdata(dev);
   1189	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
   1190
   1191	return ov7740_set_power(ov7740, 1);
   1192}
   1193
   1194static const struct i2c_device_id ov7740_id[] = {
   1195	{ "ov7740", 0 },
   1196	{ /* sentinel */ }
   1197};
   1198MODULE_DEVICE_TABLE(i2c, ov7740_id);
   1199
   1200static const struct dev_pm_ops ov7740_pm_ops = {
   1201	SET_RUNTIME_PM_OPS(ov7740_runtime_suspend, ov7740_runtime_resume, NULL)
   1202};
   1203
   1204static const struct of_device_id ov7740_of_match[] = {
   1205	{.compatible = "ovti,ov7740", },
   1206	{ /* sentinel */ },
   1207};
   1208MODULE_DEVICE_TABLE(of, ov7740_of_match);
   1209
   1210static struct i2c_driver ov7740_i2c_driver = {
   1211	.driver = {
   1212		.name = "ov7740",
   1213		.pm = &ov7740_pm_ops,
   1214		.of_match_table = of_match_ptr(ov7740_of_match),
   1215	},
   1216	.probe_new = ov7740_probe,
   1217	.remove   = ov7740_remove,
   1218	.id_table = ov7740_id,
   1219};
   1220module_i2c_driver(ov7740_i2c_driver);
   1221
   1222MODULE_DESCRIPTION("The V4L2 driver for Omnivision 7740 sensor");
   1223MODULE_AUTHOR("Songjun Wu <songjun.wu@atmel.com>");
   1224MODULE_LICENSE("GPL v2");