brintos

brintos / linux-shallow public Read only

0
0
Text · 48.6 KiB · 326f50a Raw
2007 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2023 Jacopo Mondi <jacopo.mondi@ideasonboard.com>4 * Copyright (C) 2022 Nicholas Roth <nicholas@rothemail.net>5 * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd.6 */7 8#include <linux/unaligned.h>9 10#include <linux/clk.h>11#include <linux/delay.h>12#include <linux/device.h>13#include <linux/gpio/consumer.h>14#include <linux/i2c.h>15#include <linux/module.h>16#include <linux/of.h>17#include <linux/pm_runtime.h>18#include <linux/property.h>19#include <linux/regulator/consumer.h>20#include <linux/slab.h>21 22#include <media/media-entity.h>23#include <media/v4l2-async.h>24#include <media/v4l2-common.h>25#include <media/v4l2-ctrls.h>26#include <media/v4l2-device.h>27#include <media/v4l2-event.h>28#include <media/v4l2-fwnode.h>29#include <media/v4l2-mediabus.h>30#include <media/v4l2-subdev.h>31 32#define OV8858_LINK_FREQ		360000000U33#define OV8858_XVCLK_FREQ		2400000034 35#define OV8858_REG_SIZE_SHIFT		1636#define OV8858_REG_ADDR_MASK		0xffff37#define OV8858_REG_8BIT(n)		((1U << OV8858_REG_SIZE_SHIFT) | (n))38#define OV8858_REG_16BIT(n)		((2U << OV8858_REG_SIZE_SHIFT) | (n))39#define OV8858_REG_24BIT(n)		((3U << OV8858_REG_SIZE_SHIFT) | (n))40 41#define OV8858_REG_SC_CTRL0100		OV8858_REG_8BIT(0x0100)42#define OV8858_MODE_SW_STANDBY		0x043#define OV8858_MODE_STREAMING		0x144 45#define OV8858_REG_CHIP_ID		OV8858_REG_24BIT(0x300a)46#define OV8858_CHIP_ID			0x00885847 48#define OV8858_REG_SUB_ID		OV8858_REG_8BIT(0x302a)49#define OV8858_R1A			0xb050#define OV8858_R2A			0xb251 52#define OV8858_REG_LONG_EXPO		OV8858_REG_24BIT(0x3500)53#define OV8858_EXPOSURE_MIN		454#define OV8858_EXPOSURE_STEP		155#define OV8858_EXPOSURE_MARGIN		456 57#define OV8858_REG_LONG_GAIN		OV8858_REG_16BIT(0x3508)58#define OV8858_LONG_GAIN_MIN		0x059#define OV8858_LONG_GAIN_MAX		0x7ff60#define OV8858_LONG_GAIN_STEP		161#define OV8858_LONG_GAIN_DEFAULT	0x8062 63#define OV8858_REG_LONG_DIGIGAIN	OV8858_REG_16BIT(0x350a)64#define OV8858_LONG_DIGIGAIN_H_MASK	0x3fc065#define OV8858_LONG_DIGIGAIN_L_MASK	0x3f66#define OV8858_LONG_DIGIGAIN_H_SHIFT	267#define OV8858_LONG_DIGIGAIN_MIN	0x068#define OV8858_LONG_DIGIGAIN_MAX	0x3fff69#define OV8858_LONG_DIGIGAIN_STEP	170#define OV8858_LONG_DIGIGAIN_DEFAULT	0x20071 72#define OV8858_REG_VTS			OV8858_REG_16BIT(0x380e)73#define OV8858_VTS_MAX			0x7fff74 75#define OV8858_REG_TEST_PATTERN		OV8858_REG_8BIT(0x5e00)76#define OV8858_TEST_PATTERN_ENABLE	0x8077#define OV8858_TEST_PATTERN_DISABLE	0x078 79#define REG_NULL			0xffff80 81static const char * const ov8858_supply_names[] = {82	"avdd",		/* Analog power */83	"dovdd",	/* Digital I/O power */84	"dvdd",		/* Digital core power */85};86 87struct regval {88	u16 addr;89	u8 val;90};91 92struct regval_modes {93	const struct regval *mode_2lanes;94	const struct regval *mode_4lanes;95};96 97struct ov8858_mode {98	u32 width;99	u32 height;100	u32 hts_def;101	u32 vts_def;102	u32 exp_def;103	const struct regval_modes reg_modes;104};105 106struct ov8858 {107	struct clk		*xvclk;108	struct gpio_desc	*reset_gpio;109	struct gpio_desc	*pwdn_gpio;110	struct regulator_bulk_data supplies[ARRAY_SIZE(ov8858_supply_names)];111 112	struct v4l2_subdev	subdev;113	struct media_pad	pad;114 115	struct v4l2_ctrl_handler ctrl_handler;116	struct v4l2_ctrl	*exposure;117	struct v4l2_ctrl	*hblank;118	struct v4l2_ctrl	*vblank;119 120	const struct regval	*global_regs;121 122	unsigned int		num_lanes;123};124 125static inline struct ov8858 *sd_to_ov8858(struct v4l2_subdev *sd)126{127	return container_of(sd, struct ov8858, subdev);128}129 130static const struct regval ov8858_global_regs_r1a[] = {131	{0x0100, 0x00},132	{0x0100, 0x00},133	{0x0100, 0x00},134	{0x0100, 0x00},135	{0x0302, 0x1e},136	{0x0303, 0x00},137	{0x0304, 0x03},138	{0x030e, 0x00},139	{0x030f, 0x09},140	{0x0312, 0x01},141	{0x031e, 0x0c},142	{0x3600, 0x00},143	{0x3601, 0x00},144	{0x3602, 0x00},145	{0x3603, 0x00},146	{0x3604, 0x22},147	{0x3605, 0x30},148	{0x3606, 0x00},149	{0x3607, 0x20},150	{0x3608, 0x11},151	{0x3609, 0x28},152	{0x360a, 0x00},153	{0x360b, 0x06},154	{0x360c, 0xdc},155	{0x360d, 0x40},156	{0x360e, 0x0c},157	{0x360f, 0x20},158	{0x3610, 0x07},159	{0x3611, 0x20},160	{0x3612, 0x88},161	{0x3613, 0x80},162	{0x3614, 0x58},163	{0x3615, 0x00},164	{0x3616, 0x4a},165	{0x3617, 0xb0},166	{0x3618, 0x56},167	{0x3619, 0x70},168	{0x361a, 0x99},169	{0x361b, 0x00},170	{0x361c, 0x07},171	{0x361d, 0x00},172	{0x361e, 0x00},173	{0x361f, 0x00},174	{0x3638, 0xff},175	{0x3633, 0x0c},176	{0x3634, 0x0c},177	{0x3635, 0x0c},178	{0x3636, 0x0c},179	{0x3645, 0x13},180	{0x3646, 0x83},181	{0x364a, 0x07},182	{0x3015, 0x01},183	{0x3018, 0x32},184	{0x3020, 0x93},185	{0x3022, 0x01},186	{0x3031, 0x0a},187	{0x3034, 0x00},188	{0x3106, 0x01},189	{0x3305, 0xf1},190	{0x3308, 0x00},191	{0x3309, 0x28},192	{0x330a, 0x00},193	{0x330b, 0x20},194	{0x330c, 0x00},195	{0x330d, 0x00},196	{0x330e, 0x00},197	{0x330f, 0x40},198	{0x3307, 0x04},199	{0x3500, 0x00},200	{0x3501, 0x4d},201	{0x3502, 0x40},202	{0x3503, 0x00},203	{0x3505, 0x80},204	{0x3508, 0x04},205	{0x3509, 0x00},206	{0x350c, 0x00},207	{0x350d, 0x80},208	{0x3510, 0x00},209	{0x3511, 0x02},210	{0x3512, 0x00},211	{0x3700, 0x18},212	{0x3701, 0x0c},213	{0x3702, 0x28},214	{0x3703, 0x19},215	{0x3704, 0x14},216	{0x3705, 0x00},217	{0x3706, 0x35},218	{0x3707, 0x04},219	{0x3708, 0x24},220	{0x3709, 0x33},221	{0x370a, 0x00},222	{0x370b, 0xb5},223	{0x370c, 0x04},224	{0x3718, 0x12},225	{0x3719, 0x31},226	{0x3712, 0x42},227	{0x3714, 0x24},228	{0x371e, 0x19},229	{0x371f, 0x40},230	{0x3720, 0x05},231	{0x3721, 0x05},232	{0x3724, 0x06},233	{0x3725, 0x01},234	{0x3726, 0x06},235	{0x3728, 0x05},236	{0x3729, 0x02},237	{0x372a, 0x03},238	{0x372b, 0x53},239	{0x372c, 0xa3},240	{0x372d, 0x53},241	{0x372e, 0x06},242	{0x372f, 0x10},243	{0x3730, 0x01},244	{0x3731, 0x06},245	{0x3732, 0x14},246	{0x3733, 0x10},247	{0x3734, 0x40},248	{0x3736, 0x20},249	{0x373a, 0x05},250	{0x373b, 0x06},251	{0x373c, 0x0a},252	{0x373e, 0x03},253	{0x3755, 0x10},254	{0x3758, 0x00},255	{0x3759, 0x4c},256	{0x375a, 0x06},257	{0x375b, 0x13},258	{0x375c, 0x20},259	{0x375d, 0x02},260	{0x375e, 0x00},261	{0x375f, 0x14},262	{0x3768, 0x22},263	{0x3769, 0x44},264	{0x376a, 0x44},265	{0x3761, 0x00},266	{0x3762, 0x00},267	{0x3763, 0x00},268	{0x3766, 0xff},269	{0x376b, 0x00},270	{0x3772, 0x23},271	{0x3773, 0x02},272	{0x3774, 0x16},273	{0x3775, 0x12},274	{0x3776, 0x04},275	{0x3777, 0x00},276	{0x3778, 0x1b},277	{0x37a0, 0x44},278	{0x37a1, 0x3d},279	{0x37a2, 0x3d},280	{0x37a3, 0x00},281	{0x37a4, 0x00},282	{0x37a5, 0x00},283	{0x37a6, 0x00},284	{0x37a7, 0x44},285	{0x37a8, 0x4c},286	{0x37a9, 0x4c},287	{0x3760, 0x00},288	{0x376f, 0x01},289	{0x37aa, 0x44},290	{0x37ab, 0x2e},291	{0x37ac, 0x2e},292	{0x37ad, 0x33},293	{0x37ae, 0x0d},294	{0x37af, 0x0d},295	{0x37b0, 0x00},296	{0x37b1, 0x00},297	{0x37b2, 0x00},298	{0x37b3, 0x42},299	{0x37b4, 0x42},300	{0x37b5, 0x33},301	{0x37b6, 0x00},302	{0x37b7, 0x00},303	{0x37b8, 0x00},304	{0x37b9, 0xff},305	{0x3800, 0x00},306	{0x3801, 0x0c},307	{0x3802, 0x00},308	{0x3803, 0x0c},309	{0x3804, 0x0c},310	{0x3805, 0xd3},311	{0x3806, 0x09},312	{0x3807, 0xa3},313	{0x3808, 0x06},314	{0x3809, 0x60},315	{0x380a, 0x04},316	{0x380b, 0xc8},317	{0x380c, 0x07},318	{0x380d, 0x88},319	{0x380e, 0x04},320	{0x380f, 0xdc},321	{0x3810, 0x00},322	{0x3811, 0x04},323	{0x3813, 0x02},324	{0x3814, 0x03},325	{0x3815, 0x01},326	{0x3820, 0x00},327	{0x3821, 0x67},328	{0x382a, 0x03},329	{0x382b, 0x01},330	{0x3830, 0x08},331	{0x3836, 0x02},332	{0x3837, 0x18},333	{0x3841, 0xff},334	{0x3846, 0x48},335	{0x3d85, 0x14},336	{0x3f08, 0x08},337	{0x3f0a, 0x80},338	{0x4000, 0xf1},339	{0x4001, 0x10},340	{0x4005, 0x10},341	{0x4002, 0x27},342	{0x4009, 0x81},343	{0x400b, 0x0c},344	{0x401b, 0x00},345	{0x401d, 0x00},346	{0x4020, 0x00},347	{0x4021, 0x04},348	{0x4022, 0x04},349	{0x4023, 0xb9},350	{0x4024, 0x05},351	{0x4025, 0x2a},352	{0x4026, 0x05},353	{0x4027, 0x2b},354	{0x4028, 0x00},355	{0x4029, 0x02},356	{0x402a, 0x04},357	{0x402b, 0x04},358	{0x402c, 0x02},359	{0x402d, 0x02},360	{0x402e, 0x08},361	{0x402f, 0x02},362	{0x401f, 0x00},363	{0x4034, 0x3f},364	{0x403d, 0x04},365	{0x4300, 0xff},366	{0x4301, 0x00},367	{0x4302, 0x0f},368	{0x4316, 0x00},369	{0x4500, 0x38},370	{0x4503, 0x18},371	{0x4600, 0x00},372	{0x4601, 0xcb},373	{0x481f, 0x32},374	{0x4837, 0x16},375	{0x4850, 0x10},376	{0x4851, 0x32},377	{0x4b00, 0x2a},378	{0x4b0d, 0x00},379	{0x4d00, 0x04},380	{0x4d01, 0x18},381	{0x4d02, 0xc3},382	{0x4d03, 0xff},383	{0x4d04, 0xff},384	{0x4d05, 0xff},385	{0x5000, 0x7e},386	{0x5001, 0x01},387	{0x5002, 0x08},388	{0x5003, 0x20},389	{0x5046, 0x12},390	{0x5901, 0x00},391	{0x5e00, 0x00},392	{0x5e01, 0x41},393	{0x382d, 0x7f},394	{0x4825, 0x3a},395	{0x4826, 0x40},396	{0x4808, 0x25},397	{REG_NULL, 0x00},398};399 400static const struct regval ov8858_global_regs_r2a_2lane[] = {401	/*402	 * MIPI=720Mbps, SysClk=144Mhz,Dac Clock=360Mhz.403	 * v00_01_00 (05/29/2014) : initial setting404	 * AM19 : 3617 <- 0xC0405	 * AM20 : change FWC_6K_EN to be default 0x3618=0x5a406	 */407	{0x0103, 0x01}, /* software reset */408	{0x0100, 0x00}, /* software standby */409	{0x0302, 0x1e}, /* pll1_multi */410	{0x0303, 0x00}, /* pll1_divm */411	{0x0304, 0x03}, /* pll1_div_mipi */412	{0x030e, 0x02}, /* pll2_rdiv */413	{0x030f, 0x04}, /* pll2_divsp */414	{0x0312, 0x03}, /* pll2_pre_div0, pll2_r_divdac */415	{0x031e, 0x0c}, /* pll1_no_lat */416	{0x3600, 0x00},417	{0x3601, 0x00},418	{0x3602, 0x00},419	{0x3603, 0x00},420	{0x3604, 0x22},421	{0x3605, 0x20},422	{0x3606, 0x00},423	{0x3607, 0x20},424	{0x3608, 0x11},425	{0x3609, 0x28},426	{0x360a, 0x00},427	{0x360b, 0x05},428	{0x360c, 0xd4},429	{0x360d, 0x40},430	{0x360e, 0x0c},431	{0x360f, 0x20},432	{0x3610, 0x07},433	{0x3611, 0x20},434	{0x3612, 0x88},435	{0x3613, 0x80},436	{0x3614, 0x58},437	{0x3615, 0x00},438	{0x3616, 0x4a},439	{0x3617, 0x90},440	{0x3618, 0x5a},441	{0x3619, 0x70},442	{0x361a, 0x99},443	{0x361b, 0x0a},444	{0x361c, 0x07},445	{0x361d, 0x00},446	{0x361e, 0x00},447	{0x361f, 0x00},448	{0x3638, 0xff},449	{0x3633, 0x0f},450	{0x3634, 0x0f},451	{0x3635, 0x0f},452	{0x3636, 0x12},453	{0x3645, 0x13},454	{0x3646, 0x83},455	{0x364a, 0x07},456	{0x3015, 0x00},457	{0x3018, 0x32}, /* MIPI 2 lane */458	{0x3020, 0x93}, /* Clock switch output normal, pclk_div =/1 */459	{0x3022, 0x01}, /* pd_mipi enable when rst_sync */460	{0x3031, 0x0a}, /* MIPI 10-bit mode */461	{0x3034, 0x00},462	{0x3106, 0x01}, /* sclk_div, sclk_pre_div */463	{0x3305, 0xf1},464	{0x3308, 0x00},465	{0x3309, 0x28},466	{0x330a, 0x00},467	{0x330b, 0x20},468	{0x330c, 0x00},469	{0x330d, 0x00},470	{0x330e, 0x00},471	{0x330f, 0x40},472	{0x3307, 0x04},473	{0x3500, 0x00}, /* exposure H */474	{0x3501, 0x4d}, /* exposure M */475	{0x3502, 0x40}, /* exposure L */476	{0x3503, 0x80}, /* gain delay ?, exposure delay 1 frame, real gain */477	{0x3505, 0x80}, /* gain option */478	{0x3508, 0x02}, /* gain H */479	{0x3509, 0x00}, /* gain L */480	{0x350c, 0x00}, /* short gain H */481	{0x350d, 0x80}, /* short gain L */482	{0x3510, 0x00}, /* short exposure H */483	{0x3511, 0x02}, /* short exposure M */484	{0x3512, 0x00}, /* short exposure L */485	{0x3700, 0x18},486	{0x3701, 0x0c},487	{0x3702, 0x28},488	{0x3703, 0x19},489	{0x3704, 0x14},490	{0x3705, 0x00},491	{0x3706, 0x82},492	{0x3707, 0x04},493	{0x3708, 0x24},494	{0x3709, 0x33},495	{0x370a, 0x01},496	{0x370b, 0x82},497	{0x370c, 0x04},498	{0x3718, 0x12},499	{0x3719, 0x31},500	{0x3712, 0x42},501	{0x3714, 0x24},502	{0x371e, 0x19},503	{0x371f, 0x40},504	{0x3720, 0x05},505	{0x3721, 0x05},506	{0x3724, 0x06},507	{0x3725, 0x01},508	{0x3726, 0x06},509	{0x3728, 0x05},510	{0x3729, 0x02},511	{0x372a, 0x03},512	{0x372b, 0x53},513	{0x372c, 0xa3},514	{0x372d, 0x53},515	{0x372e, 0x06},516	{0x372f, 0x10},517	{0x3730, 0x01},518	{0x3731, 0x06},519	{0x3732, 0x14},520	{0x3733, 0x10},521	{0x3734, 0x40},522	{0x3736, 0x20},523	{0x373a, 0x05},524	{0x373b, 0x06},525	{0x373c, 0x0a},526	{0x373e, 0x03},527	{0x3750, 0x0a},528	{0x3751, 0x0e},529	{0x3755, 0x10},530	{0x3758, 0x00},531	{0x3759, 0x4c},532	{0x375a, 0x06},533	{0x375b, 0x13},534	{0x375c, 0x20},535	{0x375d, 0x02},536	{0x375e, 0x00},537	{0x375f, 0x14},538	{0x3768, 0x22},539	{0x3769, 0x44},540	{0x376a, 0x44},541	{0x3761, 0x00},542	{0x3762, 0x00},543	{0x3763, 0x00},544	{0x3766, 0xff},545	{0x376b, 0x00},546	{0x3772, 0x23},547	{0x3773, 0x02},548	{0x3774, 0x16},549	{0x3775, 0x12},550	{0x3776, 0x04},551	{0x3777, 0x00},552	{0x3778, 0x17},553	{0x37a0, 0x44},554	{0x37a1, 0x3d},555	{0x37a2, 0x3d},556	{0x37a3, 0x00},557	{0x37a4, 0x00},558	{0x37a5, 0x00},559	{0x37a6, 0x00},560	{0x37a7, 0x44},561	{0x37a8, 0x4c},562	{0x37a9, 0x4c},563	{0x3760, 0x00},564	{0x376f, 0x01},565	{0x37aa, 0x44},566	{0x37ab, 0x2e},567	{0x37ac, 0x2e},568	{0x37ad, 0x33},569	{0x37ae, 0x0d},570	{0x37af, 0x0d},571	{0x37b0, 0x00},572	{0x37b1, 0x00},573	{0x37b2, 0x00},574	{0x37b3, 0x42},575	{0x37b4, 0x42},576	{0x37b5, 0x31},577	{0x37b6, 0x00},578	{0x37b7, 0x00},579	{0x37b8, 0x00},580	{0x37b9, 0xff},581	{0x3800, 0x00}, /* x start H */582	{0x3801, 0x0c}, /* x start L */583	{0x3802, 0x00}, /* y start H */584	{0x3803, 0x0c}, /* y start L */585	{0x3804, 0x0c}, /* x end H */586	{0x3805, 0xd3}, /* x end L */587	{0x3806, 0x09}, /* y end H */588	{0x3807, 0xa3}, /* y end L */589	{0x3808, 0x06}, /* x output size H */590	{0x3809, 0x60}, /* x output size L */591	{0x380a, 0x04}, /* y output size H */592	{0x380b, 0xc8}, /* y output size L */593	{0x380c, 0x07}, /* HTS H */594	{0x380d, 0x88}, /* HTS L */595	{0x380e, 0x04}, /* VTS H */596	{0x380f, 0xdc}, /* VTS L */597	{0x3810, 0x00}, /* ISP x win H */598	{0x3811, 0x04}, /* ISP x win L */599	{0x3813, 0x02}, /* ISP y win L */600	{0x3814, 0x03}, /* x odd inc */601	{0x3815, 0x01}, /* x even inc */602	{0x3820, 0x00}, /* vflip off */603	{0x3821, 0x67}, /* mirror on, bin on */604	{0x382a, 0x03}, /* y odd inc */605	{0x382b, 0x01}, /* y even inc */606	{0x3830, 0x08},607	{0x3836, 0x02},608	{0x3837, 0x18},609	{0x3841, 0xff}, /* window auto size enable */610	{0x3846, 0x48},611	{0x3d85, 0x16}, /* OTP power up load data enable with BIST */612	{0x3d8c, 0x73}, /* OTP setting start High */613	{0x3d8d, 0xde}, /* OTP setting start Low */614	{0x3f08, 0x08},615	{0x3f0a, 0x00},616	{0x4000, 0xf1}, /* out_range_trig, format_chg_trig */617	{0x4001, 0x10}, /* total 128 black column */618	{0x4005, 0x10}, /* BLC target L */619	{0x4002, 0x27}, /* value used to limit BLC offset */620	{0x4009, 0x81}, /* final BLC offset limitation enable */621	{0x400b, 0x0c}, /* DCBLC on, DCBLC manual mode on */622	{0x401b, 0x00}, /* zero line R coefficient */623	{0x401d, 0x00}, /* zoro line T coefficient */624	{0x4020, 0x00}, /* Anchor left start H */625	{0x4021, 0x04}, /* Anchor left start L */626	{0x4022, 0x06}, /* Anchor left end H */627	{0x4023, 0x00}, /* Anchor left end L */628	{0x4024, 0x0f}, /* Anchor right start H */629	{0x4025, 0x2a}, /* Anchor right start L */630	{0x4026, 0x0f}, /* Anchor right end H */631	{0x4027, 0x2b}, /* Anchor right end L */632	{0x4028, 0x00}, /* top zero line start */633	{0x4029, 0x02}, /* top zero line number */634	{0x402a, 0x04}, /* top black line start */635	{0x402b, 0x04}, /* top black line number */636	{0x402c, 0x00}, /* bottom zero line start */637	{0x402d, 0x02}, /* bottom zoro line number */638	{0x402e, 0x04}, /* bottom black line start */639	{0x402f, 0x04}, /* bottom black line number */640	{0x401f, 0x00}, /* interpolation x/y disable, Anchor one disable */641	{0x4034, 0x3f},642	{0x403d, 0x04}, /* md_precision_en */643	{0x4300, 0xff}, /* clip max H */644	{0x4301, 0x00}, /* clip min H */645	{0x4302, 0x0f}, /* clip min L, clip max L */646	{0x4316, 0x00},647	{0x4500, 0x58},648	{0x4503, 0x18},649	{0x4600, 0x00},650	{0x4601, 0xcb},651	{0x481f, 0x32}, /* clk prepare min */652	{0x4837, 0x16}, /* global timing */653	{0x4850, 0x10}, /* lane 1 = 1, lane 0 = 0 */654	{0x4851, 0x32}, /* lane 3 = 3, lane 2 = 2 */655	{0x4b00, 0x2a},656	{0x4b0d, 0x00},657	{0x4d00, 0x04}, /* temperature sensor */658	{0x4d01, 0x18},659	{0x4d02, 0xc3},660	{0x4d03, 0xff},661	{0x4d04, 0xff},662	{0x4d05, 0xff}, /* temperature sensor */663	{0x5000, 0xfe}, /* lenc on, slave/master AWB gain/statistics enable */664	{0x5001, 0x01}, /* BLC on */665	{0x5002, 0x08}, /* H scale off, WBMATCH off, OTP_DPC */666	{0x5003, 0x20}, /* DPC_DBC buffer control enable, WB */667	{0x501e, 0x93}, /* enable digital gain */668	{0x5046, 0x12},669	{0x5780, 0x3e}, /* DPC */670	{0x5781, 0x0f},671	{0x5782, 0x44},672	{0x5783, 0x02},673	{0x5784, 0x01},674	{0x5785, 0x00},675	{0x5786, 0x00},676	{0x5787, 0x04},677	{0x5788, 0x02},678	{0x5789, 0x0f},679	{0x578a, 0xfd},680	{0x578b, 0xf5},681	{0x578c, 0xf5},682	{0x578d, 0x03},683	{0x578e, 0x08},684	{0x578f, 0x0c},685	{0x5790, 0x08},686	{0x5791, 0x04},687	{0x5792, 0x00},688	{0x5793, 0x52},689	{0x5794, 0xa3}, /* DPC */690	{0x5871, 0x0d}, /* Lenc */691	{0x5870, 0x18},692	{0x586e, 0x10},693	{0x586f, 0x08},694	{0x58f7, 0x01},695	{0x58f8, 0x3d}, /* Lenc */696	{0x5901, 0x00}, /* H skip off, V skip off */697	{0x5b00, 0x02}, /* OTP DPC start address */698	{0x5b01, 0x10}, /* OTP DPC start address */699	{0x5b02, 0x03}, /* OTP DPC end address */700	{0x5b03, 0xcf}, /* OTP DPC end address */701	{0x5b05, 0x6c}, /* recover method = 2b11, */702	{0x5e00, 0x00}, /* use 0x3ff to test pattern off */703	{0x5e01, 0x41}, /* window cut enable */704	{0x382d, 0x7f},705	{0x4825, 0x3a}, /* lpx_p_min */706	{0x4826, 0x40}, /* hs_prepare_min */707	{0x4808, 0x25}, /* wake up delay in 1/1024 s */708	{0x3763, 0x18},709	{0x3768, 0xcc},710	{0x470b, 0x28},711	{0x4202, 0x00},712	{0x400d, 0x10}, /* BLC offset trigger L */713	{0x4040, 0x04}, /* BLC gain th2 */714	{0x403e, 0x04}, /* BLC gain th1 */715	{0x4041, 0xc6}, /* BLC */716	{0x3007, 0x80},717	{0x400a, 0x01},718	{REG_NULL, 0x00},719};720 721/*722 * Xclk 24Mhz723 * max_framerate 30fps724 * mipi_datarate per lane 720Mbps725 */726static const struct regval ov8858_1632x1224_regs_2lane[] = {727	/*728	 * MIPI=720Mbps, SysClk=144Mhz,Dac Clock=360Mhz.729	 * v00_01_00 (05/29/2014) : initial setting730	 * AM19 : 3617 <- 0xC0731	 * AM20 : change FWC_6K_EN to be default 0x3618=0x5a732	 */733	{0x0100, 0x00},734	{0x3501, 0x4d}, /* exposure M */735	{0x3502, 0x40}, /* exposure L */736	{0x3778, 0x17},737	{0x3808, 0x06}, /* x output size H */738	{0x3809, 0x60}, /* x output size L */739	{0x380a, 0x04}, /* y output size H */740	{0x380b, 0xc8}, /* y output size L */741	{0x380c, 0x07}, /* HTS H */742	{0x380d, 0x88}, /* HTS L */743	{0x380e, 0x04}, /* VTS H */744	{0x380f, 0xdc}, /* VTS L */745	{0x3814, 0x03}, /* x odd inc */746	{0x3821, 0x67}, /* mirror on, bin on */747	{0x382a, 0x03}, /* y odd inc */748	{0x3830, 0x08},749	{0x3836, 0x02},750	{0x3f0a, 0x00},751	{0x4001, 0x10}, /* total 128 black column */752	{0x4022, 0x06}, /* Anchor left end H */753	{0x4023, 0x00}, /* Anchor left end L */754	{0x4025, 0x2a}, /* Anchor right start L */755	{0x4027, 0x2b}, /* Anchor right end L */756	{0x402b, 0x04}, /* top black line number */757	{0x402f, 0x04}, /* bottom black line number */758	{0x4500, 0x58},759	{0x4600, 0x00},760	{0x4601, 0xcb},761	{0x382d, 0x7f},762	{0x0100, 0x01},763	{REG_NULL, 0x00},764};765 766/*767 * Xclk 24Mhz768 * max_framerate 15fps769 * mipi_datarate per lane 720Mbps770 */771static const struct regval ov8858_3264x2448_regs_2lane[] = {772	{0x0100, 0x00},773	{0x3501, 0x9a}, /* exposure M */774	{0x3502, 0x20}, /* exposure L */775	{0x3778, 0x1a},776	{0x3808, 0x0c}, /* x output size H */777	{0x3809, 0xc0}, /* x output size L */778	{0x380a, 0x09}, /* y output size H */779	{0x380b, 0x90}, /* y output size L */780	{0x380c, 0x07}, /* HTS H */781	{0x380d, 0x94}, /* HTS L */782	{0x380e, 0x09}, /* VTS H */783	{0x380f, 0xaa}, /* VTS L */784	{0x3814, 0x01}, /* x odd inc */785	{0x3821, 0x46}, /* mirror on, bin off */786	{0x382a, 0x01}, /* y odd inc */787	{0x3830, 0x06},788	{0x3836, 0x01},789	{0x3f0a, 0x00},790	{0x4001, 0x00}, /* total 256 black column */791	{0x4022, 0x0c}, /* Anchor left end H */792	{0x4023, 0x60}, /* Anchor left end L */793	{0x4025, 0x36}, /* Anchor right start L */794	{0x4027, 0x37}, /* Anchor right end L */795	{0x402b, 0x08}, /* top black line number */796	{0x402f, 0x08}, /* bottom black line number */797	{0x4500, 0x58},798	{0x4600, 0x01},799	{0x4601, 0x97},800	{0x382d, 0xff},801	{REG_NULL, 0x00},802};803 804static const struct regval ov8858_global_regs_r2a_4lane[] = {805	/*806	 * MIPI=720Mbps, SysClk=144Mhz,Dac Clock=360Mhz.807	 * v00_01_00 (05/29/2014) : initial setting808	 * AM19 : 3617 <- 0xC0809	 * AM20 : change FWC_6K_EN to be default 0x3618=0x5a810	 */811	{0x0103, 0x01}, /* software reset for OVTATool only */812	{0x0103, 0x01}, /* software reset */813	{0x0100, 0x00}, /* software standby */814	{0x0302, 0x1e}, /* pll1_multi */815	{0x0303, 0x00}, /* pll1_divm */816	{0x0304, 0x03}, /* pll1_div_mipi */817	{0x030e, 0x00}, /* pll2_rdiv */818	{0x030f, 0x04}, /* pll2_divsp */819	{0x0312, 0x01}, /* pll2_pre_div0, pll2_r_divdac */820	{0x031e, 0x0c}, /* pll1_no_lat */821	{0x3600, 0x00},822	{0x3601, 0x00},823	{0x3602, 0x00},824	{0x3603, 0x00},825	{0x3604, 0x22},826	{0x3605, 0x20},827	{0x3606, 0x00},828	{0x3607, 0x20},829	{0x3608, 0x11},830	{0x3609, 0x28},831	{0x360a, 0x00},832	{0x360b, 0x05},833	{0x360c, 0xd4},834	{0x360d, 0x40},835	{0x360e, 0x0c},836	{0x360f, 0x20},837	{0x3610, 0x07},838	{0x3611, 0x20},839	{0x3612, 0x88},840	{0x3613, 0x80},841	{0x3614, 0x58},842	{0x3615, 0x00},843	{0x3616, 0x4a},844	{0x3617, 0x90},845	{0x3618, 0x5a},846	{0x3619, 0x70},847	{0x361a, 0x99},848	{0x361b, 0x0a},849	{0x361c, 0x07},850	{0x361d, 0x00},851	{0x361e, 0x00},852	{0x361f, 0x00},853	{0x3638, 0xff},854	{0x3633, 0x0f},855	{0x3634, 0x0f},856	{0x3635, 0x0f},857	{0x3636, 0x12},858	{0x3645, 0x13},859	{0x3646, 0x83},860	{0x364a, 0x07},861	{0x3015, 0x01},862	{0x3018, 0x72}, /* MIPI 4 lane */863	{0x3020, 0x93}, /* Clock switch output normal, pclk_div =/1 */864	{0x3022, 0x01}, /* pd_mipi enable when rst_sync */865	{0x3031, 0x0a}, /* MIPI 10-bit mode */866	{0x3034, 0x00},867	{0x3106, 0x01}, /* sclk_div, sclk_pre_div */868	{0x3305, 0xf1},869	{0x3308, 0x00},870	{0x3309, 0x28},871	{0x330a, 0x00},872	{0x330b, 0x20},873	{0x330c, 0x00},874	{0x330d, 0x00},875	{0x330e, 0x00},876	{0x330f, 0x40},877	{0x3307, 0x04},878	{0x3500, 0x00}, /* exposure H */879	{0x3501, 0x4d}, /* exposure M */880	{0x3502, 0x40}, /* exposure L */881	{0x3503, 0x80}, /* gain delay ?, exposure delay 1 frame, real gain */882	{0x3505, 0x80}, /* gain option */883	{0x3508, 0x02}, /* gain H */884	{0x3509, 0x00}, /* gain L */885	{0x350c, 0x00}, /* short gain H */886	{0x350d, 0x80}, /* short gain L */887	{0x3510, 0x00}, /* short exposure H */888	{0x3511, 0x02}, /* short exposure M */889	{0x3512, 0x00}, /* short exposure L */890	{0x3700, 0x30},891	{0x3701, 0x18},892	{0x3702, 0x50},893	{0x3703, 0x32},894	{0x3704, 0x28},895	{0x3705, 0x00},896	{0x3706, 0x82},897	{0x3707, 0x08},898	{0x3708, 0x48},899	{0x3709, 0x66},900	{0x370a, 0x01},901	{0x370b, 0x82},902	{0x370c, 0x07},903	{0x3718, 0x14},904	{0x3719, 0x31},905	{0x3712, 0x44},906	{0x3714, 0x24},907	{0x371e, 0x31},908	{0x371f, 0x7f},909	{0x3720, 0x0a},910	{0x3721, 0x0a},911	{0x3724, 0x0c},912	{0x3725, 0x02},913	{0x3726, 0x0c},914	{0x3728, 0x0a},915	{0x3729, 0x03},916	{0x372a, 0x06},917	{0x372b, 0xa6},918	{0x372c, 0xa6},919	{0x372d, 0xa6},920	{0x372e, 0x0c},921	{0x372f, 0x20},922	{0x3730, 0x02},923	{0x3731, 0x0c},924	{0x3732, 0x28},925	{0x3733, 0x10},926	{0x3734, 0x40},927	{0x3736, 0x30},928	{0x373a, 0x0a},929	{0x373b, 0x0b},930	{0x373c, 0x14},931	{0x373e, 0x06},932	{0x3750, 0x0a},933	{0x3751, 0x0e},934	{0x3755, 0x10},935	{0x3758, 0x00},936	{0x3759, 0x4c},937	{0x375a, 0x0c},938	{0x375b, 0x26},939	{0x375c, 0x20},940	{0x375d, 0x04},941	{0x375e, 0x00},942	{0x375f, 0x28},943	{0x3768, 0x22},944	{0x3769, 0x44},945	{0x376a, 0x44},946	{0x3761, 0x00},947	{0x3762, 0x00},948	{0x3763, 0x00},949	{0x3766, 0xff},950	{0x376b, 0x00},951	{0x3772, 0x46},952	{0x3773, 0x04},953	{0x3774, 0x2c},954	{0x3775, 0x13},955	{0x3776, 0x08},956	{0x3777, 0x00},957	{0x3778, 0x17},958	{0x37a0, 0x88},959	{0x37a1, 0x7a},960	{0x37a2, 0x7a},961	{0x37a3, 0x00},962	{0x37a4, 0x00},963	{0x37a5, 0x00},964	{0x37a6, 0x00},965	{0x37a7, 0x88},966	{0x37a8, 0x98},967	{0x37a9, 0x98},968	{0x3760, 0x00},969	{0x376f, 0x01},970	{0x37aa, 0x88},971	{0x37ab, 0x5c},972	{0x37ac, 0x5c},973	{0x37ad, 0x55},974	{0x37ae, 0x19},975	{0x37af, 0x19},976	{0x37b0, 0x00},977	{0x37b1, 0x00},978	{0x37b2, 0x00},979	{0x37b3, 0x84},980	{0x37b4, 0x84},981	{0x37b5, 0x60},982	{0x37b6, 0x00},983	{0x37b7, 0x00},984	{0x37b8, 0x00},985	{0x37b9, 0xff},986	{0x3800, 0x00}, /* x start H */987	{0x3801, 0x0c}, /* x start L */988	{0x3802, 0x00}, /* y start H */989	{0x3803, 0x0c}, /* y start L */990	{0x3804, 0x0c}, /* x end H */991	{0x3805, 0xd3}, /* x end L */992	{0x3806, 0x09}, /* y end H */993	{0x3807, 0xa3}, /* y end L */994	{0x3808, 0x06}, /* x output size H */995	{0x3809, 0x60}, /* x output size L */996	{0x380a, 0x04}, /* y output size H */997	{0x380b, 0xc8}, /* y output size L */998	{0x380c, 0x07}, /* HTS H */999	{0x380d, 0x88}, /* HTS L */1000	{0x380e, 0x04}, /* VTS H */1001	{0x380f, 0xdc}, /* VTS L */1002	{0x3810, 0x00}, /* ISP x win H */1003	{0x3811, 0x04}, /* ISP x win L */1004	{0x3813, 0x02}, /* ISP y win L */1005	{0x3814, 0x03}, /* x odd inc */1006	{0x3815, 0x01}, /* x even inc */1007	{0x3820, 0x00}, /* vflip off */1008	{0x3821, 0x67}, /* mirror on, bin o */1009	{0x382a, 0x03}, /* y odd inc */1010	{0x382b, 0x01}, /* y even inc */1011	{0x3830, 0x08},1012	{0x3836, 0x02},1013	{0x3837, 0x18},1014	{0x3841, 0xff}, /* window auto size enable */1015	{0x3846, 0x48},1016	{0x3d85, 0x16}, /* OTP power up load data/setting enable */1017	{0x3d8c, 0x73}, /* OTP setting start High */1018	{0x3d8d, 0xde}, /* OTP setting start Low */1019	{0x3f08, 0x10},1020	{0x3f0a, 0x00},1021	{0x4000, 0xf1}, /* out_range/format_chg/gain/exp_chg trig enable */1022	{0x4001, 0x10}, /* total 128 black column */1023	{0x4005, 0x10}, /* BLC target L */1024	{0x4002, 0x27}, /* value used to limit BLC offset */1025	{0x4009, 0x81}, /* final BLC offset limitation enable */1026	{0x400b, 0x0c}, /* DCBLC on, DCBLC manual mode on */1027	{0x401b, 0x00}, /* zero line R coefficient */1028	{0x401d, 0x00}, /* zoro line T coefficient */1029	{0x4020, 0x00}, /* Anchor left start H */1030	{0x4021, 0x04}, /* Anchor left start L */1031	{0x4022, 0x06}, /* Anchor left end H */1032	{0x4023, 0x00}, /* Anchor left end L */1033	{0x4024, 0x0f}, /* Anchor right start H */1034	{0x4025, 0x2a}, /* Anchor right start L */1035	{0x4026, 0x0f}, /* Anchor right end H */1036	{0x4027, 0x2b}, /* Anchor right end L */1037	{0x4028, 0x00}, /* top zero line start */1038	{0x4029, 0x02}, /* top zero line number */1039	{0x402a, 0x04}, /* top black line start */1040	{0x402b, 0x04}, /* top black line number */1041	{0x402c, 0x00}, /* bottom zero line start */1042	{0x402d, 0x02}, /* bottom zoro line number */1043	{0x402e, 0x04}, /* bottom black line start */1044	{0x402f, 0x04}, /* bottom black line number */1045	{0x401f, 0x00}, /* interpolation x/y disable, Anchor one disable */1046	{0x4034, 0x3f},1047	{0x403d, 0x04}, /* md_precision_en */1048	{0x4300, 0xff}, /* clip max H */1049	{0x4301, 0x00}, /* clip min H */1050	{0x4302, 0x0f}, /* clip min L, clip max L */1051	{0x4316, 0x00},1052	{0x4500, 0x58},1053	{0x4503, 0x18},1054	{0x4600, 0x00},1055	{0x4601, 0xcb},1056	{0x481f, 0x32}, /* clk prepare min */1057	{0x4837, 0x16}, /* global timing */1058	{0x4850, 0x10}, /* lane 1 = 1, lane 0 = 0 */1059	{0x4851, 0x32}, /* lane 3 = 3, lane 2 = 2 */1060	{0x4b00, 0x2a},1061	{0x4b0d, 0x00},1062	{0x4d00, 0x04}, /* temperature sensor */1063	{0x4d01, 0x18},1064	{0x4d02, 0xc3},1065	{0x4d03, 0xff},1066	{0x4d04, 0xff},1067	{0x4d05, 0xff}, /* temperature sensor */1068	{0x5000, 0xfe}, /* lenc on, slave/master AWB gain/statistics enable */1069	{0x5001, 0x01}, /* BLC on */1070	{0x5002, 0x08}, /* WBMATCH sensor's gain, H scale/WBMATCH/OTP_DPC off */1071	{0x5003, 0x20}, /* DPC_DBC buffer control enable, WB */1072	{0x501e, 0x93}, /* enable digital gain */1073	{0x5046, 0x12},1074	{0x5780, 0x3e}, /* DPC */1075	{0x5781, 0x0f},1076	{0x5782, 0x44},1077	{0x5783, 0x02},1078	{0x5784, 0x01},1079	{0x5785, 0x00},1080	{0x5786, 0x00},1081	{0x5787, 0x04},1082	{0x5788, 0x02},1083	{0x5789, 0x0f},1084	{0x578a, 0xfd},1085	{0x578b, 0xf5},1086	{0x578c, 0xf5},1087	{0x578d, 0x03},1088	{0x578e, 0x08},1089	{0x578f, 0x0c},1090	{0x5790, 0x08},1091	{0x5791, 0x04},1092	{0x5792, 0x00},1093	{0x5793, 0x52},1094	{0x5794, 0xa3}, /* DPC */1095	{0x5871, 0x0d}, /* Lenc */1096	{0x5870, 0x18},1097	{0x586e, 0x10},1098	{0x586f, 0x08},1099	{0x58f7, 0x01},1100	{0x58f8, 0x3d}, /* Lenc */1101	{0x5901, 0x00}, /* H skip off, V skip off */1102	{0x5b00, 0x02}, /* OTP DPC start address */1103	{0x5b01, 0x10}, /* OTP DPC start address */1104	{0x5b02, 0x03}, /* OTP DPC end address */1105	{0x5b03, 0xcf}, /* OTP DPC end address */1106	{0x5b05, 0x6c}, /* recover method = 2b11 */1107	{0x5e00, 0x00}, /* use 0x3ff to test pattern off */1108	{0x5e01, 0x41}, /* window cut enable */1109	{0x382d, 0x7f},1110	{0x4825, 0x3a}, /* lpx_p_min */1111	{0x4826, 0x40}, /* hs_prepare_min */1112	{0x4808, 0x25}, /* wake up delay in 1/1024 s */1113	{0x3763, 0x18},1114	{0x3768, 0xcc},1115	{0x470b, 0x28},1116	{0x4202, 0x00},1117	{0x400d, 0x10}, /* BLC offset trigger L */1118	{0x4040, 0x04}, /* BLC gain th2 */1119	{0x403e, 0x04}, /* BLC gain th1 */1120	{0x4041, 0xc6}, /* BLC */1121	{0x3007, 0x80},1122	{0x400a, 0x01},1123	{REG_NULL, 0x00},1124};1125 1126/*1127 * Xclk 24Mhz1128 * max_framerate 60fps1129 * mipi_datarate per lane 720Mbps1130 */1131static const struct regval ov8858_1632x1224_regs_4lane[] = {1132	{0x0100, 0x00},1133	{0x3501, 0x4d}, /* exposure M */1134	{0x3502, 0x40}, /* exposure L */1135	{0x3808, 0x06}, /* x output size H */1136	{0x3809, 0x60}, /* x output size L */1137	{0x380a, 0x04}, /* y output size H */1138	{0x380b, 0xc8}, /* y output size L */1139	{0x380c, 0x07}, /* HTS H */1140	{0x380d, 0x88}, /* HTS L */1141	{0x380e, 0x04}, /* VTS H */1142	{0x380f, 0xdc}, /* VTS L */1143	{0x3814, 0x03}, /* x odd inc */1144	{0x3821, 0x67}, /* mirror on, bin on */1145	{0x382a, 0x03}, /* y odd inc */1146	{0x3830, 0x08},1147	{0x3836, 0x02},1148	{0x3f0a, 0x00},1149	{0x4001, 0x10}, /* total 128 black column */1150	{0x4022, 0x06}, /* Anchor left end H */1151	{0x4023, 0x00}, /* Anchor left end L */1152	{0x4025, 0x2a}, /* Anchor right start L */1153	{0x4027, 0x2b}, /* Anchor right end L */1154	{0x402b, 0x04}, /* top black line number */1155	{0x402f, 0x04}, /* bottom black line number */1156	{0x4500, 0x58},1157	{0x4600, 0x00},1158	{0x4601, 0xcb},1159	{0x382d, 0x7f},1160	{0x0100, 0x01},1161	{REG_NULL, 0x00},1162};1163 1164/*1165 * Xclk 24Mhz1166 * max_framerate 30fps1167 * mipi_datarate per lane 720Mbps1168 */1169static const struct regval ov8858_3264x2448_regs_4lane[] = {1170	{0x0100, 0x00},1171	{0x3501, 0x9a}, /* exposure M */1172	{0x3502, 0x20}, /* exposure L */1173	{0x3808, 0x0c}, /* x output size H */1174	{0x3809, 0xc0}, /* x output size L */1175	{0x380a, 0x09}, /* y output size H */1176	{0x380b, 0x90}, /* y output size L */1177	{0x380c, 0x07}, /* HTS H */1178	{0x380d, 0x94}, /* HTS L */1179	{0x380e, 0x09}, /* VTS H */1180	{0x380f, 0xaa}, /* VTS L */1181	{0x3814, 0x01}, /* x odd inc */1182	{0x3821, 0x46}, /* mirror on, bin off */1183	{0x382a, 0x01}, /* y odd inc */1184	{0x3830, 0x06},1185	{0x3836, 0x01},1186	{0x3f0a, 0x00},1187	{0x4001, 0x00}, /* total 256 black column */1188	{0x4022, 0x0c}, /* Anchor left end H */1189	{0x4023, 0x60}, /* Anchor left end L */1190	{0x4025, 0x36}, /* Anchor right start L */1191	{0x4027, 0x37}, /* Anchor right end L */1192	{0x402b, 0x08}, /* top black line number */1193	{0x402f, 0x08}, /* interpolation x/y disable, Anchor one disable */1194	{0x4500, 0x58},1195	{0x4600, 0x01},1196	{0x4601, 0x97},1197	{0x382d, 0xff},1198	{REG_NULL, 0x00},1199};1200 1201static const struct ov8858_mode ov8858_modes[] = {1202	{1203		.width = 3264,1204		.height = 2448,1205		.exp_def = 2464,1206		.hts_def = 1940 * 2,1207		.vts_def = 2472,1208		.reg_modes = {1209			.mode_2lanes = ov8858_3264x2448_regs_2lane,1210			.mode_4lanes = ov8858_3264x2448_regs_4lane,1211		},1212	},1213	{1214		.width = 1632,1215		.height = 1224,1216		.exp_def = 1232,1217		.hts_def = 1928 * 2,1218		.vts_def = 1244,1219		.reg_modes = {1220			.mode_2lanes = ov8858_1632x1224_regs_2lane,1221			.mode_4lanes = ov8858_1632x1224_regs_4lane,1222		},1223	},1224};1225 1226static const s64 link_freq_menu_items[] = {1227	OV8858_LINK_FREQ1228};1229 1230static const char * const ov8858_test_pattern_menu[] = {1231	"Disabled",1232	"Vertical Color Bar Type 1",1233	"Vertical Color Bar Type 2",1234	"Vertical Color Bar Type 3",1235	"Vertical Color Bar Type 4"1236};1237 1238/* ----------------------------------------------------------------------------1239 * HW access1240 */1241 1242static int ov8858_write(struct ov8858 *ov8858, u32 reg, u32 val, int *err)1243{1244	struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);1245	unsigned int len = (reg >> OV8858_REG_SIZE_SHIFT) & 3;1246	u16 addr = reg & OV8858_REG_ADDR_MASK;1247	u8 buf[6];1248	int ret;1249 1250	if (err && *err)1251		return *err;1252 1253	put_unaligned_be16(addr, buf);1254	put_unaligned_be32(val << (8 * (4 - len)), buf + 2);1255 1256	ret = i2c_master_send(client, buf, len + 2);1257	if (ret != len + 2) {1258		ret = ret < 0 ? ret : -EIO;1259		if (err)1260			*err = ret;1261 1262		dev_err(&client->dev,1263			"Failed to write reg %u: %d\n", addr, ret);1264		return ret;1265	}1266 1267	return 0;1268}1269 1270static int ov8858_write_array(struct ov8858 *ov8858, const struct regval *regs)1271{1272	unsigned int i;1273	int ret = 0;1274 1275	for (i = 0; ret == 0 && regs[i].addr != REG_NULL; ++i) {1276		ov8858_write(ov8858, OV8858_REG_8BIT(regs[i].addr),1277			     regs[i].val, &ret);1278	}1279 1280	return ret;1281}1282 1283static int ov8858_read(struct ov8858 *ov8858, u32 reg, u32 *val)1284{1285	struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);1286	__be16 reg_addr_be = cpu_to_be16(reg & OV8858_REG_ADDR_MASK);1287	unsigned int len = (reg >> OV8858_REG_SIZE_SHIFT) & 3;1288	struct i2c_msg msgs[2];1289	__be32 data_be = 0;1290	u8 *data_be_p;1291	int ret;1292 1293	data_be_p = (u8 *)&data_be;1294 1295	/* Write register address */1296	msgs[0].addr = client->addr;1297	msgs[0].flags = 0;1298	msgs[0].len = 2;1299	msgs[0].buf = (u8 *)&reg_addr_be;1300 1301	/* Read data from register */1302	msgs[1].addr = client->addr;1303	msgs[1].flags = I2C_M_RD;1304	msgs[1].len = len;1305	msgs[1].buf = &data_be_p[4 - len];1306 1307	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));1308	if (ret != ARRAY_SIZE(msgs)) {1309		ret = ret < 0 ? ret : -EIO;1310		dev_err(&client->dev,1311			"Failed to read reg %u: %d\n", reg, ret);1312		return ret;1313	}1314 1315	*val = be32_to_cpu(data_be);1316 1317	return 0;1318}1319 1320/* ----------------------------------------------------------------------------1321 * Streaming1322 */1323 1324static int ov8858_start_stream(struct ov8858 *ov8858,1325			       struct v4l2_subdev_state *state)1326{1327	struct v4l2_mbus_framefmt *format;1328	const struct ov8858_mode *mode;1329	const struct regval *reg_list;1330	int ret;1331 1332	ret = ov8858_write_array(ov8858, ov8858->global_regs);1333	if (ret)1334		return ret;1335 1336	format = v4l2_subdev_state_get_format(state, 0);1337	mode = v4l2_find_nearest_size(ov8858_modes, ARRAY_SIZE(ov8858_modes),1338				      width, height, format->width,1339				      format->height);1340 1341	reg_list = ov8858->num_lanes == 41342		 ? mode->reg_modes.mode_4lanes1343		 : mode->reg_modes.mode_2lanes;1344 1345	ret = ov8858_write_array(ov8858, reg_list);1346	if (ret)1347		return ret;1348 1349	/* 200 usec max to let PLL stabilize. */1350	fsleep(200);1351 1352	ret = __v4l2_ctrl_handler_setup(&ov8858->ctrl_handler);1353	if (ret)1354		return ret;1355 1356	ret = ov8858_write(ov8858, OV8858_REG_SC_CTRL0100,1357			   OV8858_MODE_STREAMING, NULL);1358	if (ret)1359		return ret;1360 1361	/* t5 (fixed) = 10msec before entering streaming state */1362	fsleep(10000);1363 1364	return 0;1365}1366 1367static int ov8858_stop_stream(struct ov8858 *ov8858)1368{1369	return ov8858_write(ov8858, OV8858_REG_SC_CTRL0100,1370			    OV8858_MODE_SW_STANDBY, NULL);1371}1372 1373static int ov8858_s_stream(struct v4l2_subdev *sd, int on)1374{1375	struct i2c_client *client = v4l2_get_subdevdata(sd);1376	struct ov8858 *ov8858 = sd_to_ov8858(sd);1377	struct v4l2_subdev_state *state;1378	int ret = 0;1379 1380	state = v4l2_subdev_lock_and_get_active_state(sd);1381 1382	if (on) {1383		ret = pm_runtime_resume_and_get(&client->dev);1384		if (ret < 0)1385			goto unlock_and_return;1386 1387		ret = ov8858_start_stream(ov8858, state);1388		if (ret) {1389			dev_err(&client->dev, "Failed to start streaming\n");1390			pm_runtime_put_sync(&client->dev);1391			goto unlock_and_return;1392		}1393	} else {1394		ov8858_stop_stream(ov8858);1395		pm_runtime_mark_last_busy(&client->dev);1396		pm_runtime_put_autosuspend(&client->dev);1397	}1398 1399unlock_and_return:1400	v4l2_subdev_unlock_state(state);1401 1402	return ret;1403}1404 1405static const struct v4l2_subdev_video_ops ov8858_video_ops = {1406	.s_stream = ov8858_s_stream,1407};1408 1409/* ----------------------------------------------------------------------------1410 * Pad ops1411 */1412 1413static int ov8858_set_fmt(struct v4l2_subdev *sd,1414			  struct v4l2_subdev_state *state,1415			  struct v4l2_subdev_format *fmt)1416{1417	struct ov8858 *ov8858 = sd_to_ov8858(sd);1418	const struct ov8858_mode *mode;1419	s64 h_blank, vblank_def;1420 1421	mode = v4l2_find_nearest_size(ov8858_modes, ARRAY_SIZE(ov8858_modes),1422				      width, height, fmt->format.width,1423				      fmt->format.height);1424 1425	fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;1426	fmt->format.width = mode->width;1427	fmt->format.height = mode->height;1428	fmt->format.field = V4L2_FIELD_NONE;1429 1430	/* Store the format in the current subdev state. */1431	*v4l2_subdev_state_get_format(state, 0) =  fmt->format;1432 1433	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)1434		return 0;1435 1436	/* Adjust control limits when a new mode is applied. */1437	h_blank = mode->hts_def - mode->width;1438	__v4l2_ctrl_modify_range(ov8858->hblank, h_blank, h_blank, 1,1439				 h_blank);1440 1441	vblank_def = mode->vts_def - mode->height;1442	__v4l2_ctrl_modify_range(ov8858->vblank, vblank_def,1443				 OV8858_VTS_MAX - mode->height, 1,1444				 vblank_def);1445 1446	return 0;1447}1448 1449static int ov8858_enum_frame_sizes(struct v4l2_subdev *sd,1450				   struct v4l2_subdev_state *state,1451				   struct v4l2_subdev_frame_size_enum *fse)1452{1453	if (fse->index >= ARRAY_SIZE(ov8858_modes))1454		return -EINVAL;1455 1456	if (fse->code != MEDIA_BUS_FMT_SBGGR10_1X10)1457		return -EINVAL;1458 1459	fse->min_width  = ov8858_modes[fse->index].width;1460	fse->max_width  = ov8858_modes[fse->index].width;1461	fse->max_height = ov8858_modes[fse->index].height;1462	fse->min_height = ov8858_modes[fse->index].height;1463 1464	return 0;1465}1466 1467static int ov8858_enum_mbus_code(struct v4l2_subdev *sd,1468				 struct v4l2_subdev_state *state,1469				 struct v4l2_subdev_mbus_code_enum *code)1470{1471	if (code->index != 0)1472		return -EINVAL;1473 1474	code->code = MEDIA_BUS_FMT_SBGGR10_1X10;1475 1476	return 0;1477}1478 1479static int ov8858_init_state(struct v4l2_subdev *sd,1480			     struct v4l2_subdev_state *sd_state)1481{1482	const struct ov8858_mode *def_mode = &ov8858_modes[0];1483	struct v4l2_subdev_format fmt = {1484		.which = V4L2_SUBDEV_FORMAT_TRY,1485		.format = {1486			.width = def_mode->width,1487			.height = def_mode->height,1488		},1489	};1490 1491	ov8858_set_fmt(sd, sd_state, &fmt);1492 1493	return 0;1494}1495 1496static const struct v4l2_subdev_pad_ops ov8858_pad_ops = {1497	.enum_mbus_code = ov8858_enum_mbus_code,1498	.enum_frame_size = ov8858_enum_frame_sizes,1499	.get_fmt = v4l2_subdev_get_fmt,1500	.set_fmt = ov8858_set_fmt,1501};1502 1503static const struct v4l2_subdev_core_ops ov8858_core_ops = {1504	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,1505	.unsubscribe_event = v4l2_event_subdev_unsubscribe,1506};1507 1508static const struct v4l2_subdev_ops ov8858_subdev_ops = {1509	.core	= &ov8858_core_ops,1510	.video	= &ov8858_video_ops,1511	.pad	= &ov8858_pad_ops,1512};1513 1514static const struct v4l2_subdev_internal_ops ov8858_internal_ops = {1515	.init_state = ov8858_init_state,1516};1517 1518/* ----------------------------------------------------------------------------1519 * Controls handling1520 */1521 1522static int ov8858_enable_test_pattern(struct ov8858 *ov8858, u32 pattern)1523{1524	u32 val;1525 1526	if (pattern)1527		val = (pattern - 1) | OV8858_TEST_PATTERN_ENABLE;1528	else1529		val = OV8858_TEST_PATTERN_DISABLE;1530 1531	return ov8858_write(ov8858, OV8858_REG_TEST_PATTERN, val, NULL);1532}1533 1534static int ov8858_set_ctrl(struct v4l2_ctrl *ctrl)1535{1536	struct ov8858 *ov8858 = container_of(ctrl->handler,1537					     struct ov8858, ctrl_handler);1538 1539	struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);1540	struct v4l2_mbus_framefmt *format;1541	struct v4l2_subdev_state *state;1542	u16 digi_gain;1543	s64 max_exp;1544	int ret;1545 1546	/*1547	 * The control handler and the subdev state use the same mutex and the1548	 * mutex is guaranteed to be locked:1549	 * - by the core when s_ctrl is called int the VIDIOC_S_CTRL call path1550	 * - by the driver when s_ctrl is called in the s_stream(1) call path1551	 */1552	state = v4l2_subdev_get_locked_active_state(&ov8858->subdev);1553	format = v4l2_subdev_state_get_format(state, 0);1554 1555	/* Propagate change of current control to all related controls */1556	switch (ctrl->id) {1557	case V4L2_CID_VBLANK:1558		/* Update max exposure while meeting expected vblanking */1559		max_exp = format->height + ctrl->val - OV8858_EXPOSURE_MARGIN;1560		__v4l2_ctrl_modify_range(ov8858->exposure,1561					 ov8858->exposure->minimum, max_exp,1562					 ov8858->exposure->step,1563					 ov8858->exposure->default_value);1564		break;1565	}1566 1567	if (!pm_runtime_get_if_in_use(&client->dev))1568		return 0;1569 1570	switch (ctrl->id) {1571	case V4L2_CID_EXPOSURE:1572		/* 4 least significant bits of exposure are fractional part */1573		ret = ov8858_write(ov8858, OV8858_REG_LONG_EXPO,1574				   ctrl->val << 4, NULL);1575		break;1576	case V4L2_CID_ANALOGUE_GAIN:1577		ret = ov8858_write(ov8858, OV8858_REG_LONG_GAIN,1578				   ctrl->val, NULL);1579		break;1580	case V4L2_CID_DIGITAL_GAIN:1581		/*1582		 * Digital gain is assembled as:1583		 * 0x350a[7:0] = dgain[13:6]1584		 * 0x350b[5:0] = dgain[5:0]1585		 * Reassemble the control value to write it in one go.1586		 */1587		digi_gain = (ctrl->val & OV8858_LONG_DIGIGAIN_L_MASK)1588			  | ((ctrl->val & OV8858_LONG_DIGIGAIN_H_MASK) <<1589			      OV8858_LONG_DIGIGAIN_H_SHIFT);1590		ret = ov8858_write(ov8858, OV8858_REG_LONG_DIGIGAIN,1591				   digi_gain, NULL);1592		break;1593	case V4L2_CID_VBLANK:1594		ret = ov8858_write(ov8858, OV8858_REG_VTS,1595				   ctrl->val + format->height, NULL);1596		break;1597	case V4L2_CID_TEST_PATTERN:1598		ret = ov8858_enable_test_pattern(ov8858, ctrl->val);1599		break;1600	default:1601		ret = -EINVAL;1602		dev_warn(&client->dev, "%s Unhandled id: 0x%x\n",1603			 __func__, ctrl->id);1604		break;1605	}1606 1607	pm_runtime_put(&client->dev);1608 1609	return ret;1610}1611 1612static const struct v4l2_ctrl_ops ov8858_ctrl_ops = {1613	.s_ctrl = ov8858_set_ctrl,1614};1615 1616/* ----------------------------------------------------------------------------1617 * Power Management1618 */1619 1620static int ov8858_power_on(struct ov8858 *ov8858)1621{1622	struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);1623	struct device *dev = &client->dev;1624	unsigned long delay_us;1625	int ret;1626 1627	if (clk_get_rate(ov8858->xvclk) != OV8858_XVCLK_FREQ)1628		dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");1629 1630	ret = clk_prepare_enable(ov8858->xvclk);1631	if (ret < 0) {1632		dev_err(dev, "Failed to enable xvclk\n");1633		return ret;1634	}1635 1636	ret = regulator_bulk_enable(ARRAY_SIZE(ov8858_supply_names),1637				    ov8858->supplies);1638	if (ret < 0) {1639		dev_err(dev, "Failed to enable regulators\n");1640		goto disable_clk;1641	}1642 1643	/*1644	 * The chip manual only suggests 8192 cycles prior to first SCCB1645	 * transaction, but a double sleep between the release of gpios1646	 * helps with sporadic failures observed at probe time.1647	 */1648	delay_us = DIV_ROUND_UP(8192, OV8858_XVCLK_FREQ / 1000 / 1000);1649 1650	gpiod_set_value_cansleep(ov8858->reset_gpio, 0);1651	fsleep(delay_us);1652	gpiod_set_value_cansleep(ov8858->pwdn_gpio, 0);1653	fsleep(delay_us);1654 1655	return 0;1656 1657disable_clk:1658	clk_disable_unprepare(ov8858->xvclk);1659 1660	return ret;1661}1662 1663static void ov8858_power_off(struct ov8858 *ov8858)1664{1665	gpiod_set_value_cansleep(ov8858->pwdn_gpio, 1);1666	clk_disable_unprepare(ov8858->xvclk);1667	gpiod_set_value_cansleep(ov8858->reset_gpio, 1);1668 1669	regulator_bulk_disable(ARRAY_SIZE(ov8858_supply_names),1670			       ov8858->supplies);1671}1672 1673static int ov8858_runtime_resume(struct device *dev)1674{1675	struct i2c_client *client = to_i2c_client(dev);1676	struct v4l2_subdev *sd = i2c_get_clientdata(client);1677	struct ov8858 *ov8858 = sd_to_ov8858(sd);1678 1679	return ov8858_power_on(ov8858);1680}1681 1682static int ov8858_runtime_suspend(struct device *dev)1683{1684	struct i2c_client *client = to_i2c_client(dev);1685	struct v4l2_subdev *sd = i2c_get_clientdata(client);1686	struct ov8858 *ov8858 = sd_to_ov8858(sd);1687 1688	ov8858_power_off(ov8858);1689 1690	return 0;1691}1692 1693static const struct dev_pm_ops ov8858_pm_ops = {1694	SET_RUNTIME_PM_OPS(ov8858_runtime_suspend,1695			   ov8858_runtime_resume, NULL)1696};1697 1698/* ----------------------------------------------------------------------------1699 * Probe and initialization1700 */1701 1702static int ov8858_init_ctrls(struct ov8858 *ov8858)1703{1704	struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);1705	struct v4l2_ctrl_handler *handler = &ov8858->ctrl_handler;1706	const struct ov8858_mode *mode = &ov8858_modes[0];1707	struct v4l2_fwnode_device_properties props;1708	s64 exposure_max, vblank_def;1709	unsigned int pixel_rate;1710	struct v4l2_ctrl *ctrl;1711	u32 h_blank;1712	int ret;1713 1714	ret = v4l2_ctrl_handler_init(handler, 10);1715	if (ret)1716		return ret;1717 1718	ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ,1719				      0, 0, link_freq_menu_items);1720	if (ctrl)1721		ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;1722 1723	/* pixel rate = link frequency * 2 * lanes / bpp */1724	pixel_rate = OV8858_LINK_FREQ * 2 * ov8858->num_lanes / 10;1725	v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE,1726			  0, pixel_rate, 1, pixel_rate);1727 1728	h_blank = mode->hts_def - mode->width;1729	ov8858->hblank = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK,1730					   h_blank, h_blank, 1, h_blank);1731	if (ov8858->hblank)1732		ov8858->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;1733 1734	vblank_def = mode->vts_def - mode->height;1735	ov8858->vblank = v4l2_ctrl_new_std(handler, &ov8858_ctrl_ops,1736					   V4L2_CID_VBLANK, vblank_def,1737					   OV8858_VTS_MAX - mode->height,1738					   1, vblank_def);1739 1740	exposure_max = mode->vts_def - OV8858_EXPOSURE_MARGIN;1741	ov8858->exposure = v4l2_ctrl_new_std(handler, &ov8858_ctrl_ops,1742					     V4L2_CID_EXPOSURE,1743					     OV8858_EXPOSURE_MIN,1744					     exposure_max, OV8858_EXPOSURE_STEP,1745					     mode->exp_def);1746 1747	v4l2_ctrl_new_std(handler, &ov8858_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,1748			  OV8858_LONG_GAIN_MIN, OV8858_LONG_GAIN_MAX,1749			  OV8858_LONG_GAIN_STEP, OV8858_LONG_GAIN_DEFAULT);1750 1751	v4l2_ctrl_new_std(handler, &ov8858_ctrl_ops, V4L2_CID_DIGITAL_GAIN,1752			  OV8858_LONG_DIGIGAIN_MIN, OV8858_LONG_DIGIGAIN_MAX,1753			  OV8858_LONG_DIGIGAIN_STEP,1754			  OV8858_LONG_DIGIGAIN_DEFAULT);1755 1756	v4l2_ctrl_new_std_menu_items(handler, &ov8858_ctrl_ops,1757				     V4L2_CID_TEST_PATTERN,1758				     ARRAY_SIZE(ov8858_test_pattern_menu) - 1,1759				     0, 0, ov8858_test_pattern_menu);1760 1761	if (handler->error) {1762		ret = handler->error;1763		goto err_free_handler;1764	}1765 1766	ret = v4l2_fwnode_device_parse(&client->dev, &props);1767	if (ret)1768		goto err_free_handler;1769 1770	ret = v4l2_ctrl_new_fwnode_properties(handler, &ov8858_ctrl_ops,1771					      &props);1772	if (ret)1773		goto err_free_handler;1774 1775	ov8858->subdev.ctrl_handler = handler;1776 1777	return 0;1778 1779err_free_handler:1780	dev_err(&client->dev, "Failed to init controls: %d\n", ret);1781	v4l2_ctrl_handler_free(handler);1782 1783	return ret;1784}1785 1786static int ov8858_check_sensor_id(struct ov8858 *ov8858)1787{1788	struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);1789	u32 id = 0;1790	int ret;1791 1792	ret = ov8858_read(ov8858, OV8858_REG_CHIP_ID, &id);1793	if (ret)1794		return ret;1795 1796	if (id != OV8858_CHIP_ID) {1797		dev_err(&client->dev, "Unexpected sensor id 0x%x\n", id);1798		return -ENODEV;1799	}1800 1801	ret = ov8858_read(ov8858, OV8858_REG_SUB_ID, &id);1802	if (ret)1803		return ret;1804 1805	dev_info(&client->dev, "Detected OV8858 sensor, revision 0x%x\n", id);1806 1807	if (id == OV8858_R2A) {1808		/* R2A supports 2 and 4 lanes modes. */1809		ov8858->global_regs = ov8858->num_lanes == 41810				    ? ov8858_global_regs_r2a_4lane1811				    : ov8858_global_regs_r2a_2lane;1812	} else if (ov8858->num_lanes == 2) {1813		/*1814		 * R1A only supports 2 lanes mode and it's only partially1815		 * supported.1816		 */1817		ov8858->global_regs = ov8858_global_regs_r1a;1818		dev_warn(&client->dev, "R1A may not work well!\n");1819	} else {1820		dev_err(&client->dev,1821			"Unsupported number of data lanes for R1A revision.\n");1822		return -EINVAL;1823	}1824 1825	return 0;1826}1827 1828static int ov8858_configure_regulators(struct ov8858 *ov8858)1829{1830	struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);1831	unsigned int i;1832 1833	for (i = 0; i < ARRAY_SIZE(ov8858_supply_names); i++)1834		ov8858->supplies[i].supply = ov8858_supply_names[i];1835 1836	return devm_regulator_bulk_get(&client->dev,1837				       ARRAY_SIZE(ov8858_supply_names),1838				       ov8858->supplies);1839}1840 1841static int ov8858_parse_of(struct ov8858 *ov8858)1842{1843	struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY };1844	struct i2c_client *client = v4l2_get_subdevdata(&ov8858->subdev);1845	struct device *dev = &client->dev;1846	struct fwnode_handle *endpoint;1847	int ret;1848 1849	endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);1850	if (!endpoint) {1851		dev_err(dev, "Failed to get endpoint\n");1852		return -EINVAL;1853	}1854 1855	ret = v4l2_fwnode_endpoint_parse(endpoint, &vep);1856	fwnode_handle_put(endpoint);1857	if (ret) {1858		dev_err(dev, "Failed to parse endpoint: %d\n", ret);1859		return ret;1860	}1861 1862	ov8858->num_lanes = vep.bus.mipi_csi2.num_data_lanes;1863	switch (ov8858->num_lanes) {1864	case 4:1865	case 2:1866		break;1867	default:1868		dev_err(dev, "Unsupported number of data lanes %u\n",1869			ov8858->num_lanes);1870		return -EINVAL;1871	}1872 1873	return 0;1874}1875 1876static int ov8858_probe(struct i2c_client *client)1877{1878	struct device *dev = &client->dev;1879	struct v4l2_subdev *sd;1880	struct ov8858 *ov8858;1881	int ret;1882 1883	ov8858 = devm_kzalloc(dev, sizeof(*ov8858), GFP_KERNEL);1884	if (!ov8858)1885		return -ENOMEM;1886 1887	ov8858->xvclk = devm_clk_get(dev, "xvclk");1888	if (IS_ERR(ov8858->xvclk))1889		return dev_err_probe(dev, PTR_ERR(ov8858->xvclk),1890				     "Failed to get xvclk\n");1891 1892	ov8858->reset_gpio = devm_gpiod_get_optional(dev, "reset",1893						     GPIOD_OUT_HIGH);1894	if (IS_ERR(ov8858->reset_gpio))1895		return dev_err_probe(dev, PTR_ERR(ov8858->reset_gpio),1896				     "Failed to get reset gpio\n");1897 1898	ov8858->pwdn_gpio = devm_gpiod_get_optional(dev, "powerdown",1899						    GPIOD_OUT_HIGH);1900	if (IS_ERR(ov8858->pwdn_gpio))1901		return dev_err_probe(dev, PTR_ERR(ov8858->pwdn_gpio),1902				     "Failed to get powerdown gpio\n");1903 1904	v4l2_i2c_subdev_init(&ov8858->subdev, client, &ov8858_subdev_ops);1905	ov8858->subdev.internal_ops = &ov8858_internal_ops;1906 1907	ret = ov8858_configure_regulators(ov8858);1908	if (ret)1909		return dev_err_probe(dev, ret, "Failed to get regulators\n");1910 1911	ret = ov8858_parse_of(ov8858);1912	if (ret)1913		return ret;1914 1915	ret = ov8858_init_ctrls(ov8858);1916	if (ret)1917		return ret;1918 1919	sd = &ov8858->subdev;1920	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;1921	ov8858->pad.flags = MEDIA_PAD_FL_SOURCE;1922	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;1923	ret = media_entity_pads_init(&sd->entity, 1, &ov8858->pad);1924	if (ret < 0)1925		goto err_free_handler;1926 1927	sd->state_lock = ov8858->ctrl_handler.lock;1928	ret = v4l2_subdev_init_finalize(sd);1929	if (ret < 0) {1930		dev_err(&client->dev, "Subdev initialization error %d\n", ret);1931		goto err_clean_entity;1932	}1933 1934	ret = ov8858_power_on(ov8858);1935	if (ret)1936		goto err_clean_entity;1937 1938	pm_runtime_set_active(dev);1939	pm_runtime_get_noresume(dev);1940	pm_runtime_enable(dev);1941 1942	ret = ov8858_check_sensor_id(ov8858);1943	if (ret)1944		goto err_power_off;1945 1946	pm_runtime_set_autosuspend_delay(dev, 1000);1947	pm_runtime_use_autosuspend(dev);1948 1949	ret = v4l2_async_register_subdev_sensor(sd);1950	if (ret) {1951		dev_err(dev, "v4l2 async register subdev failed\n");1952		goto err_power_off;1953	}1954 1955	pm_runtime_mark_last_busy(dev);1956	pm_runtime_put_autosuspend(dev);1957 1958	return 0;1959 1960err_power_off:1961	pm_runtime_disable(dev);1962	pm_runtime_put_noidle(dev);1963	ov8858_power_off(ov8858);1964err_clean_entity:1965	media_entity_cleanup(&sd->entity);1966err_free_handler:1967	v4l2_ctrl_handler_free(&ov8858->ctrl_handler);1968 1969	return ret;1970}1971 1972static void ov8858_remove(struct i2c_client *client)1973{1974	struct v4l2_subdev *sd = i2c_get_clientdata(client);1975	struct ov8858 *ov8858 = sd_to_ov8858(sd);1976 1977	v4l2_async_unregister_subdev(sd);1978	media_entity_cleanup(&sd->entity);1979	v4l2_ctrl_handler_free(&ov8858->ctrl_handler);1980 1981	pm_runtime_disable(&client->dev);1982	if (!pm_runtime_status_suspended(&client->dev))1983		ov8858_power_off(ov8858);1984	pm_runtime_set_suspended(&client->dev);1985}1986 1987static const struct of_device_id ov8858_of_match[] = {1988	{ .compatible = "ovti,ov8858" },1989	{ /* sentinel */ },1990};1991MODULE_DEVICE_TABLE(of, ov8858_of_match);1992 1993static struct i2c_driver ov8858_i2c_driver = {1994	.driver = {1995		.name = "ov8858",1996		.pm = &ov8858_pm_ops,1997		.of_match_table = ov8858_of_match,1998	},1999	.probe		= ov8858_probe,2000	.remove		= ov8858_remove,2001};2002 2003module_i2c_driver(ov8858_i2c_driver);2004 2005MODULE_DESCRIPTION("OmniVision OV8858 sensor driver");2006MODULE_LICENSE("GPL");2007