brintos

brintos / linux-shallow public Read only

0
0
Text · 52.6 KiB · dd1b4ff Raw
2505 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2018 Intel Corporation3 4#include <linux/unaligned.h>5#include <linux/acpi.h>6#include <linux/i2c.h>7#include <linux/module.h>8#include <linux/pm_runtime.h>9#include <media/v4l2-ctrls.h>10#include <media/v4l2-device.h>11#include <media/v4l2-event.h>12#include <media/v4l2-fwnode.h>13 14#define IMX319_REG_MODE_SELECT		0x010015#define IMX319_MODE_STANDBY		0x0016#define IMX319_MODE_STREAMING		0x0117 18/* Chip ID */19#define IMX319_REG_CHIP_ID		0x001620#define IMX319_CHIP_ID			0x031921 22/* V_TIMING internal */23#define IMX319_REG_FLL			0x034024#define IMX319_FLL_MAX			0xffff25 26/* Exposure control */27#define IMX319_REG_EXPOSURE		0x020228#define IMX319_EXPOSURE_MIN		129#define IMX319_EXPOSURE_STEP		130#define IMX319_EXPOSURE_DEFAULT		0x04f631 32/*33 *  the digital control register for all color control looks like:34 *  +-----------------+------------------+35 *  |      [7:0]      |       [15:8]     |36 *  +-----------------+------------------+37 *  |	  0x020f      |       0x020e     |38 *  --------------------------------------39 *  it is used to calculate the digital gain times value(integral + fractional)40 *  the [15:8] bits is the fractional part and [7:0] bits is the integral41 *  calculation equation is:42 *      gain value (unit: times) = REG[15:8] + REG[7:0]/0x10043 *  Only value in 0x0100 ~ 0x0FFF range is allowed.44 *  Analog gain use 10 bits in the registers and allowed range is 0 ~ 96045 */46/* Analog gain control */47#define IMX319_REG_ANALOG_GAIN		0x020448#define IMX319_ANA_GAIN_MIN		049#define IMX319_ANA_GAIN_MAX		96050#define IMX319_ANA_GAIN_STEP		151#define IMX319_ANA_GAIN_DEFAULT		052 53/* Digital gain control */54#define IMX319_REG_DPGA_USE_GLOBAL_GAIN	0x3ff955#define IMX319_REG_DIG_GAIN_GLOBAL	0x020e56#define IMX319_DGTL_GAIN_MIN		25657#define IMX319_DGTL_GAIN_MAX		409558#define IMX319_DGTL_GAIN_STEP		159#define IMX319_DGTL_GAIN_DEFAULT	25660 61/* Test Pattern Control */62#define IMX319_REG_TEST_PATTERN		0x060063#define IMX319_TEST_PATTERN_DISABLED		064#define IMX319_TEST_PATTERN_SOLID_COLOR		165#define IMX319_TEST_PATTERN_COLOR_BARS		266#define IMX319_TEST_PATTERN_GRAY_COLOR_BARS	367#define IMX319_TEST_PATTERN_PN9			468 69/* Flip Control */70#define IMX319_REG_ORIENTATION		0x010171 72/* default link frequency and external clock */73#define IMX319_LINK_FREQ_DEFAULT	482400000LL74#define IMX319_EXT_CLK			1920000075#define IMX319_LINK_FREQ_INDEX		076 77struct imx319_reg {78	u16 address;79	u8 val;80};81 82struct imx319_reg_list {83	u32 num_of_regs;84	const struct imx319_reg *regs;85};86 87/* Mode : resolution and related config&values */88struct imx319_mode {89	/* Frame width */90	u32 width;91	/* Frame height */92	u32 height;93 94	/* V-timing */95	u32 fll_def;96	u32 fll_min;97 98	/* H-timing */99	u32 llp;100 101	/* index of link frequency */102	u32 link_freq_index;103 104	/* Default register values */105	struct imx319_reg_list reg_list;106};107 108struct imx319_hwcfg {109	u32 ext_clk;			/* sensor external clk */110	unsigned long link_freq_bitmap;111};112 113struct imx319 {114	struct v4l2_subdev sd;115	struct media_pad pad;116 117	struct v4l2_ctrl_handler ctrl_handler;118	/* V4L2 Controls */119	struct v4l2_ctrl *link_freq;120	struct v4l2_ctrl *pixel_rate;121	struct v4l2_ctrl *vblank;122	struct v4l2_ctrl *hblank;123	struct v4l2_ctrl *exposure;124	struct v4l2_ctrl *vflip;125	struct v4l2_ctrl *hflip;126 127	/* Current mode */128	const struct imx319_mode *cur_mode;129 130	struct imx319_hwcfg *hwcfg;131 132	/*133	 * Mutex for serialized access:134	 * Protect sensor set pad format and start/stop streaming safely.135	 * Protect access to sensor v4l2 controls.136	 */137	struct mutex mutex;138 139	/* True if the device has been identified */140	bool identified;141};142 143static const struct imx319_reg imx319_global_regs[] = {144	{ 0x0136, 0x13 },145	{ 0x0137, 0x33 },146	{ 0x3c7e, 0x05 },147	{ 0x3c7f, 0x07 },148	{ 0x4d39, 0x0b },149	{ 0x4d41, 0x33 },150	{ 0x4d43, 0x0c },151	{ 0x4d49, 0x89 },152	{ 0x4e05, 0x0b },153	{ 0x4e0d, 0x33 },154	{ 0x4e0f, 0x0c },155	{ 0x4e15, 0x89 },156	{ 0x4e49, 0x2a },157	{ 0x4e51, 0x33 },158	{ 0x4e53, 0x0c },159	{ 0x4e59, 0x89 },160	{ 0x5601, 0x4f },161	{ 0x560b, 0x45 },162	{ 0x562f, 0x0a },163	{ 0x5643, 0x0a },164	{ 0x5645, 0x0c },165	{ 0x56ef, 0x51 },166	{ 0x586f, 0x33 },167	{ 0x5873, 0x89 },168	{ 0x5905, 0x33 },169	{ 0x5907, 0x89 },170	{ 0x590d, 0x33 },171	{ 0x590f, 0x89 },172	{ 0x5915, 0x33 },173	{ 0x5917, 0x89 },174	{ 0x5969, 0x1c },175	{ 0x596b, 0x72 },176	{ 0x5971, 0x33 },177	{ 0x5973, 0x89 },178	{ 0x5975, 0x33 },179	{ 0x5977, 0x89 },180	{ 0x5979, 0x1c },181	{ 0x597b, 0x72 },182	{ 0x5985, 0x33 },183	{ 0x5987, 0x89 },184	{ 0x5999, 0x1c },185	{ 0x599b, 0x72 },186	{ 0x59a5, 0x33 },187	{ 0x59a7, 0x89 },188	{ 0x7485, 0x08 },189	{ 0x7487, 0x0c },190	{ 0x7489, 0xc7 },191	{ 0x748b, 0x8b },192	{ 0x9004, 0x09 },193	{ 0x9200, 0x6a },194	{ 0x9201, 0x22 },195	{ 0x9202, 0x6a },196	{ 0x9203, 0x23 },197	{ 0x9204, 0x5f },198	{ 0x9205, 0x23 },199	{ 0x9206, 0x5f },200	{ 0x9207, 0x24 },201	{ 0x9208, 0x5f },202	{ 0x9209, 0x26 },203	{ 0x920a, 0x5f },204	{ 0x920b, 0x27 },205	{ 0x920c, 0x5f },206	{ 0x920d, 0x29 },207	{ 0x920e, 0x5f },208	{ 0x920f, 0x2a },209	{ 0x9210, 0x5f },210	{ 0x9211, 0x2c },211	{ 0xbc22, 0x1a },212	{ 0xf01f, 0x04 },213	{ 0xf021, 0x03 },214	{ 0xf023, 0x02 },215	{ 0xf03d, 0x05 },216	{ 0xf03f, 0x03 },217	{ 0xf041, 0x02 },218	{ 0xf0af, 0x04 },219	{ 0xf0b1, 0x03 },220	{ 0xf0b3, 0x02 },221	{ 0xf0cd, 0x05 },222	{ 0xf0cf, 0x03 },223	{ 0xf0d1, 0x02 },224	{ 0xf13f, 0x04 },225	{ 0xf141, 0x03 },226	{ 0xf143, 0x02 },227	{ 0xf15d, 0x05 },228	{ 0xf15f, 0x03 },229	{ 0xf161, 0x02 },230	{ 0xf1cf, 0x04 },231	{ 0xf1d1, 0x03 },232	{ 0xf1d3, 0x02 },233	{ 0xf1ed, 0x05 },234	{ 0xf1ef, 0x03 },235	{ 0xf1f1, 0x02 },236	{ 0xf287, 0x04 },237	{ 0xf289, 0x03 },238	{ 0xf28b, 0x02 },239	{ 0xf2a5, 0x05 },240	{ 0xf2a7, 0x03 },241	{ 0xf2a9, 0x02 },242	{ 0xf2b7, 0x04 },243	{ 0xf2b9, 0x03 },244	{ 0xf2bb, 0x02 },245	{ 0xf2d5, 0x05 },246	{ 0xf2d7, 0x03 },247	{ 0xf2d9, 0x02 },248};249 250static const struct imx319_reg_list imx319_global_setting = {251	.num_of_regs = ARRAY_SIZE(imx319_global_regs),252	.regs = imx319_global_regs,253};254 255static const struct imx319_reg mode_3264x2448_regs[] = {256	{ 0x0112, 0x0a },257	{ 0x0113, 0x0a },258	{ 0x0114, 0x03 },259	{ 0x0342, 0x0f },260	{ 0x0343, 0x80 },261	{ 0x0340, 0x0c },262	{ 0x0341, 0xaa },263	{ 0x0344, 0x00 },264	{ 0x0345, 0x00 },265	{ 0x0346, 0x00 },266	{ 0x0347, 0x00 },267	{ 0x0348, 0x0c },268	{ 0x0349, 0xcf },269	{ 0x034a, 0x09 },270	{ 0x034b, 0x9f },271	{ 0x0220, 0x00 },272	{ 0x0221, 0x11 },273	{ 0x0381, 0x01 },274	{ 0x0383, 0x01 },275	{ 0x0385, 0x01 },276	{ 0x0387, 0x01 },277	{ 0x0900, 0x00 },278	{ 0x0901, 0x11 },279	{ 0x0902, 0x0a },280	{ 0x3140, 0x02 },281	{ 0x3141, 0x00 },282	{ 0x3f0d, 0x0a },283	{ 0x3f14, 0x01 },284	{ 0x3f3c, 0x01 },285	{ 0x3f4d, 0x01 },286	{ 0x3f4c, 0x01 },287	{ 0x4254, 0x7f },288	{ 0x0401, 0x00 },289	{ 0x0404, 0x00 },290	{ 0x0405, 0x10 },291	{ 0x0408, 0x00 },292	{ 0x0409, 0x08 },293	{ 0x040a, 0x00 },294	{ 0x040b, 0x08 },295	{ 0x040c, 0x0c },296	{ 0x040d, 0xc0 },297	{ 0x040e, 0x09 },298	{ 0x040f, 0x90 },299	{ 0x034c, 0x0c },300	{ 0x034d, 0xc0 },301	{ 0x034e, 0x09 },302	{ 0x034f, 0x90 },303	{ 0x3261, 0x00 },304	{ 0x3264, 0x00 },305	{ 0x3265, 0x10 },306	{ 0x0301, 0x05 },307	{ 0x0303, 0x04 },308	{ 0x0305, 0x04 },309	{ 0x0306, 0x01 },310	{ 0x0307, 0x92 },311	{ 0x0309, 0x0a },312	{ 0x030b, 0x02 },313	{ 0x030d, 0x02 },314	{ 0x030e, 0x00 },315	{ 0x030f, 0xfa },316	{ 0x0310, 0x00 },317	{ 0x0820, 0x0f },318	{ 0x0821, 0x13 },319	{ 0x0822, 0x33 },320	{ 0x0823, 0x33 },321	{ 0x3e20, 0x01 },322	{ 0x3e37, 0x00 },323	{ 0x3e3b, 0x01 },324	{ 0x38a3, 0x01 },325	{ 0x38a8, 0x00 },326	{ 0x38a9, 0x00 },327	{ 0x38aa, 0x00 },328	{ 0x38ab, 0x00 },329	{ 0x3234, 0x00 },330	{ 0x3fc1, 0x00 },331	{ 0x3235, 0x00 },332	{ 0x3802, 0x00 },333	{ 0x3143, 0x04 },334	{ 0x360a, 0x00 },335	{ 0x0b00, 0x00 },336	{ 0x0106, 0x00 },337	{ 0x0b05, 0x01 },338	{ 0x0b06, 0x01 },339	{ 0x3230, 0x00 },340	{ 0x3602, 0x01 },341	{ 0x3607, 0x01 },342	{ 0x3c00, 0x00 },343	{ 0x3c01, 0x48 },344	{ 0x3c02, 0xc8 },345	{ 0x3c03, 0xaa },346	{ 0x3c04, 0x91 },347	{ 0x3c05, 0x54 },348	{ 0x3c06, 0x26 },349	{ 0x3c07, 0x20 },350	{ 0x3c08, 0x51 },351	{ 0x3d80, 0x00 },352	{ 0x3f50, 0x00 },353	{ 0x3f56, 0x00 },354	{ 0x3f57, 0x30 },355	{ 0x3f78, 0x01 },356	{ 0x3f79, 0x18 },357	{ 0x3f7c, 0x00 },358	{ 0x3f7d, 0x00 },359	{ 0x3fba, 0x00 },360	{ 0x3fbb, 0x00 },361	{ 0xa081, 0x00 },362	{ 0xe014, 0x00 },363	{ 0x0202, 0x0a },364	{ 0x0203, 0x7a },365	{ 0x0224, 0x01 },366	{ 0x0225, 0xf4 },367	{ 0x0204, 0x00 },368	{ 0x0205, 0x00 },369	{ 0x0216, 0x00 },370	{ 0x0217, 0x00 },371	{ 0x020e, 0x01 },372	{ 0x020f, 0x00 },373	{ 0x0210, 0x01 },374	{ 0x0211, 0x00 },375	{ 0x0212, 0x01 },376	{ 0x0213, 0x00 },377	{ 0x0214, 0x01 },378	{ 0x0215, 0x00 },379	{ 0x0218, 0x01 },380	{ 0x0219, 0x00 },381	{ 0x3614, 0x00 },382	{ 0x3616, 0x0d },383	{ 0x3617, 0x56 },384	{ 0xb612, 0x20 },385	{ 0xb613, 0x20 },386	{ 0xb614, 0x20 },387	{ 0xb615, 0x20 },388	{ 0xb616, 0x0a },389	{ 0xb617, 0x0a },390	{ 0xb618, 0x20 },391	{ 0xb619, 0x20 },392	{ 0xb61a, 0x20 },393	{ 0xb61b, 0x20 },394	{ 0xb61c, 0x0a },395	{ 0xb61d, 0x0a },396	{ 0xb666, 0x30 },397	{ 0xb667, 0x30 },398	{ 0xb668, 0x30 },399	{ 0xb669, 0x30 },400	{ 0xb66a, 0x14 },401	{ 0xb66b, 0x14 },402	{ 0xb66c, 0x20 },403	{ 0xb66d, 0x20 },404	{ 0xb66e, 0x20 },405	{ 0xb66f, 0x20 },406	{ 0xb670, 0x10 },407	{ 0xb671, 0x10 },408	{ 0x3237, 0x00 },409	{ 0x3900, 0x00 },410	{ 0x3901, 0x00 },411	{ 0x3902, 0x00 },412	{ 0x3904, 0x00 },413	{ 0x3905, 0x00 },414	{ 0x3906, 0x00 },415	{ 0x3907, 0x00 },416	{ 0x3908, 0x00 },417	{ 0x3909, 0x00 },418	{ 0x3912, 0x00 },419	{ 0x3930, 0x00 },420	{ 0x3931, 0x00 },421	{ 0x3933, 0x00 },422	{ 0x3934, 0x00 },423	{ 0x3935, 0x00 },424	{ 0x3936, 0x00 },425	{ 0x3937, 0x00 },426	{ 0x30ac, 0x00 },427};428 429static const struct imx319_reg mode_3280x2464_regs[] = {430	{ 0x0112, 0x0a },431	{ 0x0113, 0x0a },432	{ 0x0114, 0x03 },433	{ 0x0342, 0x0f },434	{ 0x0343, 0x80 },435	{ 0x0340, 0x0c },436	{ 0x0341, 0xaa },437	{ 0x0344, 0x00 },438	{ 0x0345, 0x00 },439	{ 0x0346, 0x00 },440	{ 0x0347, 0x00 },441	{ 0x0348, 0x0c },442	{ 0x0349, 0xcf },443	{ 0x034a, 0x09 },444	{ 0x034b, 0x9f },445	{ 0x0220, 0x00 },446	{ 0x0221, 0x11 },447	{ 0x0381, 0x01 },448	{ 0x0383, 0x01 },449	{ 0x0385, 0x01 },450	{ 0x0387, 0x01 },451	{ 0x0900, 0x00 },452	{ 0x0901, 0x11 },453	{ 0x0902, 0x0a },454	{ 0x3140, 0x02 },455	{ 0x3141, 0x00 },456	{ 0x3f0d, 0x0a },457	{ 0x3f14, 0x01 },458	{ 0x3f3c, 0x01 },459	{ 0x3f4d, 0x01 },460	{ 0x3f4c, 0x01 },461	{ 0x4254, 0x7f },462	{ 0x0401, 0x00 },463	{ 0x0404, 0x00 },464	{ 0x0405, 0x10 },465	{ 0x0408, 0x00 },466	{ 0x0409, 0x00 },467	{ 0x040a, 0x00 },468	{ 0x040b, 0x00 },469	{ 0x040c, 0x0c },470	{ 0x040d, 0xd0 },471	{ 0x040e, 0x09 },472	{ 0x040f, 0xa0 },473	{ 0x034c, 0x0c },474	{ 0x034d, 0xd0 },475	{ 0x034e, 0x09 },476	{ 0x034f, 0xa0 },477	{ 0x3261, 0x00 },478	{ 0x3264, 0x00 },479	{ 0x3265, 0x10 },480	{ 0x0301, 0x05 },481	{ 0x0303, 0x04 },482	{ 0x0305, 0x04 },483	{ 0x0306, 0x01 },484	{ 0x0307, 0x92 },485	{ 0x0309, 0x0a },486	{ 0x030b, 0x02 },487	{ 0x030d, 0x02 },488	{ 0x030e, 0x00 },489	{ 0x030f, 0xfa },490	{ 0x0310, 0x00 },491	{ 0x0820, 0x0f },492	{ 0x0821, 0x13 },493	{ 0x0822, 0x33 },494	{ 0x0823, 0x33 },495	{ 0x3e20, 0x01 },496	{ 0x3e37, 0x00 },497	{ 0x3e3b, 0x01 },498	{ 0x38a3, 0x01 },499	{ 0x38a8, 0x00 },500	{ 0x38a9, 0x00 },501	{ 0x38aa, 0x00 },502	{ 0x38ab, 0x00 },503	{ 0x3234, 0x00 },504	{ 0x3fc1, 0x00 },505	{ 0x3235, 0x00 },506	{ 0x3802, 0x00 },507	{ 0x3143, 0x04 },508	{ 0x360a, 0x00 },509	{ 0x0b00, 0x00 },510	{ 0x0106, 0x00 },511	{ 0x0b05, 0x01 },512	{ 0x0b06, 0x01 },513	{ 0x3230, 0x00 },514	{ 0x3602, 0x01 },515	{ 0x3607, 0x01 },516	{ 0x3c00, 0x00 },517	{ 0x3c01, 0x48 },518	{ 0x3c02, 0xc8 },519	{ 0x3c03, 0xaa },520	{ 0x3c04, 0x91 },521	{ 0x3c05, 0x54 },522	{ 0x3c06, 0x26 },523	{ 0x3c07, 0x20 },524	{ 0x3c08, 0x51 },525	{ 0x3d80, 0x00 },526	{ 0x3f50, 0x00 },527	{ 0x3f56, 0x00 },528	{ 0x3f57, 0x30 },529	{ 0x3f78, 0x01 },530	{ 0x3f79, 0x18 },531	{ 0x3f7c, 0x00 },532	{ 0x3f7d, 0x00 },533	{ 0x3fba, 0x00 },534	{ 0x3fbb, 0x00 },535	{ 0xa081, 0x00 },536	{ 0xe014, 0x00 },537	{ 0x0202, 0x0a },538	{ 0x0203, 0x7a },539	{ 0x0224, 0x01 },540	{ 0x0225, 0xf4 },541	{ 0x0204, 0x00 },542	{ 0x0205, 0x00 },543	{ 0x0216, 0x00 },544	{ 0x0217, 0x00 },545	{ 0x020e, 0x01 },546	{ 0x020f, 0x00 },547	{ 0x0210, 0x01 },548	{ 0x0211, 0x00 },549	{ 0x0212, 0x01 },550	{ 0x0213, 0x00 },551	{ 0x0214, 0x01 },552	{ 0x0215, 0x00 },553	{ 0x0218, 0x01 },554	{ 0x0219, 0x00 },555	{ 0x3614, 0x00 },556	{ 0x3616, 0x0d },557	{ 0x3617, 0x56 },558	{ 0xb612, 0x20 },559	{ 0xb613, 0x20 },560	{ 0xb614, 0x20 },561	{ 0xb615, 0x20 },562	{ 0xb616, 0x0a },563	{ 0xb617, 0x0a },564	{ 0xb618, 0x20 },565	{ 0xb619, 0x20 },566	{ 0xb61a, 0x20 },567	{ 0xb61b, 0x20 },568	{ 0xb61c, 0x0a },569	{ 0xb61d, 0x0a },570	{ 0xb666, 0x30 },571	{ 0xb667, 0x30 },572	{ 0xb668, 0x30 },573	{ 0xb669, 0x30 },574	{ 0xb66a, 0x14 },575	{ 0xb66b, 0x14 },576	{ 0xb66c, 0x20 },577	{ 0xb66d, 0x20 },578	{ 0xb66e, 0x20 },579	{ 0xb66f, 0x20 },580	{ 0xb670, 0x10 },581	{ 0xb671, 0x10 },582	{ 0x3237, 0x00 },583	{ 0x3900, 0x00 },584	{ 0x3901, 0x00 },585	{ 0x3902, 0x00 },586	{ 0x3904, 0x00 },587	{ 0x3905, 0x00 },588	{ 0x3906, 0x00 },589	{ 0x3907, 0x00 },590	{ 0x3908, 0x00 },591	{ 0x3909, 0x00 },592	{ 0x3912, 0x00 },593	{ 0x3930, 0x00 },594	{ 0x3931, 0x00 },595	{ 0x3933, 0x00 },596	{ 0x3934, 0x00 },597	{ 0x3935, 0x00 },598	{ 0x3936, 0x00 },599	{ 0x3937, 0x00 },600	{ 0x30ac, 0x00 },601};602 603static const struct imx319_reg mode_1936x1096_regs[] = {604	{ 0x0112, 0x0a },605	{ 0x0113, 0x0a },606	{ 0x0114, 0x03 },607	{ 0x0342, 0x0f },608	{ 0x0343, 0x80 },609	{ 0x0340, 0x0c },610	{ 0x0341, 0xaa },611	{ 0x0344, 0x00 },612	{ 0x0345, 0x00 },613	{ 0x0346, 0x02 },614	{ 0x0347, 0xac },615	{ 0x0348, 0x0c },616	{ 0x0349, 0xcf },617	{ 0x034a, 0x06 },618	{ 0x034b, 0xf3 },619	{ 0x0220, 0x00 },620	{ 0x0221, 0x11 },621	{ 0x0381, 0x01 },622	{ 0x0383, 0x01 },623	{ 0x0385, 0x01 },624	{ 0x0387, 0x01 },625	{ 0x0900, 0x00 },626	{ 0x0901, 0x11 },627	{ 0x0902, 0x0a },628	{ 0x3140, 0x02 },629	{ 0x3141, 0x00 },630	{ 0x3f0d, 0x0a },631	{ 0x3f14, 0x01 },632	{ 0x3f3c, 0x01 },633	{ 0x3f4d, 0x01 },634	{ 0x3f4c, 0x01 },635	{ 0x4254, 0x7f },636	{ 0x0401, 0x00 },637	{ 0x0404, 0x00 },638	{ 0x0405, 0x10 },639	{ 0x0408, 0x02 },640	{ 0x0409, 0xa0 },641	{ 0x040a, 0x00 },642	{ 0x040b, 0x00 },643	{ 0x040c, 0x07 },644	{ 0x040d, 0x90 },645	{ 0x040e, 0x04 },646	{ 0x040f, 0x48 },647	{ 0x034c, 0x07 },648	{ 0x034d, 0x90 },649	{ 0x034e, 0x04 },650	{ 0x034f, 0x48 },651	{ 0x3261, 0x00 },652	{ 0x3264, 0x00 },653	{ 0x3265, 0x10 },654	{ 0x0301, 0x05 },655	{ 0x0303, 0x04 },656	{ 0x0305, 0x04 },657	{ 0x0306, 0x01 },658	{ 0x0307, 0x92 },659	{ 0x0309, 0x0a },660	{ 0x030b, 0x02 },661	{ 0x030d, 0x02 },662	{ 0x030e, 0x00 },663	{ 0x030f, 0xfa },664	{ 0x0310, 0x00 },665	{ 0x0820, 0x0f },666	{ 0x0821, 0x13 },667	{ 0x0822, 0x33 },668	{ 0x0823, 0x33 },669	{ 0x3e20, 0x01 },670	{ 0x3e37, 0x00 },671	{ 0x3e3b, 0x01 },672	{ 0x38a3, 0x01 },673	{ 0x38a8, 0x00 },674	{ 0x38a9, 0x00 },675	{ 0x38aa, 0x00 },676	{ 0x38ab, 0x00 },677	{ 0x3234, 0x00 },678	{ 0x3fc1, 0x00 },679	{ 0x3235, 0x00 },680	{ 0x3802, 0x00 },681	{ 0x3143, 0x04 },682	{ 0x360a, 0x00 },683	{ 0x0b00, 0x00 },684	{ 0x0106, 0x00 },685	{ 0x0b05, 0x01 },686	{ 0x0b06, 0x01 },687	{ 0x3230, 0x00 },688	{ 0x3602, 0x01 },689	{ 0x3607, 0x01 },690	{ 0x3c00, 0x00 },691	{ 0x3c01, 0x48 },692	{ 0x3c02, 0xc8 },693	{ 0x3c03, 0xaa },694	{ 0x3c04, 0x91 },695	{ 0x3c05, 0x54 },696	{ 0x3c06, 0x26 },697	{ 0x3c07, 0x20 },698	{ 0x3c08, 0x51 },699	{ 0x3d80, 0x00 },700	{ 0x3f50, 0x00 },701	{ 0x3f56, 0x00 },702	{ 0x3f57, 0x30 },703	{ 0x3f78, 0x01 },704	{ 0x3f79, 0x18 },705	{ 0x3f7c, 0x00 },706	{ 0x3f7d, 0x00 },707	{ 0x3fba, 0x00 },708	{ 0x3fbb, 0x00 },709	{ 0xa081, 0x00 },710	{ 0xe014, 0x00 },711	{ 0x0202, 0x05 },712	{ 0x0203, 0x34 },713	{ 0x0224, 0x01 },714	{ 0x0225, 0xf4 },715	{ 0x0204, 0x00 },716	{ 0x0205, 0x00 },717	{ 0x0216, 0x00 },718	{ 0x0217, 0x00 },719	{ 0x020e, 0x01 },720	{ 0x020f, 0x00 },721	{ 0x0210, 0x01 },722	{ 0x0211, 0x00 },723	{ 0x0212, 0x01 },724	{ 0x0213, 0x00 },725	{ 0x0214, 0x01 },726	{ 0x0215, 0x00 },727	{ 0x0218, 0x01 },728	{ 0x0219, 0x00 },729	{ 0x3614, 0x00 },730	{ 0x3616, 0x0d },731	{ 0x3617, 0x56 },732	{ 0xb612, 0x20 },733	{ 0xb613, 0x20 },734	{ 0xb614, 0x20 },735	{ 0xb615, 0x20 },736	{ 0xb616, 0x0a },737	{ 0xb617, 0x0a },738	{ 0xb618, 0x20 },739	{ 0xb619, 0x20 },740	{ 0xb61a, 0x20 },741	{ 0xb61b, 0x20 },742	{ 0xb61c, 0x0a },743	{ 0xb61d, 0x0a },744	{ 0xb666, 0x30 },745	{ 0xb667, 0x30 },746	{ 0xb668, 0x30 },747	{ 0xb669, 0x30 },748	{ 0xb66a, 0x14 },749	{ 0xb66b, 0x14 },750	{ 0xb66c, 0x20 },751	{ 0xb66d, 0x20 },752	{ 0xb66e, 0x20 },753	{ 0xb66f, 0x20 },754	{ 0xb670, 0x10 },755	{ 0xb671, 0x10 },756	{ 0x3237, 0x00 },757	{ 0x3900, 0x00 },758	{ 0x3901, 0x00 },759	{ 0x3902, 0x00 },760	{ 0x3904, 0x00 },761	{ 0x3905, 0x00 },762	{ 0x3906, 0x00 },763	{ 0x3907, 0x00 },764	{ 0x3908, 0x00 },765	{ 0x3909, 0x00 },766	{ 0x3912, 0x00 },767	{ 0x3930, 0x00 },768	{ 0x3931, 0x00 },769	{ 0x3933, 0x00 },770	{ 0x3934, 0x00 },771	{ 0x3935, 0x00 },772	{ 0x3936, 0x00 },773	{ 0x3937, 0x00 },774	{ 0x30ac, 0x00 },775};776 777static const struct imx319_reg mode_1920x1080_regs[] = {778	{ 0x0112, 0x0a },779	{ 0x0113, 0x0a },780	{ 0x0114, 0x03 },781	{ 0x0342, 0x0f },782	{ 0x0343, 0x80 },783	{ 0x0340, 0x0c },784	{ 0x0341, 0xaa },785	{ 0x0344, 0x00 },786	{ 0x0345, 0x00 },787	{ 0x0346, 0x02 },788	{ 0x0347, 0xb4 },789	{ 0x0348, 0x0c },790	{ 0x0349, 0xcf },791	{ 0x034a, 0x06 },792	{ 0x034b, 0xeb },793	{ 0x0220, 0x00 },794	{ 0x0221, 0x11 },795	{ 0x0381, 0x01 },796	{ 0x0383, 0x01 },797	{ 0x0385, 0x01 },798	{ 0x0387, 0x01 },799	{ 0x0900, 0x00 },800	{ 0x0901, 0x11 },801	{ 0x0902, 0x0a },802	{ 0x3140, 0x02 },803	{ 0x3141, 0x00 },804	{ 0x3f0d, 0x0a },805	{ 0x3f14, 0x01 },806	{ 0x3f3c, 0x01 },807	{ 0x3f4d, 0x01 },808	{ 0x3f4c, 0x01 },809	{ 0x4254, 0x7f },810	{ 0x0401, 0x00 },811	{ 0x0404, 0x00 },812	{ 0x0405, 0x10 },813	{ 0x0408, 0x02 },814	{ 0x0409, 0xa8 },815	{ 0x040a, 0x00 },816	{ 0x040b, 0x00 },817	{ 0x040c, 0x07 },818	{ 0x040d, 0x80 },819	{ 0x040e, 0x04 },820	{ 0x040f, 0x38 },821	{ 0x034c, 0x07 },822	{ 0x034d, 0x80 },823	{ 0x034e, 0x04 },824	{ 0x034f, 0x38 },825	{ 0x3261, 0x00 },826	{ 0x3264, 0x00 },827	{ 0x3265, 0x10 },828	{ 0x0301, 0x05 },829	{ 0x0303, 0x04 },830	{ 0x0305, 0x04 },831	{ 0x0306, 0x01 },832	{ 0x0307, 0x92 },833	{ 0x0309, 0x0a },834	{ 0x030b, 0x02 },835	{ 0x030d, 0x02 },836	{ 0x030e, 0x00 },837	{ 0x030f, 0xfa },838	{ 0x0310, 0x00 },839	{ 0x0820, 0x0f },840	{ 0x0821, 0x13 },841	{ 0x0822, 0x33 },842	{ 0x0823, 0x33 },843	{ 0x3e20, 0x01 },844	{ 0x3e37, 0x00 },845	{ 0x3e3b, 0x01 },846	{ 0x38a3, 0x01 },847	{ 0x38a8, 0x00 },848	{ 0x38a9, 0x00 },849	{ 0x38aa, 0x00 },850	{ 0x38ab, 0x00 },851	{ 0x3234, 0x00 },852	{ 0x3fc1, 0x00 },853	{ 0x3235, 0x00 },854	{ 0x3802, 0x00 },855	{ 0x3143, 0x04 },856	{ 0x360a, 0x00 },857	{ 0x0b00, 0x00 },858	{ 0x0106, 0x00 },859	{ 0x0b05, 0x01 },860	{ 0x0b06, 0x01 },861	{ 0x3230, 0x00 },862	{ 0x3602, 0x01 },863	{ 0x3607, 0x01 },864	{ 0x3c00, 0x00 },865	{ 0x3c01, 0x48 },866	{ 0x3c02, 0xc8 },867	{ 0x3c03, 0xaa },868	{ 0x3c04, 0x91 },869	{ 0x3c05, 0x54 },870	{ 0x3c06, 0x26 },871	{ 0x3c07, 0x20 },872	{ 0x3c08, 0x51 },873	{ 0x3d80, 0x00 },874	{ 0x3f50, 0x00 },875	{ 0x3f56, 0x00 },876	{ 0x3f57, 0x30 },877	{ 0x3f78, 0x01 },878	{ 0x3f79, 0x18 },879	{ 0x3f7c, 0x00 },880	{ 0x3f7d, 0x00 },881	{ 0x3fba, 0x00 },882	{ 0x3fbb, 0x00 },883	{ 0xa081, 0x00 },884	{ 0xe014, 0x00 },885	{ 0x0202, 0x05 },886	{ 0x0203, 0x34 },887	{ 0x0224, 0x01 },888	{ 0x0225, 0xf4 },889	{ 0x0204, 0x00 },890	{ 0x0205, 0x00 },891	{ 0x0216, 0x00 },892	{ 0x0217, 0x00 },893	{ 0x020e, 0x01 },894	{ 0x020f, 0x00 },895	{ 0x0210, 0x01 },896	{ 0x0211, 0x00 },897	{ 0x0212, 0x01 },898	{ 0x0213, 0x00 },899	{ 0x0214, 0x01 },900	{ 0x0215, 0x00 },901	{ 0x0218, 0x01 },902	{ 0x0219, 0x00 },903	{ 0x3614, 0x00 },904	{ 0x3616, 0x0d },905	{ 0x3617, 0x56 },906	{ 0xb612, 0x20 },907	{ 0xb613, 0x20 },908	{ 0xb614, 0x20 },909	{ 0xb615, 0x20 },910	{ 0xb616, 0x0a },911	{ 0xb617, 0x0a },912	{ 0xb618, 0x20 },913	{ 0xb619, 0x20 },914	{ 0xb61a, 0x20 },915	{ 0xb61b, 0x20 },916	{ 0xb61c, 0x0a },917	{ 0xb61d, 0x0a },918	{ 0xb666, 0x30 },919	{ 0xb667, 0x30 },920	{ 0xb668, 0x30 },921	{ 0xb669, 0x30 },922	{ 0xb66a, 0x14 },923	{ 0xb66b, 0x14 },924	{ 0xb66c, 0x20 },925	{ 0xb66d, 0x20 },926	{ 0xb66e, 0x20 },927	{ 0xb66f, 0x20 },928	{ 0xb670, 0x10 },929	{ 0xb671, 0x10 },930	{ 0x3237, 0x00 },931	{ 0x3900, 0x00 },932	{ 0x3901, 0x00 },933	{ 0x3902, 0x00 },934	{ 0x3904, 0x00 },935	{ 0x3905, 0x00 },936	{ 0x3906, 0x00 },937	{ 0x3907, 0x00 },938	{ 0x3908, 0x00 },939	{ 0x3909, 0x00 },940	{ 0x3912, 0x00 },941	{ 0x3930, 0x00 },942	{ 0x3931, 0x00 },943	{ 0x3933, 0x00 },944	{ 0x3934, 0x00 },945	{ 0x3935, 0x00 },946	{ 0x3936, 0x00 },947	{ 0x3937, 0x00 },948	{ 0x30ac, 0x00 },949};950 951static const struct imx319_reg mode_1640x1232_regs[] = {952	{ 0x0112, 0x0a },953	{ 0x0113, 0x0a },954	{ 0x0114, 0x03 },955	{ 0x0342, 0x08 },956	{ 0x0343, 0x20 },957	{ 0x0340, 0x18 },958	{ 0x0341, 0x2a },959	{ 0x0344, 0x00 },960	{ 0x0345, 0x00 },961	{ 0x0346, 0x00 },962	{ 0x0347, 0x00 },963	{ 0x0348, 0x0c },964	{ 0x0349, 0xcf },965	{ 0x034a, 0x09 },966	{ 0x034b, 0x9f },967	{ 0x0220, 0x00 },968	{ 0x0221, 0x11 },969	{ 0x0381, 0x01 },970	{ 0x0383, 0x01 },971	{ 0x0385, 0x01 },972	{ 0x0387, 0x01 },973	{ 0x0900, 0x01 },974	{ 0x0901, 0x22 },975	{ 0x0902, 0x0a },976	{ 0x3140, 0x02 },977	{ 0x3141, 0x00 },978	{ 0x3f0d, 0x0a },979	{ 0x3f14, 0x01 },980	{ 0x3f3c, 0x02 },981	{ 0x3f4d, 0x01 },982	{ 0x3f4c, 0x01 },983	{ 0x4254, 0x7f },984	{ 0x0401, 0x00 },985	{ 0x0404, 0x00 },986	{ 0x0405, 0x10 },987	{ 0x0408, 0x00 },988	{ 0x0409, 0x00 },989	{ 0x040a, 0x00 },990	{ 0x040b, 0x00 },991	{ 0x040c, 0x06 },992	{ 0x040d, 0x68 },993	{ 0x040e, 0x04 },994	{ 0x040f, 0xd0 },995	{ 0x034c, 0x06 },996	{ 0x034d, 0x68 },997	{ 0x034e, 0x04 },998	{ 0x034f, 0xd0 },999	{ 0x3261, 0x00 },1000	{ 0x3264, 0x00 },1001	{ 0x3265, 0x10 },1002	{ 0x0301, 0x05 },1003	{ 0x0303, 0x04 },1004	{ 0x0305, 0x04 },1005	{ 0x0306, 0x01 },1006	{ 0x0307, 0x92 },1007	{ 0x0309, 0x0a },1008	{ 0x030b, 0x02 },1009	{ 0x030d, 0x02 },1010	{ 0x030e, 0x00 },1011	{ 0x030f, 0xfa },1012	{ 0x0310, 0x00 },1013	{ 0x0820, 0x0f },1014	{ 0x0821, 0x13 },1015	{ 0x0822, 0x33 },1016	{ 0x0823, 0x33 },1017	{ 0x3e20, 0x01 },1018	{ 0x3e37, 0x00 },1019	{ 0x3e3b, 0x01 },1020	{ 0x38a3, 0x01 },1021	{ 0x38a8, 0x00 },1022	{ 0x38a9, 0x00 },1023	{ 0x38aa, 0x00 },1024	{ 0x38ab, 0x00 },1025	{ 0x3234, 0x00 },1026	{ 0x3fc1, 0x00 },1027	{ 0x3235, 0x00 },1028	{ 0x3802, 0x00 },1029	{ 0x3143, 0x04 },1030	{ 0x360a, 0x00 },1031	{ 0x0b00, 0x00 },1032	{ 0x0106, 0x00 },1033	{ 0x0b05, 0x01 },1034	{ 0x0b06, 0x01 },1035	{ 0x3230, 0x00 },1036	{ 0x3602, 0x01 },1037	{ 0x3607, 0x01 },1038	{ 0x3c00, 0x00 },1039	{ 0x3c01, 0xba },1040	{ 0x3c02, 0xc8 },1041	{ 0x3c03, 0xaa },1042	{ 0x3c04, 0x91 },1043	{ 0x3c05, 0x54 },1044	{ 0x3c06, 0x26 },1045	{ 0x3c07, 0x20 },1046	{ 0x3c08, 0x51 },1047	{ 0x3d80, 0x00 },1048	{ 0x3f50, 0x00 },1049	{ 0x3f56, 0x00 },1050	{ 0x3f57, 0x30 },1051	{ 0x3f78, 0x00 },1052	{ 0x3f79, 0x34 },1053	{ 0x3f7c, 0x00 },1054	{ 0x3f7d, 0x00 },1055	{ 0x3fba, 0x00 },1056	{ 0x3fbb, 0x00 },1057	{ 0xa081, 0x04 },1058	{ 0xe014, 0x00 },1059	{ 0x0202, 0x04 },1060	{ 0x0203, 0xf6 },1061	{ 0x0224, 0x01 },1062	{ 0x0225, 0xf4 },1063	{ 0x0204, 0x00 },1064	{ 0x0205, 0x00 },1065	{ 0x0216, 0x00 },1066	{ 0x0217, 0x00 },1067	{ 0x020e, 0x01 },1068	{ 0x020f, 0x00 },1069	{ 0x0210, 0x01 },1070	{ 0x0211, 0x00 },1071	{ 0x0212, 0x01 },1072	{ 0x0213, 0x00 },1073	{ 0x0214, 0x01 },1074	{ 0x0215, 0x00 },1075	{ 0x0218, 0x01 },1076	{ 0x0219, 0x00 },1077	{ 0x3614, 0x00 },1078	{ 0x3616, 0x0d },1079	{ 0x3617, 0x56 },1080	{ 0xb612, 0x20 },1081	{ 0xb613, 0x20 },1082	{ 0xb614, 0x20 },1083	{ 0xb615, 0x20 },1084	{ 0xb616, 0x0a },1085	{ 0xb617, 0x0a },1086	{ 0xb618, 0x20 },1087	{ 0xb619, 0x20 },1088	{ 0xb61a, 0x20 },1089	{ 0xb61b, 0x20 },1090	{ 0xb61c, 0x0a },1091	{ 0xb61d, 0x0a },1092	{ 0xb666, 0x30 },1093	{ 0xb667, 0x30 },1094	{ 0xb668, 0x30 },1095	{ 0xb669, 0x30 },1096	{ 0xb66a, 0x14 },1097	{ 0xb66b, 0x14 },1098	{ 0xb66c, 0x20 },1099	{ 0xb66d, 0x20 },1100	{ 0xb66e, 0x20 },1101	{ 0xb66f, 0x20 },1102	{ 0xb670, 0x10 },1103	{ 0xb671, 0x10 },1104	{ 0x3237, 0x00 },1105	{ 0x3900, 0x00 },1106	{ 0x3901, 0x00 },1107	{ 0x3902, 0x00 },1108	{ 0x3904, 0x00 },1109	{ 0x3905, 0x00 },1110	{ 0x3906, 0x00 },1111	{ 0x3907, 0x00 },1112	{ 0x3908, 0x00 },1113	{ 0x3909, 0x00 },1114	{ 0x3912, 0x00 },1115	{ 0x3930, 0x00 },1116	{ 0x3931, 0x00 },1117	{ 0x3933, 0x00 },1118	{ 0x3934, 0x00 },1119	{ 0x3935, 0x00 },1120	{ 0x3936, 0x00 },1121	{ 0x3937, 0x00 },1122	{ 0x30ac, 0x00 },1123};1124 1125static const struct imx319_reg mode_1640x922_regs[] = {1126	{ 0x0112, 0x0a },1127	{ 0x0113, 0x0a },1128	{ 0x0114, 0x03 },1129	{ 0x0342, 0x08 },1130	{ 0x0343, 0x20 },1131	{ 0x0340, 0x18 },1132	{ 0x0341, 0x2a },1133	{ 0x0344, 0x00 },1134	{ 0x0345, 0x00 },1135	{ 0x0346, 0x01 },1136	{ 0x0347, 0x30 },1137	{ 0x0348, 0x0c },1138	{ 0x0349, 0xcf },1139	{ 0x034a, 0x08 },1140	{ 0x034b, 0x6f },1141	{ 0x0220, 0x00 },1142	{ 0x0221, 0x11 },1143	{ 0x0381, 0x01 },1144	{ 0x0383, 0x01 },1145	{ 0x0385, 0x01 },1146	{ 0x0387, 0x01 },1147	{ 0x0900, 0x01 },1148	{ 0x0901, 0x22 },1149	{ 0x0902, 0x0a },1150	{ 0x3140, 0x02 },1151	{ 0x3141, 0x00 },1152	{ 0x3f0d, 0x0a },1153	{ 0x3f14, 0x01 },1154	{ 0x3f3c, 0x02 },1155	{ 0x3f4d, 0x01 },1156	{ 0x3f4c, 0x01 },1157	{ 0x4254, 0x7f },1158	{ 0x0401, 0x00 },1159	{ 0x0404, 0x00 },1160	{ 0x0405, 0x10 },1161	{ 0x0408, 0x00 },1162	{ 0x0409, 0x00 },1163	{ 0x040a, 0x00 },1164	{ 0x040b, 0x02 },1165	{ 0x040c, 0x06 },1166	{ 0x040d, 0x68 },1167	{ 0x040e, 0x03 },1168	{ 0x040f, 0x9a },1169	{ 0x034c, 0x06 },1170	{ 0x034d, 0x68 },1171	{ 0x034e, 0x03 },1172	{ 0x034f, 0x9a },1173	{ 0x3261, 0x00 },1174	{ 0x3264, 0x00 },1175	{ 0x3265, 0x10 },1176	{ 0x0301, 0x05 },1177	{ 0x0303, 0x04 },1178	{ 0x0305, 0x04 },1179	{ 0x0306, 0x01 },1180	{ 0x0307, 0x92 },1181	{ 0x0309, 0x0a },1182	{ 0x030b, 0x02 },1183	{ 0x030d, 0x02 },1184	{ 0x030e, 0x00 },1185	{ 0x030f, 0xfa },1186	{ 0x0310, 0x00 },1187	{ 0x0820, 0x0f },1188	{ 0x0821, 0x13 },1189	{ 0x0822, 0x33 },1190	{ 0x0823, 0x33 },1191	{ 0x3e20, 0x01 },1192	{ 0x3e37, 0x00 },1193	{ 0x3e3b, 0x01 },1194	{ 0x38a3, 0x01 },1195	{ 0x38a8, 0x00 },1196	{ 0x38a9, 0x00 },1197	{ 0x38aa, 0x00 },1198	{ 0x38ab, 0x00 },1199	{ 0x3234, 0x00 },1200	{ 0x3fc1, 0x00 },1201	{ 0x3235, 0x00 },1202	{ 0x3802, 0x00 },1203	{ 0x3143, 0x04 },1204	{ 0x360a, 0x00 },1205	{ 0x0b00, 0x00 },1206	{ 0x0106, 0x00 },1207	{ 0x0b05, 0x01 },1208	{ 0x0b06, 0x01 },1209	{ 0x3230, 0x00 },1210	{ 0x3602, 0x01 },1211	{ 0x3607, 0x01 },1212	{ 0x3c00, 0x00 },1213	{ 0x3c01, 0xba },1214	{ 0x3c02, 0xc8 },1215	{ 0x3c03, 0xaa },1216	{ 0x3c04, 0x91 },1217	{ 0x3c05, 0x54 },1218	{ 0x3c06, 0x26 },1219	{ 0x3c07, 0x20 },1220	{ 0x3c08, 0x51 },1221	{ 0x3d80, 0x00 },1222	{ 0x3f50, 0x00 },1223	{ 0x3f56, 0x00 },1224	{ 0x3f57, 0x30 },1225	{ 0x3f78, 0x00 },1226	{ 0x3f79, 0x34 },1227	{ 0x3f7c, 0x00 },1228	{ 0x3f7d, 0x00 },1229	{ 0x3fba, 0x00 },1230	{ 0x3fbb, 0x00 },1231	{ 0xa081, 0x04 },1232	{ 0xe014, 0x00 },1233	{ 0x0202, 0x04 },1234	{ 0x0203, 0xf6 },1235	{ 0x0224, 0x01 },1236	{ 0x0225, 0xf4 },1237	{ 0x0204, 0x00 },1238	{ 0x0205, 0x00 },1239	{ 0x0216, 0x00 },1240	{ 0x0217, 0x00 },1241	{ 0x020e, 0x01 },1242	{ 0x020f, 0x00 },1243	{ 0x0210, 0x01 },1244	{ 0x0211, 0x00 },1245	{ 0x0212, 0x01 },1246	{ 0x0213, 0x00 },1247	{ 0x0214, 0x01 },1248	{ 0x0215, 0x00 },1249	{ 0x0218, 0x01 },1250	{ 0x0219, 0x00 },1251	{ 0x3614, 0x00 },1252	{ 0x3616, 0x0d },1253	{ 0x3617, 0x56 },1254	{ 0xb612, 0x20 },1255	{ 0xb613, 0x20 },1256	{ 0xb614, 0x20 },1257	{ 0xb615, 0x20 },1258	{ 0xb616, 0x0a },1259	{ 0xb617, 0x0a },1260	{ 0xb618, 0x20 },1261	{ 0xb619, 0x20 },1262	{ 0xb61a, 0x20 },1263	{ 0xb61b, 0x20 },1264	{ 0xb61c, 0x0a },1265	{ 0xb61d, 0x0a },1266	{ 0xb666, 0x30 },1267	{ 0xb667, 0x30 },1268	{ 0xb668, 0x30 },1269	{ 0xb669, 0x30 },1270	{ 0xb66a, 0x14 },1271	{ 0xb66b, 0x14 },1272	{ 0xb66c, 0x20 },1273	{ 0xb66d, 0x20 },1274	{ 0xb66e, 0x20 },1275	{ 0xb66f, 0x20 },1276	{ 0xb670, 0x10 },1277	{ 0xb671, 0x10 },1278	{ 0x3237, 0x00 },1279	{ 0x3900, 0x00 },1280	{ 0x3901, 0x00 },1281	{ 0x3902, 0x00 },1282	{ 0x3904, 0x00 },1283	{ 0x3905, 0x00 },1284	{ 0x3906, 0x00 },1285	{ 0x3907, 0x00 },1286	{ 0x3908, 0x00 },1287	{ 0x3909, 0x00 },1288	{ 0x3912, 0x00 },1289	{ 0x3930, 0x00 },1290	{ 0x3931, 0x00 },1291	{ 0x3933, 0x00 },1292	{ 0x3934, 0x00 },1293	{ 0x3935, 0x00 },1294	{ 0x3936, 0x00 },1295	{ 0x3937, 0x00 },1296	{ 0x30ac, 0x00 },1297};1298 1299static const struct imx319_reg mode_1296x736_regs[] = {1300	{ 0x0112, 0x0a },1301	{ 0x0113, 0x0a },1302	{ 0x0114, 0x03 },1303	{ 0x0342, 0x08 },1304	{ 0x0343, 0x20 },1305	{ 0x0340, 0x18 },1306	{ 0x0341, 0x2a },1307	{ 0x0344, 0x00 },1308	{ 0x0345, 0x00 },1309	{ 0x0346, 0x01 },1310	{ 0x0347, 0xf0 },1311	{ 0x0348, 0x0c },1312	{ 0x0349, 0xcf },1313	{ 0x034a, 0x07 },1314	{ 0x034b, 0xaf },1315	{ 0x0220, 0x00 },1316	{ 0x0221, 0x11 },1317	{ 0x0381, 0x01 },1318	{ 0x0383, 0x01 },1319	{ 0x0385, 0x01 },1320	{ 0x0387, 0x01 },1321	{ 0x0900, 0x01 },1322	{ 0x0901, 0x22 },1323	{ 0x0902, 0x0a },1324	{ 0x3140, 0x02 },1325	{ 0x3141, 0x00 },1326	{ 0x3f0d, 0x0a },1327	{ 0x3f14, 0x01 },1328	{ 0x3f3c, 0x02 },1329	{ 0x3f4d, 0x01 },1330	{ 0x3f4c, 0x01 },1331	{ 0x4254, 0x7f },1332	{ 0x0401, 0x00 },1333	{ 0x0404, 0x00 },1334	{ 0x0405, 0x10 },1335	{ 0x0408, 0x00 },1336	{ 0x0409, 0xac },1337	{ 0x040a, 0x00 },1338	{ 0x040b, 0x00 },1339	{ 0x040c, 0x05 },1340	{ 0x040d, 0x10 },1341	{ 0x040e, 0x02 },1342	{ 0x040f, 0xe0 },1343	{ 0x034c, 0x05 },1344	{ 0x034d, 0x10 },1345	{ 0x034e, 0x02 },1346	{ 0x034f, 0xe0 },1347	{ 0x3261, 0x00 },1348	{ 0x3264, 0x00 },1349	{ 0x3265, 0x10 },1350	{ 0x0301, 0x05 },1351	{ 0x0303, 0x04 },1352	{ 0x0305, 0x04 },1353	{ 0x0306, 0x01 },1354	{ 0x0307, 0x92 },1355	{ 0x0309, 0x0a },1356	{ 0x030b, 0x02 },1357	{ 0x030d, 0x02 },1358	{ 0x030e, 0x00 },1359	{ 0x030f, 0xfa },1360	{ 0x0310, 0x00 },1361	{ 0x0820, 0x0f },1362	{ 0x0821, 0x13 },1363	{ 0x0822, 0x33 },1364	{ 0x0823, 0x33 },1365	{ 0x3e20, 0x01 },1366	{ 0x3e37, 0x00 },1367	{ 0x3e3b, 0x01 },1368	{ 0x38a3, 0x01 },1369	{ 0x38a8, 0x00 },1370	{ 0x38a9, 0x00 },1371	{ 0x38aa, 0x00 },1372	{ 0x38ab, 0x00 },1373	{ 0x3234, 0x00 },1374	{ 0x3fc1, 0x00 },1375	{ 0x3235, 0x00 },1376	{ 0x3802, 0x00 },1377	{ 0x3143, 0x04 },1378	{ 0x360a, 0x00 },1379	{ 0x0b00, 0x00 },1380	{ 0x0106, 0x00 },1381	{ 0x0b05, 0x01 },1382	{ 0x0b06, 0x01 },1383	{ 0x3230, 0x00 },1384	{ 0x3602, 0x01 },1385	{ 0x3607, 0x01 },1386	{ 0x3c00, 0x00 },1387	{ 0x3c01, 0xba },1388	{ 0x3c02, 0xc8 },1389	{ 0x3c03, 0xaa },1390	{ 0x3c04, 0x91 },1391	{ 0x3c05, 0x54 },1392	{ 0x3c06, 0x26 },1393	{ 0x3c07, 0x20 },1394	{ 0x3c08, 0x51 },1395	{ 0x3d80, 0x00 },1396	{ 0x3f50, 0x00 },1397	{ 0x3f56, 0x00 },1398	{ 0x3f57, 0x30 },1399	{ 0x3f78, 0x00 },1400	{ 0x3f79, 0x34 },1401	{ 0x3f7c, 0x00 },1402	{ 0x3f7d, 0x00 },1403	{ 0x3fba, 0x00 },1404	{ 0x3fbb, 0x00 },1405	{ 0xa081, 0x04 },1406	{ 0xe014, 0x00 },1407	{ 0x0202, 0x04 },1408	{ 0x0203, 0xf6 },1409	{ 0x0224, 0x01 },1410	{ 0x0225, 0xf4 },1411	{ 0x0204, 0x00 },1412	{ 0x0205, 0x00 },1413	{ 0x0216, 0x00 },1414	{ 0x0217, 0x00 },1415	{ 0x020e, 0x01 },1416	{ 0x020f, 0x00 },1417	{ 0x0210, 0x01 },1418	{ 0x0211, 0x00 },1419	{ 0x0212, 0x01 },1420	{ 0x0213, 0x00 },1421	{ 0x0214, 0x01 },1422	{ 0x0215, 0x00 },1423	{ 0x0218, 0x01 },1424	{ 0x0219, 0x00 },1425	{ 0x3614, 0x00 },1426	{ 0x3616, 0x0d },1427	{ 0x3617, 0x56 },1428	{ 0xb612, 0x20 },1429	{ 0xb613, 0x20 },1430	{ 0xb614, 0x20 },1431	{ 0xb615, 0x20 },1432	{ 0xb616, 0x0a },1433	{ 0xb617, 0x0a },1434	{ 0xb618, 0x20 },1435	{ 0xb619, 0x20 },1436	{ 0xb61a, 0x20 },1437	{ 0xb61b, 0x20 },1438	{ 0xb61c, 0x0a },1439	{ 0xb61d, 0x0a },1440	{ 0xb666, 0x30 },1441	{ 0xb667, 0x30 },1442	{ 0xb668, 0x30 },1443	{ 0xb669, 0x30 },1444	{ 0xb66a, 0x14 },1445	{ 0xb66b, 0x14 },1446	{ 0xb66c, 0x20 },1447	{ 0xb66d, 0x20 },1448	{ 0xb66e, 0x20 },1449	{ 0xb66f, 0x20 },1450	{ 0xb670, 0x10 },1451	{ 0xb671, 0x10 },1452	{ 0x3237, 0x00 },1453	{ 0x3900, 0x00 },1454	{ 0x3901, 0x00 },1455	{ 0x3902, 0x00 },1456	{ 0x3904, 0x00 },1457	{ 0x3905, 0x00 },1458	{ 0x3906, 0x00 },1459	{ 0x3907, 0x00 },1460	{ 0x3908, 0x00 },1461	{ 0x3909, 0x00 },1462	{ 0x3912, 0x00 },1463	{ 0x3930, 0x00 },1464	{ 0x3931, 0x00 },1465	{ 0x3933, 0x00 },1466	{ 0x3934, 0x00 },1467	{ 0x3935, 0x00 },1468	{ 0x3936, 0x00 },1469	{ 0x3937, 0x00 },1470	{ 0x30ac, 0x00 },1471};1472 1473static const struct imx319_reg mode_1280x720_regs[] = {1474	{ 0x0112, 0x0a },1475	{ 0x0113, 0x0a },1476	{ 0x0114, 0x03 },1477	{ 0x0342, 0x08 },1478	{ 0x0343, 0x20 },1479	{ 0x0340, 0x18 },1480	{ 0x0341, 0x2a },1481	{ 0x0344, 0x00 },1482	{ 0x0345, 0x00 },1483	{ 0x0346, 0x02 },1484	{ 0x0347, 0x00 },1485	{ 0x0348, 0x0c },1486	{ 0x0349, 0xcf },1487	{ 0x034a, 0x07 },1488	{ 0x034b, 0x9f },1489	{ 0x0220, 0x00 },1490	{ 0x0221, 0x11 },1491	{ 0x0381, 0x01 },1492	{ 0x0383, 0x01 },1493	{ 0x0385, 0x01 },1494	{ 0x0387, 0x01 },1495	{ 0x0900, 0x01 },1496	{ 0x0901, 0x22 },1497	{ 0x0902, 0x0a },1498	{ 0x3140, 0x02 },1499	{ 0x3141, 0x00 },1500	{ 0x3f0d, 0x0a },1501	{ 0x3f14, 0x01 },1502	{ 0x3f3c, 0x02 },1503	{ 0x3f4d, 0x01 },1504	{ 0x3f4c, 0x01 },1505	{ 0x4254, 0x7f },1506	{ 0x0401, 0x00 },1507	{ 0x0404, 0x00 },1508	{ 0x0405, 0x10 },1509	{ 0x0408, 0x00 },1510	{ 0x0409, 0xb4 },1511	{ 0x040a, 0x00 },1512	{ 0x040b, 0x00 },1513	{ 0x040c, 0x05 },1514	{ 0x040d, 0x00 },1515	{ 0x040e, 0x02 },1516	{ 0x040f, 0xd0 },1517	{ 0x034c, 0x05 },1518	{ 0x034d, 0x00 },1519	{ 0x034e, 0x02 },1520	{ 0x034f, 0xd0 },1521	{ 0x3261, 0x00 },1522	{ 0x3264, 0x00 },1523	{ 0x3265, 0x10 },1524	{ 0x0301, 0x05 },1525	{ 0x0303, 0x04 },1526	{ 0x0305, 0x04 },1527	{ 0x0306, 0x01 },1528	{ 0x0307, 0x92 },1529	{ 0x0309, 0x0a },1530	{ 0x030b, 0x02 },1531	{ 0x030d, 0x02 },1532	{ 0x030e, 0x00 },1533	{ 0x030f, 0xfa },1534	{ 0x0310, 0x00 },1535	{ 0x0820, 0x0f },1536	{ 0x0821, 0x13 },1537	{ 0x0822, 0x33 },1538	{ 0x0823, 0x33 },1539	{ 0x3e20, 0x01 },1540	{ 0x3e37, 0x00 },1541	{ 0x3e3b, 0x01 },1542	{ 0x38a3, 0x01 },1543	{ 0x38a8, 0x00 },1544	{ 0x38a9, 0x00 },1545	{ 0x38aa, 0x00 },1546	{ 0x38ab, 0x00 },1547	{ 0x3234, 0x00 },1548	{ 0x3fc1, 0x00 },1549	{ 0x3235, 0x00 },1550	{ 0x3802, 0x00 },1551	{ 0x3143, 0x04 },1552	{ 0x360a, 0x00 },1553	{ 0x0b00, 0x00 },1554	{ 0x0106, 0x00 },1555	{ 0x0b05, 0x01 },1556	{ 0x0b06, 0x01 },1557	{ 0x3230, 0x00 },1558	{ 0x3602, 0x01 },1559	{ 0x3607, 0x01 },1560	{ 0x3c00, 0x00 },1561	{ 0x3c01, 0xba },1562	{ 0x3c02, 0xc8 },1563	{ 0x3c03, 0xaa },1564	{ 0x3c04, 0x91 },1565	{ 0x3c05, 0x54 },1566	{ 0x3c06, 0x26 },1567	{ 0x3c07, 0x20 },1568	{ 0x3c08, 0x51 },1569	{ 0x3d80, 0x00 },1570	{ 0x3f50, 0x00 },1571	{ 0x3f56, 0x00 },1572	{ 0x3f57, 0x30 },1573	{ 0x3f78, 0x00 },1574	{ 0x3f79, 0x34 },1575	{ 0x3f7c, 0x00 },1576	{ 0x3f7d, 0x00 },1577	{ 0x3fba, 0x00 },1578	{ 0x3fbb, 0x00 },1579	{ 0xa081, 0x04 },1580	{ 0xe014, 0x00 },1581	{ 0x0202, 0x04 },1582	{ 0x0203, 0xf6 },1583	{ 0x0224, 0x01 },1584	{ 0x0225, 0xf4 },1585	{ 0x0204, 0x00 },1586	{ 0x0205, 0x00 },1587	{ 0x0216, 0x00 },1588	{ 0x0217, 0x00 },1589	{ 0x020e, 0x01 },1590	{ 0x020f, 0x00 },1591	{ 0x0210, 0x01 },1592	{ 0x0211, 0x00 },1593	{ 0x0212, 0x01 },1594	{ 0x0213, 0x00 },1595	{ 0x0214, 0x01 },1596	{ 0x0215, 0x00 },1597	{ 0x0218, 0x01 },1598	{ 0x0219, 0x00 },1599	{ 0x3614, 0x00 },1600	{ 0x3616, 0x0d },1601	{ 0x3617, 0x56 },1602	{ 0xb612, 0x20 },1603	{ 0xb613, 0x20 },1604	{ 0xb614, 0x20 },1605	{ 0xb615, 0x20 },1606	{ 0xb616, 0x0a },1607	{ 0xb617, 0x0a },1608	{ 0xb618, 0x20 },1609	{ 0xb619, 0x20 },1610	{ 0xb61a, 0x20 },1611	{ 0xb61b, 0x20 },1612	{ 0xb61c, 0x0a },1613	{ 0xb61d, 0x0a },1614	{ 0xb666, 0x30 },1615	{ 0xb667, 0x30 },1616	{ 0xb668, 0x30 },1617	{ 0xb669, 0x30 },1618	{ 0xb66a, 0x14 },1619	{ 0xb66b, 0x14 },1620	{ 0xb66c, 0x20 },1621	{ 0xb66d, 0x20 },1622	{ 0xb66e, 0x20 },1623	{ 0xb66f, 0x20 },1624	{ 0xb670, 0x10 },1625	{ 0xb671, 0x10 },1626	{ 0x3237, 0x00 },1627	{ 0x3900, 0x00 },1628	{ 0x3901, 0x00 },1629	{ 0x3902, 0x00 },1630	{ 0x3904, 0x00 },1631	{ 0x3905, 0x00 },1632	{ 0x3906, 0x00 },1633	{ 0x3907, 0x00 },1634	{ 0x3908, 0x00 },1635	{ 0x3909, 0x00 },1636	{ 0x3912, 0x00 },1637	{ 0x3930, 0x00 },1638	{ 0x3931, 0x00 },1639	{ 0x3933, 0x00 },1640	{ 0x3934, 0x00 },1641	{ 0x3935, 0x00 },1642	{ 0x3936, 0x00 },1643	{ 0x3937, 0x00 },1644	{ 0x30ac, 0x00 },1645};1646 1647static const char * const imx319_test_pattern_menu[] = {1648	"Disabled",1649	"Solid Colour",1650	"Eight Vertical Colour Bars",1651	"Colour Bars With Fade to Grey",1652	"Pseudorandom Sequence (PN9)",1653};1654 1655/*1656 * When adding more than the one below, make sure the disallowed ones will1657 * actually be disabled in the LINK_FREQ control.1658 */1659static const s64 link_freq_menu_items[] = {1660	IMX319_LINK_FREQ_DEFAULT,1661};1662 1663/* Mode configs */1664static const struct imx319_mode supported_modes[] = {1665	{1666		.width = 3280,1667		.height = 2464,1668		.fll_def = 3242,1669		.fll_min = 3242,1670		.llp = 3968,1671		.link_freq_index = IMX319_LINK_FREQ_INDEX,1672		.reg_list = {1673			.num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),1674			.regs = mode_3280x2464_regs,1675		},1676	},1677	{1678		.width = 3264,1679		.height = 2448,1680		.fll_def = 3242,1681		.fll_min = 3242,1682		.llp = 3968,1683		.link_freq_index = IMX319_LINK_FREQ_INDEX,1684		.reg_list = {1685			.num_of_regs = ARRAY_SIZE(mode_3264x2448_regs),1686			.regs = mode_3264x2448_regs,1687		},1688	},1689	{1690		.width = 1936,1691		.height = 1096,1692		.fll_def = 3242,1693		.fll_min = 3242,1694		.llp = 3968,1695		.link_freq_index = IMX319_LINK_FREQ_INDEX,1696		.reg_list = {1697			.num_of_regs = ARRAY_SIZE(mode_1936x1096_regs),1698			.regs = mode_1936x1096_regs,1699		},1700	},1701	{1702		.width = 1920,1703		.height = 1080,1704		.fll_def = 3242,1705		.fll_min = 3242,1706		.llp = 3968,1707		.link_freq_index = IMX319_LINK_FREQ_INDEX,1708		.reg_list = {1709			.num_of_regs = ARRAY_SIZE(mode_1920x1080_regs),1710			.regs = mode_1920x1080_regs,1711		},1712	},1713	{1714		.width = 1640,1715		.height = 1232,1716		.fll_def = 5146,1717		.fll_min = 5146,1718		.llp = 2500,1719		.link_freq_index = IMX319_LINK_FREQ_INDEX,1720		.reg_list = {1721			.num_of_regs = ARRAY_SIZE(mode_1640x1232_regs),1722			.regs = mode_1640x1232_regs,1723		},1724	},1725	{1726		.width = 1640,1727		.height = 922,1728		.fll_def = 5146,1729		.fll_min = 5146,1730		.llp = 2500,1731		.link_freq_index = IMX319_LINK_FREQ_INDEX,1732		.reg_list = {1733			.num_of_regs = ARRAY_SIZE(mode_1640x922_regs),1734			.regs = mode_1640x922_regs,1735		},1736	},1737	{1738		.width = 1296,1739		.height = 736,1740		.fll_def = 5146,1741		.fll_min = 5146,1742		.llp = 2500,1743		.link_freq_index = IMX319_LINK_FREQ_INDEX,1744		.reg_list = {1745			.num_of_regs = ARRAY_SIZE(mode_1296x736_regs),1746			.regs = mode_1296x736_regs,1747		},1748	},1749	{1750		.width = 1280,1751		.height = 720,1752		.fll_def = 5146,1753		.fll_min = 5146,1754		.llp = 2500,1755		.link_freq_index = IMX319_LINK_FREQ_INDEX,1756		.reg_list = {1757			.num_of_regs = ARRAY_SIZE(mode_1280x720_regs),1758			.regs = mode_1280x720_regs,1759		},1760	},1761};1762 1763static inline struct imx319 *to_imx319(struct v4l2_subdev *_sd)1764{1765	return container_of(_sd, struct imx319, sd);1766}1767 1768/* Get bayer order based on flip setting. */1769static u32 imx319_get_format_code(struct imx319 *imx319)1770{1771	/*1772	 * Only one bayer order is supported.1773	 * It depends on the flip settings.1774	 */1775	u32 code;1776	static const u32 codes[2][2] = {1777		{ MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, },1778		{ MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, },1779	};1780 1781	lockdep_assert_held(&imx319->mutex);1782	code = codes[imx319->vflip->val][imx319->hflip->val];1783 1784	return code;1785}1786 1787/* Read registers up to 4 at a time */1788static int imx319_read_reg(struct imx319 *imx319, u16 reg, u32 len, u32 *val)1789{1790	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);1791	struct i2c_msg msgs[2];1792	u8 addr_buf[2];1793	u8 data_buf[4] = { 0 };1794	int ret;1795 1796	if (len > 4)1797		return -EINVAL;1798 1799	put_unaligned_be16(reg, addr_buf);1800	/* Write register address */1801	msgs[0].addr = client->addr;1802	msgs[0].flags = 0;1803	msgs[0].len = ARRAY_SIZE(addr_buf);1804	msgs[0].buf = addr_buf;1805 1806	/* Read data from register */1807	msgs[1].addr = client->addr;1808	msgs[1].flags = I2C_M_RD;1809	msgs[1].len = len;1810	msgs[1].buf = &data_buf[4 - len];1811 1812	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));1813	if (ret != ARRAY_SIZE(msgs))1814		return -EIO;1815 1816	*val = get_unaligned_be32(data_buf);1817 1818	return 0;1819}1820 1821/* Write registers up to 4 at a time */1822static int imx319_write_reg(struct imx319 *imx319, u16 reg, u32 len, u32 val)1823{1824	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);1825	u8 buf[6];1826 1827	if (len > 4)1828		return -EINVAL;1829 1830	put_unaligned_be16(reg, buf);1831	put_unaligned_be32(val << (8 * (4 - len)), buf + 2);1832	if (i2c_master_send(client, buf, len + 2) != len + 2)1833		return -EIO;1834 1835	return 0;1836}1837 1838/* Write a list of registers */1839static int imx319_write_regs(struct imx319 *imx319,1840			     const struct imx319_reg *regs, u32 len)1841{1842	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);1843	int ret;1844	u32 i;1845 1846	for (i = 0; i < len; i++) {1847		ret = imx319_write_reg(imx319, regs[i].address, 1, regs[i].val);1848		if (ret) {1849			dev_err_ratelimited(&client->dev,1850					    "write reg 0x%4.4x return err %d",1851					    regs[i].address, ret);1852			return ret;1853		}1854	}1855 1856	return 0;1857}1858 1859/* Open sub-device */1860static int imx319_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)1861{1862	struct imx319 *imx319 = to_imx319(sd);1863	struct v4l2_mbus_framefmt *try_fmt =1864		v4l2_subdev_state_get_format(fh->state, 0);1865 1866	mutex_lock(&imx319->mutex);1867 1868	/* Initialize try_fmt */1869	try_fmt->width = imx319->cur_mode->width;1870	try_fmt->height = imx319->cur_mode->height;1871	try_fmt->code = imx319_get_format_code(imx319);1872	try_fmt->field = V4L2_FIELD_NONE;1873 1874	mutex_unlock(&imx319->mutex);1875 1876	return 0;1877}1878 1879static int imx319_set_ctrl(struct v4l2_ctrl *ctrl)1880{1881	struct imx319 *imx319 = container_of(ctrl->handler,1882					     struct imx319, ctrl_handler);1883	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);1884	s64 max;1885	int ret;1886 1887	/* Propagate change of current control to all related controls */1888	switch (ctrl->id) {1889	case V4L2_CID_VBLANK:1890		/* Update max exposure while meeting expected vblanking */1891		max = imx319->cur_mode->height + ctrl->val - 18;1892		__v4l2_ctrl_modify_range(imx319->exposure,1893					 imx319->exposure->minimum,1894					 max, imx319->exposure->step, max);1895		break;1896	}1897 1898	/*1899	 * Applying V4L2 control value only happens1900	 * when power is up for streaming1901	 */1902	if (!pm_runtime_get_if_in_use(&client->dev))1903		return 0;1904 1905	switch (ctrl->id) {1906	case V4L2_CID_ANALOGUE_GAIN:1907		/* Analog gain = 1024/(1024 - ctrl->val) times */1908		ret = imx319_write_reg(imx319, IMX319_REG_ANALOG_GAIN, 2,1909				       ctrl->val);1910		break;1911	case V4L2_CID_DIGITAL_GAIN:1912		ret = imx319_write_reg(imx319, IMX319_REG_DIG_GAIN_GLOBAL, 2,1913				       ctrl->val);1914		break;1915	case V4L2_CID_EXPOSURE:1916		ret = imx319_write_reg(imx319, IMX319_REG_EXPOSURE, 2,1917				       ctrl->val);1918		break;1919	case V4L2_CID_VBLANK:1920		/* Update FLL that meets expected vertical blanking */1921		ret = imx319_write_reg(imx319, IMX319_REG_FLL, 2,1922				       imx319->cur_mode->height + ctrl->val);1923		break;1924	case V4L2_CID_TEST_PATTERN:1925		ret = imx319_write_reg(imx319, IMX319_REG_TEST_PATTERN,1926				       2, ctrl->val);1927		break;1928	case V4L2_CID_HFLIP:1929	case V4L2_CID_VFLIP:1930		ret = imx319_write_reg(imx319, IMX319_REG_ORIENTATION, 1,1931				       imx319->hflip->val |1932				       imx319->vflip->val << 1);1933		break;1934	default:1935		ret = -EINVAL;1936		dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled",1937			 ctrl->id, ctrl->val);1938		break;1939	}1940 1941	pm_runtime_put(&client->dev);1942 1943	return ret;1944}1945 1946static const struct v4l2_ctrl_ops imx319_ctrl_ops = {1947	.s_ctrl = imx319_set_ctrl,1948};1949 1950static int imx319_enum_mbus_code(struct v4l2_subdev *sd,1951				 struct v4l2_subdev_state *sd_state,1952				 struct v4l2_subdev_mbus_code_enum *code)1953{1954	struct imx319 *imx319 = to_imx319(sd);1955 1956	if (code->index > 0)1957		return -EINVAL;1958 1959	mutex_lock(&imx319->mutex);1960	code->code = imx319_get_format_code(imx319);1961	mutex_unlock(&imx319->mutex);1962 1963	return 0;1964}1965 1966static int imx319_enum_frame_size(struct v4l2_subdev *sd,1967				  struct v4l2_subdev_state *sd_state,1968				  struct v4l2_subdev_frame_size_enum *fse)1969{1970	struct imx319 *imx319 = to_imx319(sd);1971 1972	if (fse->index >= ARRAY_SIZE(supported_modes))1973		return -EINVAL;1974 1975	mutex_lock(&imx319->mutex);1976	if (fse->code != imx319_get_format_code(imx319)) {1977		mutex_unlock(&imx319->mutex);1978		return -EINVAL;1979	}1980	mutex_unlock(&imx319->mutex);1981 1982	fse->min_width = supported_modes[fse->index].width;1983	fse->max_width = fse->min_width;1984	fse->min_height = supported_modes[fse->index].height;1985	fse->max_height = fse->min_height;1986 1987	return 0;1988}1989 1990static void imx319_update_pad_format(struct imx319 *imx319,1991				     const struct imx319_mode *mode,1992				     struct v4l2_subdev_format *fmt)1993{1994	fmt->format.width = mode->width;1995	fmt->format.height = mode->height;1996	fmt->format.code = imx319_get_format_code(imx319);1997	fmt->format.field = V4L2_FIELD_NONE;1998}1999 2000static int imx319_do_get_pad_format(struct imx319 *imx319,2001				    struct v4l2_subdev_state *sd_state,2002				    struct v4l2_subdev_format *fmt)2003{2004	struct v4l2_mbus_framefmt *framefmt;2005 2006	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {2007		framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);2008		fmt->format = *framefmt;2009	} else {2010		imx319_update_pad_format(imx319, imx319->cur_mode, fmt);2011	}2012 2013	return 0;2014}2015 2016static int imx319_get_pad_format(struct v4l2_subdev *sd,2017				 struct v4l2_subdev_state *sd_state,2018				 struct v4l2_subdev_format *fmt)2019{2020	struct imx319 *imx319 = to_imx319(sd);2021	int ret;2022 2023	mutex_lock(&imx319->mutex);2024	ret = imx319_do_get_pad_format(imx319, sd_state, fmt);2025	mutex_unlock(&imx319->mutex);2026 2027	return ret;2028}2029 2030static int2031imx319_set_pad_format(struct v4l2_subdev *sd,2032		      struct v4l2_subdev_state *sd_state,2033		      struct v4l2_subdev_format *fmt)2034{2035	struct imx319 *imx319 = to_imx319(sd);2036	const struct imx319_mode *mode;2037	struct v4l2_mbus_framefmt *framefmt;2038	s32 vblank_def;2039	s32 vblank_min;2040	s64 h_blank;2041	u64 pixel_rate;2042	u32 height;2043 2044	mutex_lock(&imx319->mutex);2045 2046	/*2047	 * Only one bayer order is supported.2048	 * It depends on the flip settings.2049	 */2050	fmt->format.code = imx319_get_format_code(imx319);2051 2052	mode = v4l2_find_nearest_size(supported_modes,2053				      ARRAY_SIZE(supported_modes),2054				      width, height,2055				      fmt->format.width, fmt->format.height);2056	imx319_update_pad_format(imx319, mode, fmt);2057	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {2058		framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);2059		*framefmt = fmt->format;2060	} else {2061		imx319->cur_mode = mode;2062		pixel_rate = IMX319_LINK_FREQ_DEFAULT * 2 * 4;2063		do_div(pixel_rate, 10);2064		__v4l2_ctrl_s_ctrl_int64(imx319->pixel_rate, pixel_rate);2065		/* Update limits and set FPS to default */2066		height = imx319->cur_mode->height;2067		vblank_def = imx319->cur_mode->fll_def - height;2068		vblank_min = imx319->cur_mode->fll_min - height;2069		height = IMX319_FLL_MAX - height;2070		__v4l2_ctrl_modify_range(imx319->vblank, vblank_min, height, 1,2071					 vblank_def);2072		__v4l2_ctrl_s_ctrl(imx319->vblank, vblank_def);2073		h_blank = mode->llp - imx319->cur_mode->width;2074		/*2075		 * Currently hblank is not changeable.2076		 * So FPS control is done only by vblank.2077		 */2078		__v4l2_ctrl_modify_range(imx319->hblank, h_blank,2079					 h_blank, 1, h_blank);2080	}2081 2082	mutex_unlock(&imx319->mutex);2083 2084	return 0;2085}2086 2087/* Verify chip ID */2088static int imx319_identify_module(struct imx319 *imx319)2089{2090	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);2091	int ret;2092	u32 val;2093 2094	if (imx319->identified)2095		return 0;2096 2097	ret = imx319_read_reg(imx319, IMX319_REG_CHIP_ID, 2, &val);2098	if (ret)2099		return ret;2100 2101	if (val != IMX319_CHIP_ID) {2102		dev_err(&client->dev, "chip id mismatch: %x!=%x",2103			IMX319_CHIP_ID, val);2104		return -EIO;2105	}2106 2107	imx319->identified = true;2108 2109	return 0;2110}2111 2112/* Start streaming */2113static int imx319_start_streaming(struct imx319 *imx319)2114{2115	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);2116	const struct imx319_reg_list *reg_list;2117	int ret;2118 2119	ret = imx319_identify_module(imx319);2120	if (ret)2121		return ret;2122 2123	/* Global Setting */2124	reg_list = &imx319_global_setting;2125	ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs);2126	if (ret) {2127		dev_err(&client->dev, "failed to set global settings");2128		return ret;2129	}2130 2131	/* Apply default values of current mode */2132	reg_list = &imx319->cur_mode->reg_list;2133	ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs);2134	if (ret) {2135		dev_err(&client->dev, "failed to set mode");2136		return ret;2137	}2138 2139	/* set digital gain control to all color mode */2140	ret = imx319_write_reg(imx319, IMX319_REG_DPGA_USE_GLOBAL_GAIN, 1, 1);2141	if (ret)2142		return ret;2143 2144	/* Apply customized values from user */2145	ret =  __v4l2_ctrl_handler_setup(imx319->sd.ctrl_handler);2146	if (ret)2147		return ret;2148 2149	return imx319_write_reg(imx319, IMX319_REG_MODE_SELECT,2150				1, IMX319_MODE_STREAMING);2151}2152 2153/* Stop streaming */2154static int imx319_stop_streaming(struct imx319 *imx319)2155{2156	return imx319_write_reg(imx319, IMX319_REG_MODE_SELECT,2157				1, IMX319_MODE_STANDBY);2158}2159 2160static int imx319_set_stream(struct v4l2_subdev *sd, int enable)2161{2162	struct imx319 *imx319 = to_imx319(sd);2163	struct i2c_client *client = v4l2_get_subdevdata(sd);2164	int ret = 0;2165 2166	mutex_lock(&imx319->mutex);2167 2168	if (enable) {2169		ret = pm_runtime_resume_and_get(&client->dev);2170		if (ret < 0)2171			goto err_unlock;2172 2173		/*2174		 * Apply default & customized values2175		 * and then start streaming.2176		 */2177		ret = imx319_start_streaming(imx319);2178		if (ret)2179			goto err_rpm_put;2180	} else {2181		imx319_stop_streaming(imx319);2182		pm_runtime_put(&client->dev);2183	}2184 2185	/* vflip and hflip cannot change during streaming */2186	__v4l2_ctrl_grab(imx319->vflip, enable);2187	__v4l2_ctrl_grab(imx319->hflip, enable);2188 2189	mutex_unlock(&imx319->mutex);2190 2191	return ret;2192 2193err_rpm_put:2194	pm_runtime_put(&client->dev);2195err_unlock:2196	mutex_unlock(&imx319->mutex);2197 2198	return ret;2199}2200 2201static const struct v4l2_subdev_core_ops imx319_subdev_core_ops = {2202	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,2203	.unsubscribe_event = v4l2_event_subdev_unsubscribe,2204};2205 2206static const struct v4l2_subdev_video_ops imx319_video_ops = {2207	.s_stream = imx319_set_stream,2208};2209 2210static const struct v4l2_subdev_pad_ops imx319_pad_ops = {2211	.enum_mbus_code = imx319_enum_mbus_code,2212	.get_fmt = imx319_get_pad_format,2213	.set_fmt = imx319_set_pad_format,2214	.enum_frame_size = imx319_enum_frame_size,2215};2216 2217static const struct v4l2_subdev_ops imx319_subdev_ops = {2218	.core = &imx319_subdev_core_ops,2219	.video = &imx319_video_ops,2220	.pad = &imx319_pad_ops,2221};2222 2223static const struct media_entity_operations imx319_subdev_entity_ops = {2224	.link_validate = v4l2_subdev_link_validate,2225};2226 2227static const struct v4l2_subdev_internal_ops imx319_internal_ops = {2228	.open = imx319_open,2229};2230 2231/* Initialize control handlers */2232static int imx319_init_controls(struct imx319 *imx319)2233{2234	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);2235	struct v4l2_ctrl_handler *ctrl_hdlr;2236	s64 exposure_max;2237	s64 vblank_def;2238	s64 vblank_min;2239	s64 hblank;2240	u64 pixel_rate;2241	const struct imx319_mode *mode;2242	u32 max;2243	int ret;2244 2245	ctrl_hdlr = &imx319->ctrl_handler;2246	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);2247	if (ret)2248		return ret;2249 2250	ctrl_hdlr->lock = &imx319->mutex;2251	max = ARRAY_SIZE(link_freq_menu_items) - 1;2252	imx319->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx319_ctrl_ops,2253						   V4L2_CID_LINK_FREQ, max, 0,2254						   link_freq_menu_items);2255	if (imx319->link_freq)2256		imx319->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;2257 2258	/* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */2259	pixel_rate = IMX319_LINK_FREQ_DEFAULT * 2 * 4;2260	do_div(pixel_rate, 10);2261	/* By default, PIXEL_RATE is read only */2262	imx319->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,2263					       V4L2_CID_PIXEL_RATE, pixel_rate,2264					       pixel_rate, 1, pixel_rate);2265 2266	/* Initial vblank/hblank/exposure parameters based on current mode */2267	mode = imx319->cur_mode;2268	vblank_def = mode->fll_def - mode->height;2269	vblank_min = mode->fll_min - mode->height;2270	imx319->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,2271					   V4L2_CID_VBLANK, vblank_min,2272					   IMX319_FLL_MAX - mode->height,2273					   1, vblank_def);2274 2275	hblank = mode->llp - mode->width;2276	imx319->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,2277					   V4L2_CID_HBLANK, hblank, hblank,2278					   1, hblank);2279	if (imx319->hblank)2280		imx319->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;2281 2282	/* fll >= exposure time + adjust parameter (default value is 18) */2283	exposure_max = mode->fll_def - 18;2284	imx319->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,2285					     V4L2_CID_EXPOSURE,2286					     IMX319_EXPOSURE_MIN, exposure_max,2287					     IMX319_EXPOSURE_STEP,2288					     IMX319_EXPOSURE_DEFAULT);2289 2290	imx319->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,2291					  V4L2_CID_HFLIP, 0, 1, 1, 0);2292	if (imx319->hflip)2293		imx319->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;2294	imx319->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops,2295					  V4L2_CID_VFLIP, 0, 1, 1, 0);2296	if (imx319->vflip)2297		imx319->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;2298 2299	v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,2300			  IMX319_ANA_GAIN_MIN, IMX319_ANA_GAIN_MAX,2301			  IMX319_ANA_GAIN_STEP, IMX319_ANA_GAIN_DEFAULT);2302 2303	/* Digital gain */2304	v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, V4L2_CID_DIGITAL_GAIN,2305			  IMX319_DGTL_GAIN_MIN, IMX319_DGTL_GAIN_MAX,2306			  IMX319_DGTL_GAIN_STEP, IMX319_DGTL_GAIN_DEFAULT);2307 2308	v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx319_ctrl_ops,2309				     V4L2_CID_TEST_PATTERN,2310				     ARRAY_SIZE(imx319_test_pattern_menu) - 1,2311				     0, 0, imx319_test_pattern_menu);2312	if (ctrl_hdlr->error) {2313		ret = ctrl_hdlr->error;2314		dev_err(&client->dev, "control init failed: %d", ret);2315		goto error;2316	}2317 2318	imx319->sd.ctrl_handler = ctrl_hdlr;2319 2320	return 0;2321 2322error:2323	v4l2_ctrl_handler_free(ctrl_hdlr);2324 2325	return ret;2326}2327 2328static struct imx319_hwcfg *imx319_get_hwcfg(struct device *dev)2329{2330	struct imx319_hwcfg *cfg;2331	struct v4l2_fwnode_endpoint bus_cfg = {2332		.bus_type = V4L2_MBUS_CSI2_DPHY2333	};2334	struct fwnode_handle *ep;2335	struct fwnode_handle *fwnode = dev_fwnode(dev);2336	int ret;2337 2338	if (!fwnode)2339		return NULL;2340 2341	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);2342	if (!ep)2343		return NULL;2344 2345	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);2346	if (ret)2347		goto out_err;2348 2349	cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL);2350	if (!cfg)2351		goto out_err;2352 2353	ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",2354				       &cfg->ext_clk);2355	if (ret) {2356		dev_err(dev, "can't get clock frequency");2357		goto out_err;2358	}2359 2360	dev_dbg(dev, "ext clk: %d", cfg->ext_clk);2361	if (cfg->ext_clk != IMX319_EXT_CLK) {2362		dev_err(dev, "external clock %d is not supported",2363			cfg->ext_clk);2364		goto out_err;2365	}2366 2367	ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies,2368				       bus_cfg.nr_of_link_frequencies,2369				       link_freq_menu_items,2370				       ARRAY_SIZE(link_freq_menu_items),2371				       &cfg->link_freq_bitmap);2372	if (ret)2373		goto out_err;2374 2375	v4l2_fwnode_endpoint_free(&bus_cfg);2376	fwnode_handle_put(ep);2377	return cfg;2378 2379out_err:2380	v4l2_fwnode_endpoint_free(&bus_cfg);2381	fwnode_handle_put(ep);2382	return NULL;2383}2384 2385static int imx319_probe(struct i2c_client *client)2386{2387	struct imx319 *imx319;2388	bool full_power;2389	int ret;2390 2391	imx319 = devm_kzalloc(&client->dev, sizeof(*imx319), GFP_KERNEL);2392	if (!imx319)2393		return -ENOMEM;2394 2395	mutex_init(&imx319->mutex);2396 2397	/* Initialize subdev */2398	v4l2_i2c_subdev_init(&imx319->sd, client, &imx319_subdev_ops);2399 2400	full_power = acpi_dev_state_d0(&client->dev);2401	if (full_power) {2402		/* Check module identity */2403		ret = imx319_identify_module(imx319);2404		if (ret) {2405			dev_err(&client->dev, "failed to find sensor: %d", ret);2406			goto error_probe;2407		}2408	}2409 2410	imx319->hwcfg = imx319_get_hwcfg(&client->dev);2411	if (!imx319->hwcfg) {2412		dev_err(&client->dev, "failed to get hwcfg");2413		ret = -ENODEV;2414		goto error_probe;2415	}2416 2417	/* Set default mode to max resolution */2418	imx319->cur_mode = &supported_modes[0];2419 2420	ret = imx319_init_controls(imx319);2421	if (ret) {2422		dev_err(&client->dev, "failed to init controls: %d", ret);2423		goto error_probe;2424	}2425 2426	/* Initialize subdev */2427	imx319->sd.internal_ops = &imx319_internal_ops;2428	imx319->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |2429		V4L2_SUBDEV_FL_HAS_EVENTS;2430	imx319->sd.entity.ops = &imx319_subdev_entity_ops;2431	imx319->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;2432 2433	/* Initialize source pad */2434	imx319->pad.flags = MEDIA_PAD_FL_SOURCE;2435	ret = media_entity_pads_init(&imx319->sd.entity, 1, &imx319->pad);2436	if (ret) {2437		dev_err(&client->dev, "failed to init entity pads: %d", ret);2438		goto error_handler_free;2439	}2440 2441	/* Set the device's state to active if it's in D0 state. */2442	if (full_power)2443		pm_runtime_set_active(&client->dev);2444	pm_runtime_enable(&client->dev);2445	pm_runtime_idle(&client->dev);2446 2447	ret = v4l2_async_register_subdev_sensor(&imx319->sd);2448	if (ret < 0)2449		goto error_media_entity_pm;2450 2451	return 0;2452 2453error_media_entity_pm:2454	pm_runtime_disable(&client->dev);2455	pm_runtime_set_suspended(&client->dev);2456	media_entity_cleanup(&imx319->sd.entity);2457 2458error_handler_free:2459	v4l2_ctrl_handler_free(imx319->sd.ctrl_handler);2460 2461error_probe:2462	mutex_destroy(&imx319->mutex);2463 2464	return ret;2465}2466 2467static void imx319_remove(struct i2c_client *client)2468{2469	struct v4l2_subdev *sd = i2c_get_clientdata(client);2470	struct imx319 *imx319 = to_imx319(sd);2471 2472	v4l2_async_unregister_subdev(sd);2473	media_entity_cleanup(&sd->entity);2474	v4l2_ctrl_handler_free(sd->ctrl_handler);2475 2476	pm_runtime_disable(&client->dev);2477	pm_runtime_set_suspended(&client->dev);2478 2479	mutex_destroy(&imx319->mutex);2480}2481 2482static const struct acpi_device_id imx319_acpi_ids[] __maybe_unused = {2483	{ "SONY319A" },2484	{ /* sentinel */ }2485};2486MODULE_DEVICE_TABLE(acpi, imx319_acpi_ids);2487 2488static struct i2c_driver imx319_i2c_driver = {2489	.driver = {2490		.name = "imx319",2491		.acpi_match_table = ACPI_PTR(imx319_acpi_ids),2492	},2493	.probe = imx319_probe,2494	.remove = imx319_remove,2495	.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,2496};2497module_i2c_driver(imx319_i2c_driver);2498 2499MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");2500MODULE_AUTHOR("Rapolu, Chiranjeevi");2501MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");2502MODULE_AUTHOR("Yang, Hyungwoo");2503MODULE_DESCRIPTION("Sony imx319 sensor driver");2504MODULE_LICENSE("GPL v2");2505