brintos

brintos / linux-shallow public Read only

0
0
Text · 32.5 KiB · 1bacbdf Raw
1479 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2022 Intel Corporation.3 4#include <linux/acpi.h>5#include <linux/clk.h>6#include <linux/delay.h>7#include <linux/i2c.h>8#include <linux/module.h>9#include <linux/pm_runtime.h>10#include <linux/regulator/consumer.h>11#include <media/v4l2-ctrls.h>12#include <media/v4l2-device.h>13#include <media/v4l2-fwnode.h>14 15#define OV08D10_SCLK			144000000ULL16#define OV08D10_XVCLK_19_2		1920000017#define OV08D10_ROWCLK			3600018#define OV08D10_DATA_LANES		219#define OV08D10_RGB_DEPTH		1020 21#define OV08D10_REG_PAGE		0xfd22#define OV08D10_REG_GLOBAL_EFFECTIVE		0x0123#define OV08D10_REG_CHIP_ID_0		0x0024#define OV08D10_REG_CHIP_ID_1		0x0125#define OV08D10_ID_MASK			GENMASK(15, 0)26#define OV08D10_CHIP_ID			0x560827 28#define OV08D10_REG_MODE_SELECT		0xa029#define OV08D10_MODE_STANDBY		0x0030#define OV08D10_MODE_STREAMING		0x0131 32/* vertical-timings from sensor */33#define OV08D10_REG_VTS_H		0x0534#define OV08D10_REG_VTS_L		0x0635#define OV08D10_VTS_MAX			0x7fff36 37/* Exposure controls from sensor */38#define OV08D10_REG_EXPOSURE_H		0x0239#define OV08D10_REG_EXPOSURE_M		0x0340#define OV08D10_REG_EXPOSURE_L		0x0441#define	OV08D10_EXPOSURE_MIN		642#define OV08D10_EXPOSURE_MAX_MARGIN	643#define	OV08D10_EXPOSURE_STEP		144 45/* Analog gain controls from sensor */46#define OV08D10_REG_ANALOG_GAIN		0x2447#define	OV08D10_ANAL_GAIN_MIN		12848#define	OV08D10_ANAL_GAIN_MAX		204749#define	OV08D10_ANAL_GAIN_STEP		150 51/* Digital gain controls from sensor */52#define OV08D10_REG_MWB_DGAIN_C		0x2153#define OV08D10_REG_MWB_DGAIN_F		0x2254#define OV08D10_DGTL_GAIN_MIN		055#define OV08D10_DGTL_GAIN_MAX		409556#define OV08D10_DGTL_GAIN_STEP		157#define OV08D10_DGTL_GAIN_DEFAULT	102458 59/* Test Pattern Control */60#define OV08D10_REG_TEST_PATTERN		0x1261#define OV08D10_TEST_PATTERN_ENABLE		0x0162#define OV08D10_TEST_PATTERN_DISABLE		0x0063 64/* Flip Mirror Controls from sensor */65#define OV08D10_REG_FLIP_OPT			0x3266#define OV08D10_REG_FLIP_MASK			0x367 68#define to_ov08d10(_sd)		container_of(_sd, struct ov08d10, sd)69 70struct ov08d10_reg {71	u8 address;72	u8 val;73};74 75struct ov08d10_reg_list {76	u32 num_of_regs;77	const struct ov08d10_reg *regs;78};79 80struct ov08d10_link_freq_config {81	const struct ov08d10_reg_list reg_list;82};83 84struct ov08d10_mode {85	/* Frame width in pixels */86	u32 width;87 88	/* Frame height in pixels */89	u32 height;90 91	/* Horizontal timining size */92	u32 hts;93 94	/* Default vertical timining size */95	u32 vts_def;96 97	/* Min vertical timining size */98	u32 vts_min;99 100	/* Link frequency needed for this resolution */101	u32 link_freq_index;102 103	/* Sensor register settings for this resolution */104	const struct ov08d10_reg_list reg_list;105 106	/* Number of data lanes */107	u8 data_lanes;108};109 110/* 3280x2460, 3264x2448 need 720Mbps/lane, 2 lanes */111static const struct ov08d10_reg mipi_data_rate_720mbps[] = {112	{0xfd, 0x00},113	{0x11, 0x2a},114	{0x14, 0x43},115	{0x1a, 0x04},116	{0x1b, 0xe1},117	{0x1e, 0x13},118	{0xb7, 0x02}119};120 121/* 1632x1224 needs 360Mbps/lane, 2 lanes */122static const struct ov08d10_reg mipi_data_rate_360mbps[] = {123	{0xfd, 0x00},124	{0x1a, 0x04},125	{0x1b, 0xe1},126	{0x1d, 0x00},127	{0x1c, 0x19},128	{0x11, 0x2a},129	{0x14, 0x54},130	{0x1e, 0x13},131	{0xb7, 0x02}132};133 134static const struct ov08d10_reg lane_2_mode_3280x2460[] = {135	/* 3280x2460 resolution */136	{0xfd, 0x01},137	{0x12, 0x00},138	{0x03, 0x12},139	{0x04, 0x58},140	{0x07, 0x05},141	{0x21, 0x02},142	{0x24, 0x30},143	{0x33, 0x03},144	{0x01, 0x03},145	{0x19, 0x10},146	{0x42, 0x55},147	{0x43, 0x00},148	{0x47, 0x07},149	{0x48, 0x08},150	{0xb2, 0x7f},151	{0xb3, 0x7b},152	{0xbd, 0x08},153	{0xd2, 0x57},154	{0xd3, 0x10},155	{0xd4, 0x08},156	{0xd5, 0x08},157	{0xd6, 0x06},158	{0xb1, 0x00},159	{0xb4, 0x00},160	{0xb7, 0x0a},161	{0xbc, 0x44},162	{0xbf, 0x48},163	{0xc1, 0x10},164	{0xc3, 0x24},165	{0xc8, 0x03},166	{0xc9, 0xf8},167	{0xe1, 0x33},168	{0xe2, 0xbb},169	{0x51, 0x0c},170	{0x52, 0x0a},171	{0x57, 0x8c},172	{0x59, 0x09},173	{0x5a, 0x08},174	{0x5e, 0x10},175	{0x60, 0x02},176	{0x6d, 0x5c},177	{0x76, 0x16},178	{0x7c, 0x11},179	{0x90, 0x28},180	{0x91, 0x16},181	{0x92, 0x1c},182	{0x93, 0x24},183	{0x95, 0x48},184	{0x9c, 0x06},185	{0xca, 0x0c},186	{0xce, 0x0d},187	{0xfd, 0x01},188	{0xc0, 0x00},189	{0xdd, 0x18},190	{0xde, 0x19},191	{0xdf, 0x32},192	{0xe0, 0x70},193	{0xfd, 0x01},194	{0xc2, 0x05},195	{0xd7, 0x88},196	{0xd8, 0x77},197	{0xd9, 0x00},198	{0xfd, 0x07},199	{0x00, 0xf8},200	{0x01, 0x2b},201	{0x05, 0x40},202	{0x08, 0x06},203	{0x09, 0x11},204	{0x28, 0x6f},205	{0x2a, 0x20},206	{0x2b, 0x05},207	{0x5e, 0x10},208	{0x52, 0x00},209	{0x53, 0x7c},210	{0x54, 0x00},211	{0x55, 0x7c},212	{0x56, 0x00},213	{0x57, 0x7c},214	{0x58, 0x00},215	{0x59, 0x7c},216	{0xfd, 0x02},217	{0x9a, 0x30},218	{0xa8, 0x02},219	{0xfd, 0x02},220	{0xa1, 0x01},221	{0xa2, 0x09},222	{0xa3, 0x9c},223	{0xa5, 0x00},224	{0xa6, 0x0c},225	{0xa7, 0xd0},226	{0xfd, 0x00},227	{0x24, 0x01},228	{0xc0, 0x16},229	{0xc1, 0x08},230	{0xc2, 0x30},231	{0x8e, 0x0c},232	{0x8f, 0xd0},233	{0x90, 0x09},234	{0x91, 0x9c},235	{0xfd, 0x05},236	{0x04, 0x40},237	{0x07, 0x00},238	{0x0d, 0x01},239	{0x0f, 0x01},240	{0x10, 0x00},241	{0x11, 0x00},242	{0x12, 0x0c},243	{0x13, 0xcf},244	{0x14, 0x00},245	{0x15, 0x00},246	{0xfd, 0x00},247	{0x20, 0x0f},248	{0xe7, 0x03},249	{0xe7, 0x00}250};251 252static const struct ov08d10_reg lane_2_mode_3264x2448[] = {253	/* 3264x2448 resolution */254	{0xfd, 0x01},255	{0x12, 0x00},256	{0x03, 0x12},257	{0x04, 0x58},258	{0x07, 0x05},259	{0x21, 0x02},260	{0x24, 0x30},261	{0x33, 0x03},262	{0x01, 0x03},263	{0x19, 0x10},264	{0x42, 0x55},265	{0x43, 0x00},266	{0x47, 0x07},267	{0x48, 0x08},268	{0xb2, 0x7f},269	{0xb3, 0x7b},270	{0xbd, 0x08},271	{0xd2, 0x57},272	{0xd3, 0x10},273	{0xd4, 0x08},274	{0xd5, 0x08},275	{0xd6, 0x06},276	{0xb1, 0x00},277	{0xb4, 0x00},278	{0xb7, 0x0a},279	{0xbc, 0x44},280	{0xbf, 0x48},281	{0xc1, 0x10},282	{0xc3, 0x24},283	{0xc8, 0x03},284	{0xc9, 0xf8},285	{0xe1, 0x33},286	{0xe2, 0xbb},287	{0x51, 0x0c},288	{0x52, 0x0a},289	{0x57, 0x8c},290	{0x59, 0x09},291	{0x5a, 0x08},292	{0x5e, 0x10},293	{0x60, 0x02},294	{0x6d, 0x5c},295	{0x76, 0x16},296	{0x7c, 0x11},297	{0x90, 0x28},298	{0x91, 0x16},299	{0x92, 0x1c},300	{0x93, 0x24},301	{0x95, 0x48},302	{0x9c, 0x06},303	{0xca, 0x0c},304	{0xce, 0x0d},305	{0xfd, 0x01},306	{0xc0, 0x00},307	{0xdd, 0x18},308	{0xde, 0x19},309	{0xdf, 0x32},310	{0xe0, 0x70},311	{0xfd, 0x01},312	{0xc2, 0x05},313	{0xd7, 0x88},314	{0xd8, 0x77},315	{0xd9, 0x00},316	{0xfd, 0x07},317	{0x00, 0xf8},318	{0x01, 0x2b},319	{0x05, 0x40},320	{0x08, 0x06},321	{0x09, 0x11},322	{0x28, 0x6f},323	{0x2a, 0x20},324	{0x2b, 0x05},325	{0x5e, 0x10},326	{0x52, 0x00},327	{0x53, 0x7c},328	{0x54, 0x00},329	{0x55, 0x7c},330	{0x56, 0x00},331	{0x57, 0x7c},332	{0x58, 0x00},333	{0x59, 0x7c},334	{0xfd, 0x02},335	{0x9a, 0x30},336	{0xa8, 0x02},337	{0xfd, 0x02},338	{0xa1, 0x09},339	{0xa2, 0x09},340	{0xa3, 0x90},341	{0xa5, 0x08},342	{0xa6, 0x0c},343	{0xa7, 0xc0},344	{0xfd, 0x00},345	{0x24, 0x01},346	{0xc0, 0x16},347	{0xc1, 0x08},348	{0xc2, 0x30},349	{0x8e, 0x0c},350	{0x8f, 0xc0},351	{0x90, 0x09},352	{0x91, 0x90},353	{0xfd, 0x05},354	{0x04, 0x40},355	{0x07, 0x00},356	{0x0d, 0x01},357	{0x0f, 0x01},358	{0x10, 0x00},359	{0x11, 0x00},360	{0x12, 0x0c},361	{0x13, 0xcf},362	{0x14, 0x00},363	{0x15, 0x00},364	{0xfd, 0x00},365	{0x20, 0x0f},366	{0xe7, 0x03},367	{0xe7, 0x00}368};369 370static const struct ov08d10_reg lane_2_mode_1632x1224[] = {371	/* 1640x1232 resolution */372	{0xfd, 0x01},373	{0x1a, 0x0a},374	{0x1b, 0x08},375	{0x2a, 0x01},376	{0x2b, 0x9a},377	{0xfd, 0x01},378	{0x12, 0x00},379	{0x03, 0x05},380	{0x04, 0xe2},381	{0x07, 0x05},382	{0x21, 0x02},383	{0x24, 0x30},384	{0x33, 0x03},385	{0x31, 0x06},386	{0x33, 0x03},387	{0x01, 0x03},388	{0x19, 0x10},389	{0x42, 0x55},390	{0x43, 0x00},391	{0x47, 0x07},392	{0x48, 0x08},393	{0xb2, 0x7f},394	{0xb3, 0x7b},395	{0xbd, 0x08},396	{0xd2, 0x57},397	{0xd3, 0x10},398	{0xd4, 0x08},399	{0xd5, 0x08},400	{0xd6, 0x06},401	{0xb1, 0x00},402	{0xb4, 0x00},403	{0xb7, 0x0a},404	{0xbc, 0x44},405	{0xbf, 0x48},406	{0xc1, 0x10},407	{0xc3, 0x24},408	{0xc8, 0x03},409	{0xc9, 0xf8},410	{0xe1, 0x33},411	{0xe2, 0xbb},412	{0x51, 0x0c},413	{0x52, 0x0a},414	{0x57, 0x8c},415	{0x59, 0x09},416	{0x5a, 0x08},417	{0x5e, 0x10},418	{0x60, 0x02},419	{0x6d, 0x5c},420	{0x76, 0x16},421	{0x7c, 0x1a},422	{0x90, 0x28},423	{0x91, 0x16},424	{0x92, 0x1c},425	{0x93, 0x24},426	{0x95, 0x48},427	{0x9c, 0x06},428	{0xca, 0x0c},429	{0xce, 0x0d},430	{0xfd, 0x01},431	{0xc0, 0x00},432	{0xdd, 0x18},433	{0xde, 0x19},434	{0xdf, 0x32},435	{0xe0, 0x70},436	{0xfd, 0x01},437	{0xc2, 0x05},438	{0xd7, 0x88},439	{0xd8, 0x77},440	{0xd9, 0x00},441	{0xfd, 0x07},442	{0x00, 0xf8},443	{0x01, 0x2b},444	{0x05, 0x40},445	{0x08, 0x03},446	{0x09, 0x08},447	{0x28, 0x6f},448	{0x2a, 0x20},449	{0x2b, 0x05},450	{0x2c, 0x01},451	{0x50, 0x02},452	{0x51, 0x03},453	{0x5e, 0x00},454	{0x52, 0x00},455	{0x53, 0x7c},456	{0x54, 0x00},457	{0x55, 0x7c},458	{0x56, 0x00},459	{0x57, 0x7c},460	{0x58, 0x00},461	{0x59, 0x7c},462	{0xfd, 0x02},463	{0x9a, 0x30},464	{0xa8, 0x02},465	{0xfd, 0x02},466	{0xa9, 0x04},467	{0xaa, 0xd0},468	{0xab, 0x06},469	{0xac, 0x68},470	{0xa1, 0x09},471	{0xa2, 0x04},472	{0xa3, 0xc8},473	{0xa5, 0x04},474	{0xa6, 0x06},475	{0xa7, 0x60},476	{0xfd, 0x05},477	{0x06, 0x80},478	{0x18, 0x06},479	{0x19, 0x68},480	{0xfd, 0x00},481	{0x24, 0x01},482	{0xc0, 0x16},483	{0xc1, 0x08},484	{0xc2, 0x30},485	{0x8e, 0x06},486	{0x8f, 0x60},487	{0x90, 0x04},488	{0x91, 0xc8},489	{0x93, 0x0e},490	{0x94, 0x77},491	{0x95, 0x77},492	{0x96, 0x10},493	{0x98, 0x88},494	{0x9c, 0x1a},495	{0xfd, 0x05},496	{0x04, 0x40},497	{0x07, 0x99},498	{0x0d, 0x03},499	{0x0f, 0x03},500	{0x10, 0x00},501	{0x11, 0x00},502	{0x12, 0x0c},503	{0x13, 0xcf},504	{0x14, 0x00},505	{0x15, 0x00},506	{0xfd, 0x00},507	{0x20, 0x0f},508	{0xe7, 0x03},509	{0xe7, 0x00},510};511 512static const char * const ov08d10_test_pattern_menu[] = {513	"Disabled",514	"Standard Color Bar",515};516 517struct ov08d10 {518	struct v4l2_subdev sd;519	struct media_pad pad;520	struct v4l2_ctrl_handler ctrl_handler;521 522	struct clk		*xvclk;523 524	/* V4L2 Controls */525	struct v4l2_ctrl *link_freq;526	struct v4l2_ctrl *pixel_rate;527	struct v4l2_ctrl *vblank;528	struct v4l2_ctrl *hblank;529	struct v4l2_ctrl *vflip;530	struct v4l2_ctrl *hflip;531	struct v4l2_ctrl *exposure;532 533	/* Current mode */534	const struct ov08d10_mode *cur_mode;535 536	/* To serialize asynchronus callbacks */537	struct mutex mutex;538 539	/* lanes index */540	u8 nlanes;541 542	const struct ov08d10_lane_cfg *priv_lane;543	u8 modes_size;544};545 546struct ov08d10_lane_cfg {547	const s64 link_freq_menu[2];548	const struct ov08d10_link_freq_config link_freq_configs[2];549	const struct ov08d10_mode sp_modes[3];550};551 552static const struct ov08d10_lane_cfg lane_cfg_2 = {553	{554		720000000,555		360000000,556	},557	{{558		.reg_list = {559			.num_of_regs =560				ARRAY_SIZE(mipi_data_rate_720mbps),561			.regs = mipi_data_rate_720mbps,562		}563	},564	{565		.reg_list = {566			.num_of_regs =567				ARRAY_SIZE(mipi_data_rate_360mbps),568			.regs = mipi_data_rate_360mbps,569		}570	}},571	{{572		.width = 3280,573		.height = 2460,574		.hts = 1840,575		.vts_def = 2504,576		.vts_min = 2504,577		.reg_list = {578			.num_of_regs = ARRAY_SIZE(lane_2_mode_3280x2460),579			.regs = lane_2_mode_3280x2460,580		},581		.link_freq_index = 0,582		.data_lanes = 2,583	},584	{585		.width = 3264,586		.height = 2448,587		.hts = 1840,588		.vts_def = 2504,589		.vts_min = 2504,590		.reg_list = {591			.num_of_regs = ARRAY_SIZE(lane_2_mode_3264x2448),592			.regs = lane_2_mode_3264x2448,593		},594		.link_freq_index = 0,595		.data_lanes = 2,596	},597	{598		.width = 1632,599		.height = 1224,600		.hts = 1912,601		.vts_def = 3736,602		.vts_min = 3736,603		.reg_list = {604			.num_of_regs = ARRAY_SIZE(lane_2_mode_1632x1224),605			.regs = lane_2_mode_1632x1224,606		},607		.link_freq_index = 1,608		.data_lanes = 2,609	}}610};611 612static u32 ov08d10_get_format_code(struct ov08d10 *ov08d10)613{614	static const u32 codes[2][2] = {615		{ MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10},616		{ MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10},617	};618 619	return codes[ov08d10->vflip->val][ov08d10->hflip->val];620}621 622static unsigned int ov08d10_modes_num(const struct ov08d10 *ov08d10)623{624	unsigned int i, count = 0;625 626	for (i = 0; i < ARRAY_SIZE(ov08d10->priv_lane->sp_modes); i++) {627		if (ov08d10->priv_lane->sp_modes[i].width == 0)628			break;629		count++;630	}631 632	return count;633}634 635static u64 to_rate(const s64 *link_freq_menu,636		   u32 f_index, u8 nlanes)637{638	u64 pixel_rate = link_freq_menu[f_index] * 2 * nlanes;639 640	do_div(pixel_rate, OV08D10_RGB_DEPTH);641 642	return pixel_rate;643}644 645static u64 to_pixels_per_line(const s64 *link_freq_menu, u32 hts,646			      u32 f_index, u8 nlanes)647{648	u64 ppl = hts * to_rate(link_freq_menu, f_index, nlanes);649 650	do_div(ppl, OV08D10_SCLK);651 652	return ppl;653}654 655static int ov08d10_write_reg_list(struct ov08d10 *ov08d10,656				  const struct ov08d10_reg_list *r_list)657{658	struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);659	unsigned int i;660	int ret;661 662	for (i = 0; i < r_list->num_of_regs; i++) {663		ret = i2c_smbus_write_byte_data(client, r_list->regs[i].address,664						r_list->regs[i].val);665		if (ret) {666			dev_err_ratelimited(&client->dev,667					    "failed to write reg 0x%2.2x. error = %d",668					    r_list->regs[i].address, ret);669			return ret;670		}671	}672 673	return 0;674}675 676static int ov08d10_update_analog_gain(struct ov08d10 *ov08d10, u32 a_gain)677{678	struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);679	u8 val;680	int ret;681 682	val = ((a_gain >> 3) & 0xFF);683	/* CIS control registers */684	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);685	if (ret < 0)686		return ret;687 688	/* update AGAIN */689	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_ANALOG_GAIN, val);690	if (ret < 0)691		return ret;692 693	return i2c_smbus_write_byte_data(client,694					 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);695}696 697static int ov08d10_update_digital_gain(struct ov08d10 *ov08d10, u32 d_gain)698{699	struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);700	u8 val;701	int ret;702 703	d_gain = (d_gain >> 1);704	/* CIS control registers */705	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);706	if (ret < 0)707		return ret;708 709	val = ((d_gain >> 8) & 0x3F);710	/* update DGAIN */711	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MWB_DGAIN_C, val);712	if (ret < 0)713		return ret;714 715	val = d_gain & 0xFF;716	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MWB_DGAIN_F, val);717	if (ret < 0)718		return ret;719 720	return i2c_smbus_write_byte_data(client,721					 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);722}723 724static int ov08d10_set_exposure(struct ov08d10 *ov08d10, u32 exposure)725{726	struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);727	u8 val;728	u8 hts_h, hts_l;729	u32 hts, cur_vts, exp_cal;730	int ret;731 732	cur_vts = ov08d10->cur_mode->vts_def;733	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);734	if (ret < 0)735		return ret;736 737	hts_h = i2c_smbus_read_byte_data(client, 0x37);738	hts_l = i2c_smbus_read_byte_data(client, 0x38);739	hts = ((hts_h << 8) | (hts_l));740	exp_cal = 66 * OV08D10_ROWCLK / hts;741	exposure = exposure * exp_cal / (cur_vts - OV08D10_EXPOSURE_MAX_MARGIN);742	/* CIS control registers */743	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);744	if (ret < 0)745		return ret;746 747	/* update exposure */748	val = ((exposure >> 16) & 0xFF);749	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_EXPOSURE_H, val);750	if (ret < 0)751		return ret;752 753	val = ((exposure >> 8) & 0xFF);754	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_EXPOSURE_M, val);755	if (ret < 0)756		return ret;757 758	val = exposure & 0xFF;759	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_EXPOSURE_L, val);760	if (ret < 0)761		return ret;762 763	return i2c_smbus_write_byte_data(client,764					 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);765}766 767static int ov08d10_set_vblank(struct ov08d10 *ov08d10, u32 vblank)768{769	struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);770	u8 val;771	int ret;772 773	/* CIS control registers */774	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);775	if (ret < 0)776		return ret;777 778	val = ((vblank >> 8) & 0xFF);779	/* update vblank */780	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_VTS_H, val);781	if (ret < 0)782		return ret;783 784	val = vblank & 0xFF;785	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_VTS_L, val);786	if (ret < 0)787		return ret;788 789	return i2c_smbus_write_byte_data(client,790					 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);791}792 793static int ov08d10_test_pattern(struct ov08d10 *ov08d10, u32 pattern)794{795	struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);796	u8 val;797	int ret;798 799	if (pattern)800		val = OV08D10_TEST_PATTERN_ENABLE;801	else802		val = OV08D10_TEST_PATTERN_DISABLE;803 804	/* CIS control registers */805	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);806	if (ret < 0)807		return ret;808 809	ret = i2c_smbus_write_byte_data(client,810					OV08D10_REG_TEST_PATTERN, val);811	if (ret < 0)812		return ret;813 814	return i2c_smbus_write_byte_data(client,815					 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);816}817 818static int ov08d10_set_ctrl_flip(struct ov08d10 *ov08d10, u32 ctrl_val)819{820	struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);821	u8 val;822	int ret;823 824	/* System control registers */825	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);826	if (ret < 0)827		return ret;828 829	ret = i2c_smbus_read_byte_data(client, OV08D10_REG_FLIP_OPT);830	if (ret < 0)831		return ret;832 833	val = ret | (ctrl_val & OV08D10_REG_FLIP_MASK);834 835	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);836	if (ret < 0)837		return ret;838 839	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_FLIP_OPT, val);840 841	if (ret < 0)842		return ret;843 844	return i2c_smbus_write_byte_data(client,845					 OV08D10_REG_GLOBAL_EFFECTIVE, 0x01);846}847 848static int ov08d10_set_ctrl(struct v4l2_ctrl *ctrl)849{850	struct ov08d10 *ov08d10 = container_of(ctrl->handler,851					     struct ov08d10, ctrl_handler);852	struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);853	s64 exposure_max;854	int ret;855 856	/* Propagate change of current control to all related controls */857	if (ctrl->id == V4L2_CID_VBLANK) {858		/* Update max exposure while meeting expected vblanking */859		exposure_max = ov08d10->cur_mode->height + ctrl->val -860			       OV08D10_EXPOSURE_MAX_MARGIN;861		__v4l2_ctrl_modify_range(ov08d10->exposure,862					 ov08d10->exposure->minimum,863					 exposure_max, ov08d10->exposure->step,864					 exposure_max);865	}866 867	/* V4L2 controls values will be applied only when power is already up */868	if (!pm_runtime_get_if_in_use(&client->dev))869		return 0;870 871	switch (ctrl->id) {872	case V4L2_CID_ANALOGUE_GAIN:873		ret = ov08d10_update_analog_gain(ov08d10, ctrl->val);874		break;875 876	case V4L2_CID_DIGITAL_GAIN:877		ret = ov08d10_update_digital_gain(ov08d10, ctrl->val);878		break;879 880	case V4L2_CID_EXPOSURE:881		ret = ov08d10_set_exposure(ov08d10, ctrl->val);882		break;883 884	case V4L2_CID_VBLANK:885		ret = ov08d10_set_vblank(ov08d10, ctrl->val);886		break;887 888	case V4L2_CID_TEST_PATTERN:889		ret = ov08d10_test_pattern(ov08d10, ctrl->val);890		break;891 892	case V4L2_CID_HFLIP:893	case V4L2_CID_VFLIP:894		ret = ov08d10_set_ctrl_flip(ov08d10,895					    ov08d10->hflip->val |896					    ov08d10->vflip->val << 1);897		break;898 899	default:900		ret = -EINVAL;901		break;902	}903 904	pm_runtime_put(&client->dev);905 906	return ret;907}908 909static const struct v4l2_ctrl_ops ov08d10_ctrl_ops = {910	.s_ctrl = ov08d10_set_ctrl,911};912 913static int ov08d10_init_controls(struct ov08d10 *ov08d10)914{915	struct v4l2_ctrl_handler *ctrl_hdlr;916	u8 link_freq_size;917	s64 exposure_max;918	s64 vblank_def;919	s64 vblank_min;920	s64 h_blank;921	s64 pixel_rate_max;922	const struct ov08d10_mode *mode;923	int ret;924 925	ctrl_hdlr = &ov08d10->ctrl_handler;926	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);927	if (ret)928		return ret;929 930	ctrl_hdlr->lock = &ov08d10->mutex;931	link_freq_size = ARRAY_SIZE(ov08d10->priv_lane->link_freq_menu);932	ov08d10->link_freq =933		v4l2_ctrl_new_int_menu(ctrl_hdlr, &ov08d10_ctrl_ops,934				       V4L2_CID_LINK_FREQ,935				       link_freq_size - 1,936				       0,937				       ov08d10->priv_lane->link_freq_menu);938	if (ov08d10->link_freq)939		ov08d10->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;940 941	pixel_rate_max = to_rate(ov08d10->priv_lane->link_freq_menu, 0,942				 ov08d10->cur_mode->data_lanes);943	ov08d10->pixel_rate =944		v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,945				  V4L2_CID_PIXEL_RATE, 0, pixel_rate_max, 1,946				  pixel_rate_max);947 948	mode = ov08d10->cur_mode;949	vblank_def = mode->vts_def - mode->height;950	vblank_min = mode->vts_min - mode->height;951	ov08d10->vblank =952		v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,953				  V4L2_CID_VBLANK, vblank_min,954				  OV08D10_VTS_MAX - mode->height, 1,955				  vblank_def);956 957	h_blank = to_pixels_per_line(ov08d10->priv_lane->link_freq_menu,958				     mode->hts, mode->link_freq_index,959				     mode->data_lanes) -960				     mode->width;961	ov08d10->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,962					    V4L2_CID_HBLANK, h_blank, h_blank,963					    1, h_blank);964	if (ov08d10->hblank)965		ov08d10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;966 967	v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,968			  OV08D10_ANAL_GAIN_MIN, OV08D10_ANAL_GAIN_MAX,969			  OV08D10_ANAL_GAIN_STEP, OV08D10_ANAL_GAIN_MIN);970 971	v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops, V4L2_CID_DIGITAL_GAIN,972			  OV08D10_DGTL_GAIN_MIN, OV08D10_DGTL_GAIN_MAX,973			  OV08D10_DGTL_GAIN_STEP, OV08D10_DGTL_GAIN_DEFAULT);974 975	exposure_max = mode->vts_def - OV08D10_EXPOSURE_MAX_MARGIN;976	ov08d10->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,977					      V4L2_CID_EXPOSURE,978					      OV08D10_EXPOSURE_MIN,979					      exposure_max,980					      OV08D10_EXPOSURE_STEP,981					      exposure_max);982 983	v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov08d10_ctrl_ops,984				     V4L2_CID_TEST_PATTERN,985				     ARRAY_SIZE(ov08d10_test_pattern_menu) - 1,986				     0, 0, ov08d10_test_pattern_menu);987 988	ov08d10->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,989					   V4L2_CID_HFLIP, 0, 1, 1, 0);990	if (ov08d10->hflip)991		ov08d10->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;992	ov08d10->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov08d10_ctrl_ops,993					   V4L2_CID_VFLIP, 0, 1, 1, 0);994	if (ov08d10->vflip)995		ov08d10->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;996 997	if (ctrl_hdlr->error)998		return ctrl_hdlr->error;999 1000	ov08d10->sd.ctrl_handler = ctrl_hdlr;1001 1002	return 0;1003}1004 1005static void ov08d10_update_pad_format(struct ov08d10 *ov08d10,1006				      const struct ov08d10_mode *mode,1007				      struct v4l2_mbus_framefmt *fmt)1008{1009	fmt->width = mode->width;1010	fmt->height = mode->height;1011	fmt->code = ov08d10_get_format_code(ov08d10);1012	fmt->field = V4L2_FIELD_NONE;1013}1014 1015static int ov08d10_start_streaming(struct ov08d10 *ov08d10)1016{1017	struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);1018	const struct ov08d10_reg_list *reg_list;1019	int link_freq_index, ret;1020 1021	link_freq_index = ov08d10->cur_mode->link_freq_index;1022	reg_list =1023	    &ov08d10->priv_lane->link_freq_configs[link_freq_index].reg_list;1024 1025	/* soft reset */1026	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00);1027	if (ret < 0) {1028		dev_err(&client->dev, "failed to reset sensor");1029		return ret;1030	}1031	ret = i2c_smbus_write_byte_data(client, 0x20, 0x0e);1032	if (ret < 0) {1033		dev_err(&client->dev, "failed to reset sensor");1034		return ret;1035	}1036	usleep_range(3000, 4000);1037	ret = i2c_smbus_write_byte_data(client, 0x20, 0x0b);1038	if (ret < 0) {1039		dev_err(&client->dev, "failed to reset sensor");1040		return ret;1041	}1042 1043	/* update sensor setting */1044	ret = ov08d10_write_reg_list(ov08d10, reg_list);1045	if (ret) {1046		dev_err(&client->dev, "failed to set plls");1047		return ret;1048	}1049 1050	reg_list = &ov08d10->cur_mode->reg_list;1051	ret = ov08d10_write_reg_list(ov08d10, reg_list);1052	if (ret) {1053		dev_err(&client->dev, "failed to set mode");1054		return ret;1055	}1056 1057	ret = __v4l2_ctrl_handler_setup(ov08d10->sd.ctrl_handler);1058	if (ret)1059		return ret;1060 1061	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00);1062	if (ret < 0)1063		return ret;1064 1065	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MODE_SELECT,1066					OV08D10_MODE_STREAMING);1067	if (ret < 0)1068		return ret;1069 1070	return i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);1071}1072 1073static void ov08d10_stop_streaming(struct ov08d10 *ov08d10)1074{1075	struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);1076	int ret;1077 1078	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00);1079	if (ret < 0) {1080		dev_err(&client->dev, "failed to stop streaming");1081		return;1082	}1083	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_MODE_SELECT,1084					OV08D10_MODE_STANDBY);1085	if (ret < 0) {1086		dev_err(&client->dev, "failed to stop streaming");1087		return;1088	}1089 1090	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x01);1091	if (ret < 0) {1092		dev_err(&client->dev, "failed to stop streaming");1093		return;1094	}1095}1096 1097static int ov08d10_set_stream(struct v4l2_subdev *sd, int enable)1098{1099	struct ov08d10 *ov08d10 = to_ov08d10(sd);1100	struct i2c_client *client = v4l2_get_subdevdata(sd);1101	int ret = 0;1102 1103	mutex_lock(&ov08d10->mutex);1104	if (enable) {1105		ret = pm_runtime_resume_and_get(&client->dev);1106		if (ret < 0) {1107			mutex_unlock(&ov08d10->mutex);1108			return ret;1109		}1110 1111		ret = ov08d10_start_streaming(ov08d10);1112		if (ret) {1113			enable = 0;1114			ov08d10_stop_streaming(ov08d10);1115			pm_runtime_put(&client->dev);1116		}1117	} else {1118		ov08d10_stop_streaming(ov08d10);1119		pm_runtime_put(&client->dev);1120	}1121 1122	/* vflip and hflip cannot change during streaming */1123	__v4l2_ctrl_grab(ov08d10->vflip, enable);1124	__v4l2_ctrl_grab(ov08d10->hflip, enable);1125 1126	mutex_unlock(&ov08d10->mutex);1127 1128	return ret;1129}1130 1131static int ov08d10_set_format(struct v4l2_subdev *sd,1132			      struct v4l2_subdev_state *sd_state,1133			      struct v4l2_subdev_format *fmt)1134{1135	struct ov08d10 *ov08d10 = to_ov08d10(sd);1136	const struct ov08d10_mode *mode;1137	s32 vblank_def, h_blank;1138	s64 pixel_rate;1139 1140	mode = v4l2_find_nearest_size(ov08d10->priv_lane->sp_modes,1141				      ov08d10->modes_size,1142				      width, height, fmt->format.width,1143				      fmt->format.height);1144 1145	mutex_lock(&ov08d10->mutex);1146	ov08d10_update_pad_format(ov08d10, mode, &fmt->format);1147	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {1148		*v4l2_subdev_state_get_format(sd_state, fmt->pad) =1149								fmt->format;1150	} else {1151		ov08d10->cur_mode = mode;1152		__v4l2_ctrl_s_ctrl(ov08d10->link_freq, mode->link_freq_index);1153		pixel_rate = to_rate(ov08d10->priv_lane->link_freq_menu,1154				     mode->link_freq_index,1155				     ov08d10->cur_mode->data_lanes);1156		__v4l2_ctrl_s_ctrl_int64(ov08d10->pixel_rate, pixel_rate);1157 1158		/* Update limits and set FPS to default */1159		vblank_def = mode->vts_def - mode->height;1160		__v4l2_ctrl_modify_range(ov08d10->vblank,1161					 mode->vts_min - mode->height,1162					 OV08D10_VTS_MAX - mode->height, 1,1163					 vblank_def);1164		__v4l2_ctrl_s_ctrl(ov08d10->vblank, vblank_def);1165		h_blank = to_pixels_per_line(ov08d10->priv_lane->link_freq_menu,1166					     mode->hts,1167					     mode->link_freq_index,1168					     ov08d10->cur_mode->data_lanes)1169					     - mode->width;1170		__v4l2_ctrl_modify_range(ov08d10->hblank, h_blank, h_blank, 1,1171					 h_blank);1172	}1173 1174	mutex_unlock(&ov08d10->mutex);1175 1176	return 0;1177}1178 1179static int ov08d10_get_format(struct v4l2_subdev *sd,1180			      struct v4l2_subdev_state *sd_state,1181			      struct v4l2_subdev_format *fmt)1182{1183	struct ov08d10 *ov08d10 = to_ov08d10(sd);1184 1185	mutex_lock(&ov08d10->mutex);1186	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)1187		fmt->format = *v4l2_subdev_state_get_format(sd_state,1188							    fmt->pad);1189	else1190		ov08d10_update_pad_format(ov08d10, ov08d10->cur_mode,1191					  &fmt->format);1192 1193	mutex_unlock(&ov08d10->mutex);1194 1195	return 0;1196}1197 1198static int ov08d10_enum_mbus_code(struct v4l2_subdev *sd,1199				  struct v4l2_subdev_state *sd_state,1200				  struct v4l2_subdev_mbus_code_enum *code)1201{1202	struct ov08d10 *ov08d10 = to_ov08d10(sd);1203 1204	if (code->index > 0)1205		return -EINVAL;1206 1207	mutex_lock(&ov08d10->mutex);1208	code->code = ov08d10_get_format_code(ov08d10);1209	mutex_unlock(&ov08d10->mutex);1210 1211	return 0;1212}1213 1214static int ov08d10_enum_frame_size(struct v4l2_subdev *sd,1215				   struct v4l2_subdev_state *sd_state,1216				   struct v4l2_subdev_frame_size_enum *fse)1217{1218	struct ov08d10 *ov08d10 = to_ov08d10(sd);1219 1220	if (fse->index >= ov08d10->modes_size)1221		return -EINVAL;1222 1223	mutex_lock(&ov08d10->mutex);1224	if (fse->code != ov08d10_get_format_code(ov08d10)) {1225		mutex_unlock(&ov08d10->mutex);1226		return -EINVAL;1227	}1228	mutex_unlock(&ov08d10->mutex);1229 1230	fse->min_width = ov08d10->priv_lane->sp_modes[fse->index].width;1231	fse->max_width = fse->min_width;1232	fse->min_height = ov08d10->priv_lane->sp_modes[fse->index].height;1233	fse->max_height = fse->min_height;1234 1235	return 0;1236}1237 1238static int ov08d10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)1239{1240	struct ov08d10 *ov08d10 = to_ov08d10(sd);1241 1242	mutex_lock(&ov08d10->mutex);1243	ov08d10_update_pad_format(ov08d10, &ov08d10->priv_lane->sp_modes[0],1244				  v4l2_subdev_state_get_format(fh->state, 0));1245	mutex_unlock(&ov08d10->mutex);1246 1247	return 0;1248}1249 1250static const struct v4l2_subdev_video_ops ov08d10_video_ops = {1251	.s_stream = ov08d10_set_stream,1252};1253 1254static const struct v4l2_subdev_pad_ops ov08d10_pad_ops = {1255	.set_fmt = ov08d10_set_format,1256	.get_fmt = ov08d10_get_format,1257	.enum_mbus_code = ov08d10_enum_mbus_code,1258	.enum_frame_size = ov08d10_enum_frame_size,1259};1260 1261static const struct v4l2_subdev_ops ov08d10_subdev_ops = {1262	.video = &ov08d10_video_ops,1263	.pad = &ov08d10_pad_ops,1264};1265 1266static const struct v4l2_subdev_internal_ops ov08d10_internal_ops = {1267	.open = ov08d10_open,1268};1269 1270static int ov08d10_identify_module(struct ov08d10 *ov08d10)1271{1272	struct i2c_client *client = v4l2_get_subdevdata(&ov08d10->sd);1273	u32 val;1274	u16 chip_id;1275	int ret;1276 1277	/* System control registers */1278	ret = i2c_smbus_write_byte_data(client, OV08D10_REG_PAGE, 0x00);1279	if (ret < 0)1280		return ret;1281 1282	/* Validate the chip ID */1283	ret = i2c_smbus_read_byte_data(client, OV08D10_REG_CHIP_ID_0);1284	if (ret < 0)1285		return ret;1286 1287	val = ret << 8;1288 1289	ret = i2c_smbus_read_byte_data(client, OV08D10_REG_CHIP_ID_1);1290	if (ret < 0)1291		return ret;1292 1293	chip_id = val | ret;1294 1295	if ((chip_id & OV08D10_ID_MASK) != OV08D10_CHIP_ID) {1296		dev_err(&client->dev, "unexpected sensor id(0x%04x)\n",1297			chip_id);1298		return -EINVAL;1299	}1300 1301	return 0;1302}1303 1304static int ov08d10_get_hwcfg(struct ov08d10 *ov08d10, struct device *dev)1305{1306	struct fwnode_handle *ep;1307	struct fwnode_handle *fwnode = dev_fwnode(dev);1308	struct v4l2_fwnode_endpoint bus_cfg = {1309		.bus_type = V4L2_MBUS_CSI2_DPHY1310	};1311	u32 xvclk_rate;1312	unsigned int i, j;1313	int ret;1314 1315	if (!fwnode)1316		return -ENXIO;1317 1318	ret = fwnode_property_read_u32(fwnode, "clock-frequency", &xvclk_rate);1319	if (ret)1320		return ret;1321 1322	if (xvclk_rate != OV08D10_XVCLK_19_2)1323		dev_warn(dev, "external clock rate %u is unsupported",1324			 xvclk_rate);1325 1326	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);1327	if (!ep)1328		return -ENXIO;1329 1330	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);1331	fwnode_handle_put(ep);1332	if (ret)1333		return ret;1334 1335	/* Get number of data lanes */1336	if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2) {1337		dev_err(dev, "number of CSI2 data lanes %d is not supported",1338			bus_cfg.bus.mipi_csi2.num_data_lanes);1339		ret = -EINVAL;1340		goto check_hwcfg_error;1341	}1342 1343	dev_dbg(dev, "Using %u data lanes\n", ov08d10->cur_mode->data_lanes);1344 1345	ov08d10->priv_lane = &lane_cfg_2;1346	ov08d10->modes_size = ov08d10_modes_num(ov08d10);1347 1348	if (!bus_cfg.nr_of_link_frequencies) {1349		dev_err(dev, "no link frequencies defined");1350		ret = -EINVAL;1351		goto check_hwcfg_error;1352	}1353 1354	for (i = 0; i < ARRAY_SIZE(ov08d10->priv_lane->link_freq_menu); i++) {1355		for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) {1356			if (ov08d10->priv_lane->link_freq_menu[i] ==1357			    bus_cfg.link_frequencies[j])1358				break;1359		}1360 1361		if (j == bus_cfg.nr_of_link_frequencies) {1362			dev_err(dev, "no link frequency %lld supported",1363				ov08d10->priv_lane->link_freq_menu[i]);1364			ret = -EINVAL;1365			goto check_hwcfg_error;1366		}1367	}1368 1369check_hwcfg_error:1370	v4l2_fwnode_endpoint_free(&bus_cfg);1371 1372	return ret;1373}1374 1375static void ov08d10_remove(struct i2c_client *client)1376{1377	struct v4l2_subdev *sd = i2c_get_clientdata(client);1378	struct ov08d10 *ov08d10 = to_ov08d10(sd);1379 1380	v4l2_async_unregister_subdev(sd);1381	media_entity_cleanup(&sd->entity);1382	v4l2_ctrl_handler_free(sd->ctrl_handler);1383	pm_runtime_disable(&client->dev);1384	mutex_destroy(&ov08d10->mutex);1385}1386 1387static int ov08d10_probe(struct i2c_client *client)1388{1389	struct ov08d10 *ov08d10;1390	int ret;1391 1392	ov08d10 = devm_kzalloc(&client->dev, sizeof(*ov08d10), GFP_KERNEL);1393	if (!ov08d10)1394		return -ENOMEM;1395 1396	ret = ov08d10_get_hwcfg(ov08d10, &client->dev);1397	if (ret) {1398		dev_err(&client->dev, "failed to get HW configuration: %d",1399			ret);1400		return ret;1401	}1402 1403	v4l2_i2c_subdev_init(&ov08d10->sd, client, &ov08d10_subdev_ops);1404 1405	ret = ov08d10_identify_module(ov08d10);1406	if (ret) {1407		dev_err(&client->dev, "failed to find sensor: %d", ret);1408		return ret;1409	}1410 1411	mutex_init(&ov08d10->mutex);1412	ov08d10->cur_mode = &ov08d10->priv_lane->sp_modes[0];1413	ret = ov08d10_init_controls(ov08d10);1414	if (ret) {1415		dev_err(&client->dev, "failed to init controls: %d", ret);1416		goto probe_error_v4l2_ctrl_handler_free;1417	}1418 1419	ov08d10->sd.internal_ops = &ov08d10_internal_ops;1420	ov08d10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;1421	ov08d10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;1422	ov08d10->pad.flags = MEDIA_PAD_FL_SOURCE;1423	ret = media_entity_pads_init(&ov08d10->sd.entity, 1, &ov08d10->pad);1424	if (ret) {1425		dev_err(&client->dev, "failed to init entity pads: %d", ret);1426		goto probe_error_v4l2_ctrl_handler_free;1427	}1428 1429	ret = v4l2_async_register_subdev_sensor(&ov08d10->sd);1430	if (ret < 0) {1431		dev_err(&client->dev, "failed to register V4L2 subdev: %d",1432			ret);1433		goto probe_error_media_entity_cleanup;1434	}1435 1436	/*1437	 * Device is already turned on by i2c-core with ACPI domain PM.1438	 * Enable runtime PM and turn off the device.1439	 */1440	pm_runtime_set_active(&client->dev);1441	pm_runtime_enable(&client->dev);1442	pm_runtime_idle(&client->dev);1443 1444	return 0;1445 1446probe_error_media_entity_cleanup:1447	media_entity_cleanup(&ov08d10->sd.entity);1448 1449probe_error_v4l2_ctrl_handler_free:1450	v4l2_ctrl_handler_free(ov08d10->sd.ctrl_handler);1451	mutex_destroy(&ov08d10->mutex);1452 1453	return ret;1454}1455 1456#ifdef CONFIG_ACPI1457static const struct acpi_device_id ov08d10_acpi_ids[] = {1458	{ "OVTI08D1" },1459	{ /* sentinel */ }1460};1461 1462MODULE_DEVICE_TABLE(acpi, ov08d10_acpi_ids);1463#endif1464 1465static struct i2c_driver ov08d10_i2c_driver = {1466	.driver = {1467		.name = "ov08d10",1468		.acpi_match_table = ACPI_PTR(ov08d10_acpi_ids),1469	},1470	.probe = ov08d10_probe,1471	.remove = ov08d10_remove,1472};1473 1474module_i2c_driver(ov08d10_i2c_driver);1475 1476MODULE_AUTHOR("Su, Jimmy <jimmy.su@intel.com>");1477MODULE_DESCRIPTION("OmniVision ov08d10 sensor driver");1478MODULE_LICENSE("GPL v2");1479