File Index
Files and directories
Sign in
FILE

imx355.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/i2c/imx355.c C
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (C) 2018 Intel Corporation
   3
   4#include <linux/acpi.h>
   5#include <linux/clk.h>
   6#include <linux/i2c.h>
   7#include <linux/module.h>
   8#include <linux/pm_runtime.h>
   9#include <linux/unaligned.h>
  10
  11#include <media/v4l2-ctrls.h>
  12#include <media/v4l2-device.h>
  13#include <media/v4l2-event.h>
  14#include <media/v4l2-fwnode.h>
  15
  16#define IMX355_REG_MODE_SELECT		0x0100
  17#define IMX355_MODE_STANDBY		0x00
  18#define IMX355_MODE_STREAMING		0x01
  19
  20/* Chip ID */
  21#define IMX355_REG_CHIP_ID		0x0016
  22#define IMX355_CHIP_ID			0x0355
  23
  24/* V_TIMING internal */
  25#define IMX355_REG_FLL			0x0340
  26#define IMX355_FLL_MAX			0xffff
  27
  28/* Exposure control */
  29#define IMX355_REG_EXPOSURE		0x0202
  30#define IMX355_EXPOSURE_MIN		1
  31#define IMX355_EXPOSURE_STEP		1
  32#define IMX355_EXPOSURE_DEFAULT		0x0282
  33
  34/* Analog gain control */
  35#define IMX355_REG_ANALOG_GAIN		0x0204
  36#define IMX355_ANA_GAIN_MIN		0
  37#define IMX355_ANA_GAIN_MAX		960
  38#define IMX355_ANA_GAIN_STEP		1
  39#define IMX355_ANA_GAIN_DEFAULT		0
  40
  41/* Digital gain control */
  42#define IMX355_REG_DPGA_USE_GLOBAL_GAIN	0x3070
  43#define IMX355_REG_DIG_GAIN_GLOBAL	0x020e
  44#define IMX355_DGTL_GAIN_MIN		256
  45#define IMX355_DGTL_GAIN_MAX		4095
  46#define IMX355_DGTL_GAIN_STEP		1
  47#define IMX355_DGTL_GAIN_DEFAULT	256
  48
  49/* Test Pattern Control */
  50#define IMX355_REG_TEST_PATTERN		0x0600
  51#define IMX355_TEST_PATTERN_DISABLED		0
  52#define IMX355_TEST_PATTERN_SOLID_COLOR		1
  53#define IMX355_TEST_PATTERN_COLOR_BARS		2
  54#define IMX355_TEST_PATTERN_GRAY_COLOR_BARS	3
  55#define IMX355_TEST_PATTERN_PN9			4
  56
  57/* Flip Control */
  58#define IMX355_REG_ORIENTATION		0x0101
  59
  60/* default link frequency and external clock */
  61#define IMX355_LINK_FREQ_DEFAULT	360000000LL
  62#define IMX355_EXT_CLK			19200000
  63#define IMX355_LINK_FREQ_INDEX		0
  64
  65struct imx355_reg {
  66	u16 address;
  67	u8 val;
  68};
  69
  70struct imx355_reg_list {
  71	u32 num_of_regs;
  72	const struct imx355_reg *regs;
  73};
  74
  75/* Mode : resolution and related config&values */
  76struct imx355_mode {
  77	/* Frame width */
  78	u32 width;
  79	/* Frame height */
  80	u32 height;
  81
  82	/* V-timing */
  83	u32 fll_def;
  84	u32 fll_min;
  85
  86	/* H-timing */
  87	u32 llp;
  88
  89	/* index of link frequency */
  90	u32 link_freq_index;
  91
  92	/* Default register values */
  93	struct imx355_reg_list reg_list;
  94};
  95
  96struct imx355_hwcfg {
  97	unsigned long link_freq_bitmap;
  98};
  99
 100struct imx355 {
 101	struct device *dev;
 102	struct clk *clk;
 103
 104	struct v4l2_subdev sd;
 105	struct media_pad pad;
 106
 107	struct v4l2_ctrl_handler ctrl_handler;
 108	/* V4L2 Controls */
 109	struct v4l2_ctrl *link_freq;
 110	struct v4l2_ctrl *pixel_rate;
 111	struct v4l2_ctrl *vblank;
 112	struct v4l2_ctrl *hblank;
 113	struct v4l2_ctrl *exposure;
 114	struct v4l2_ctrl *vflip;
 115	struct v4l2_ctrl *hflip;
 116
 117	/* Current mode */
 118	const struct imx355_mode *cur_mode;
 119
 120	struct imx355_hwcfg *hwcfg;
 121
 122	/*
 123	 * Mutex for serialized access:
 124	 * Protect sensor set pad format and start/stop streaming safely.
 125	 * Protect access to sensor v4l2 controls.
 126	 */
 127	struct mutex mutex;
 128};
 129
 130static const struct imx355_reg imx355_global_regs[] = {
 131	{ 0x0136, 0x13 },
 132	{ 0x0137, 0x33 },
 133	{ 0x304e, 0x03 },
 134	{ 0x4348, 0x16 },
 135	{ 0x4350, 0x19 },
 136	{ 0x4408, 0x0a },
 137	{ 0x440c, 0x0b },
 138	{ 0x4411, 0x5f },
 139	{ 0x4412, 0x2c },
 140	{ 0x4623, 0x00 },
 141	{ 0x462c, 0x0f },
 142	{ 0x462d, 0x00 },
 143	{ 0x462e, 0x00 },
 144	{ 0x4684, 0x54 },
 145	{ 0x480a, 0x07 },
 146	{ 0x4908, 0x07 },
 147	{ 0x4909, 0x07 },
 148	{ 0x490d, 0x0a },
 149	{ 0x491e, 0x0f },
 150	{ 0x4921, 0x06 },
 151	{ 0x4923, 0x28 },
 152	{ 0x4924, 0x28 },
 153	{ 0x4925, 0x29 },
 154	{ 0x4926, 0x29 },
 155	{ 0x4927, 0x1f },
 156	{ 0x4928, 0x20 },
 157	{ 0x4929, 0x20 },
 158	{ 0x492a, 0x20 },
 159	{ 0x492c, 0x05 },
 160	{ 0x492d, 0x06 },
 161	{ 0x492e, 0x06 },
 162	{ 0x492f, 0x06 },
 163	{ 0x4930, 0x03 },
 164	{ 0x4931, 0x04 },
 165	{ 0x4932, 0x04 },
 166	{ 0x4933, 0x05 },
 167	{ 0x595e, 0x01 },
 168	{ 0x5963, 0x01 },
 169	{ 0x3030, 0x01 },
 170	{ 0x3031, 0x01 },
 171	{ 0x3045, 0x01 },
 172	{ 0x4010, 0x00 },
 173	{ 0x4011, 0x00 },
 174	{ 0x4012, 0x00 },
 175	{ 0x4013, 0x01 },
 176	{ 0x68a8, 0xfe },
 177	{ 0x68a9, 0xff },
 178	{ 0x6888, 0x00 },
 179	{ 0x6889, 0x00 },
 180	{ 0x68b0, 0x00 },
 181	{ 0x3058, 0x00 },
 182	{ 0x305a, 0x00 },
 183};
 184
 185static const struct imx355_reg_list imx355_global_setting = {
 186	.num_of_regs = ARRAY_SIZE(imx355_global_regs),
 187	.regs = imx355_global_regs,
 188};
 189
 190static const struct imx355_reg mode_3268x2448_regs[] = {
 191	{ 0x0112, 0x0a },
 192	{ 0x0113, 0x0a },
 193	{ 0x0114, 0x03 },
 194	{ 0x0342, 0x0e },
 195	{ 0x0343, 0x58 },
 196	{ 0x0340, 0x0a },
 197	{ 0x0341, 0x37 },
 198	{ 0x0344, 0x00 },
 199	{ 0x0345, 0x08 },
 200	{ 0x0346, 0x00 },
 201	{ 0x0347, 0x08 },
 202	{ 0x0348, 0x0c },
 203	{ 0x0349, 0xcb },
 204	{ 0x034a, 0x09 },
 205	{ 0x034b, 0x97 },
 206	{ 0x0220, 0x00 },
 207	{ 0x0222, 0x01 },
 208	{ 0x0900, 0x00 },
 209	{ 0x0901, 0x11 },
 210	{ 0x0902, 0x00 },
 211	{ 0x034c, 0x0c },
 212	{ 0x034d, 0xc4 },
 213	{ 0x034e, 0x09 },
 214	{ 0x034f, 0x90 },
 215	{ 0x0301, 0x05 },
 216	{ 0x0303, 0x01 },
 217	{ 0x0305, 0x02 },
 218	{ 0x0306, 0x00 },
 219	{ 0x0307, 0x78 },
 220	{ 0x030b, 0x01 },
 221	{ 0x030d, 0x02 },
 222	{ 0x030e, 0x00 },
 223	{ 0x030f, 0x4b },
 224	{ 0x0310, 0x00 },
 225	{ 0x0700, 0x00 },
 226	{ 0x0701, 0x10 },
 227	{ 0x0820, 0x0b },
 228	{ 0x0821, 0x40 },
 229	{ 0x3088, 0x04 },
 230	{ 0x6813, 0x02 },
 231	{ 0x6835, 0x07 },
 232	{ 0x6836, 0x01 },
 233	{ 0x6837, 0x04 },
 234	{ 0x684d, 0x07 },
 235	{ 0x684e, 0x01 },
 236	{ 0x684f, 0x04 },
 237};
 238
 239static const struct imx355_reg mode_3264x2448_regs[] = {
 240	{ 0x0112, 0x0a },
 241	{ 0x0113, 0x0a },
 242	{ 0x0114, 0x03 },
 243	{ 0x0342, 0x0e },
 244	{ 0x0343, 0x58 },
 245	{ 0x0340, 0x0a },
 246	{ 0x0341, 0x37 },
 247	{ 0x0344, 0x00 },
 248	{ 0x0345, 0x08 },
 249	{ 0x0346, 0x00 },
 250	{ 0x0347, 0x08 },
 251	{ 0x0348, 0x0c },
 252	{ 0x0349, 0xc7 },
 253	{ 0x034a, 0x09 },
 254	{ 0x034b, 0x97 },
 255	{ 0x0220, 0x00 },
 256	{ 0x0222, 0x01 },
 257	{ 0x0900, 0x00 },
 258	{ 0x0901, 0x11 },
 259	{ 0x0902, 0x00 },
 260	{ 0x034c, 0x0c },
 261	{ 0x034d, 0xc0 },
 262	{ 0x034e, 0x09 },
 263	{ 0x034f, 0x90 },
 264	{ 0x0301, 0x05 },
 265	{ 0x0303, 0x01 },
 266	{ 0x0305, 0x02 },
 267	{ 0x0306, 0x00 },
 268	{ 0x0307, 0x78 },
 269	{ 0x030b, 0x01 },
 270	{ 0x030d, 0x02 },
 271	{ 0x030e, 0x00 },
 272	{ 0x030f, 0x4b },
 273	{ 0x0310, 0x00 },
 274	{ 0x0700, 0x00 },
 275	{ 0x0701, 0x10 },
 276	{ 0x0820, 0x0b },
 277	{ 0x0821, 0x40 },
 278	{ 0x3088, 0x04 },
 279	{ 0x6813, 0x02 },
 280	{ 0x6835, 0x07 },
 281	{ 0x6836, 0x01 },
 282	{ 0x6837, 0x04 },
 283	{ 0x684d, 0x07 },
 284	{ 0x684e, 0x01 },
 285	{ 0x684f, 0x04 },
 286};
 287
 288static const struct imx355_reg mode_3280x2464_regs[] = {
 289	{ 0x0112, 0x0a },
 290	{ 0x0113, 0x0a },
 291	{ 0x0114, 0x03 },
 292	{ 0x0342, 0x0e },
 293	{ 0x0343, 0x58 },
 294	{ 0x0340, 0x0a },
 295	{ 0x0341, 0x37 },
 296	{ 0x0344, 0x00 },
 297	{ 0x0345, 0x00 },
 298	{ 0x0346, 0x00 },
 299	{ 0x0347, 0x00 },
 300	{ 0x0348, 0x0c },
 301	{ 0x0349, 0xcf },
 302	{ 0x034a, 0x09 },
 303	{ 0x034b, 0x9f },
 304	{ 0x0220, 0x00 },
 305	{ 0x0222, 0x01 },
 306	{ 0x0900, 0x00 },
 307	{ 0x0901, 0x11 },
 308	{ 0x0902, 0x00 },
 309	{ 0x034c, 0x0c },
 310	{ 0x034d, 0xd0 },
 311	{ 0x034e, 0x09 },
 312	{ 0x034f, 0xa0 },
 313	{ 0x0301, 0x05 },
 314	{ 0x0303, 0x01 },
 315	{ 0x0305, 0x02 },
 316	{ 0x0306, 0x00 },
 317	{ 0x0307, 0x78 },
 318	{ 0x030b, 0x01 },
 319	{ 0x030d, 0x02 },
 320	{ 0x030e, 0x00 },
 321	{ 0x030f, 0x4b },
 322	{ 0x0310, 0x00 },
 323	{ 0x0700, 0x00 },
 324	{ 0x0701, 0x10 },
 325	{ 0x0820, 0x0b },
 326	{ 0x0821, 0x40 },
 327	{ 0x3088, 0x04 },
 328	{ 0x6813, 0x02 },
 329	{ 0x6835, 0x07 },
 330	{ 0x6836, 0x01 },
 331	{ 0x6837, 0x04 },
 332	{ 0x684d, 0x07 },
 333	{ 0x684e, 0x01 },
 334	{ 0x684f, 0x04 },
 335};
 336
 337static const struct imx355_reg mode_1940x1096_regs[] = {
 338	{ 0x0112, 0x0a },
 339	{ 0x0113, 0x0a },
 340	{ 0x0114, 0x03 },
 341	{ 0x0342, 0x0e },
 342	{ 0x0343, 0x58 },
 343	{ 0x0340, 0x05 },
 344	{ 0x0341, 0x1a },
 345	{ 0x0344, 0x02 },
 346	{ 0x0345, 0xa0 },
 347	{ 0x0346, 0x02 },
 348	{ 0x0347, 0xac },
 349	{ 0x0348, 0x0a },
 350	{ 0x0349, 0x33 },
 351	{ 0x034a, 0x06 },
 352	{ 0x034b, 0xf3 },
 353	{ 0x0220, 0x00 },
 354	{ 0x0222, 0x01 },
 355	{ 0x0900, 0x00 },
 356	{ 0x0901, 0x11 },
 357	{ 0x0902, 0x00 },
 358	{ 0x034c, 0x07 },
 359	{ 0x034d, 0x94 },
 360	{ 0x034e, 0x04 },
 361	{ 0x034f, 0x48 },
 362	{ 0x0301, 0x05 },
 363	{ 0x0303, 0x01 },
 364	{ 0x0305, 0x02 },
 365	{ 0x0306, 0x00 },
 366	{ 0x0307, 0x78 },
 367	{ 0x030b, 0x01 },
 368	{ 0x030d, 0x02 },
 369	{ 0x030e, 0x00 },
 370	{ 0x030f, 0x4b },
 371	{ 0x0310, 0x00 },
 372	{ 0x0700, 0x00 },
 373	{ 0x0701, 0x10 },
 374	{ 0x0820, 0x0b },
 375	{ 0x0821, 0x40 },
 376	{ 0x3088, 0x04 },
 377	{ 0x6813, 0x02 },
 378	{ 0x6835, 0x07 },
 379	{ 0x6836, 0x01 },
 380	{ 0x6837, 0x04 },
 381	{ 0x684d, 0x07 },
 382	{ 0x684e, 0x01 },
 383	{ 0x684f, 0x04 },
 384};
 385
 386static const struct imx355_reg mode_1936x1096_regs[] = {
 387	{ 0x0112, 0x0a },
 388	{ 0x0113, 0x0a },
 389	{ 0x0114, 0x03 },
 390	{ 0x0342, 0x0e },
 391	{ 0x0343, 0x58 },
 392	{ 0x0340, 0x05 },
 393	{ 0x0341, 0x1a },
 394	{ 0x0344, 0x02 },
 395	{ 0x0345, 0xa0 },
 396	{ 0x0346, 0x02 },
 397	{ 0x0347, 0xac },
 398	{ 0x0348, 0x0a },
 399	{ 0x0349, 0x2f },
 400	{ 0x034a, 0x06 },
 401	{ 0x034b, 0xf3 },
 402	{ 0x0220, 0x00 },
 403	{ 0x0222, 0x01 },
 404	{ 0x0900, 0x00 },
 405	{ 0x0901, 0x11 },
 406	{ 0x0902, 0x00 },
 407	{ 0x034c, 0x07 },
 408	{ 0x034d, 0x90 },
 409	{ 0x034e, 0x04 },
 410	{ 0x034f, 0x48 },
 411	{ 0x0301, 0x05 },
 412	{ 0x0303, 0x01 },
 413	{ 0x0305, 0x02 },
 414	{ 0x0306, 0x00 },
 415	{ 0x0307, 0x78 },
 416	{ 0x030b, 0x01 },
 417	{ 0x030d, 0x02 },
 418	{ 0x030e, 0x00 },
 419	{ 0x030f, 0x4b },
 420	{ 0x0310, 0x00 },
 421	{ 0x0700, 0x00 },
 422	{ 0x0701, 0x10 },
 423	{ 0x0820, 0x0b },
 424	{ 0x0821, 0x40 },
 425	{ 0x3088, 0x04 },
 426	{ 0x6813, 0x02 },
 427	{ 0x6835, 0x07 },
 428	{ 0x6836, 0x01 },
 429	{ 0x6837, 0x04 },
 430	{ 0x684d, 0x07 },
 431	{ 0x684e, 0x01 },
 432	{ 0x684f, 0x04 },
 433};
 434
 435static const struct imx355_reg mode_1924x1080_regs[] = {
 436	{ 0x0112, 0x0a },
 437	{ 0x0113, 0x0a },
 438	{ 0x0114, 0x03 },
 439	{ 0x0342, 0x0e },
 440	{ 0x0343, 0x58 },
 441	{ 0x0340, 0x05 },
 442	{ 0x0341, 0x1a },
 443	{ 0x0344, 0x02 },
 444	{ 0x0345, 0xa8 },
 445	{ 0x0346, 0x02 },
 446	{ 0x0347, 0xb4 },
 447	{ 0x0348, 0x0a },
 448	{ 0x0349, 0x2b },
 449	{ 0x034a, 0x06 },
 450	{ 0x034b, 0xeb },
 451	{ 0x0220, 0x00 },
 452	{ 0x0222, 0x01 },
 453	{ 0x0900, 0x00 },
 454	{ 0x0901, 0x11 },
 455	{ 0x0902, 0x00 },
 456	{ 0x034c, 0x07 },
 457	{ 0x034d, 0x84 },
 458	{ 0x034e, 0x04 },
 459	{ 0x034f, 0x38 },
 460	{ 0x0301, 0x05 },
 461	{ 0x0303, 0x01 },
 462	{ 0x0305, 0x02 },
 463	{ 0x0306, 0x00 },
 464	{ 0x0307, 0x78 },
 465	{ 0x030b, 0x01 },
 466	{ 0x030d, 0x02 },
 467	{ 0x030e, 0x00 },
 468	{ 0x030f, 0x4b },
 469	{ 0x0310, 0x00 },
 470	{ 0x0700, 0x00 },
 471	{ 0x0701, 0x10 },
 472	{ 0x0820, 0x0b },
 473	{ 0x0821, 0x40 },
 474	{ 0x3088, 0x04 },
 475	{ 0x6813, 0x02 },
 476	{ 0x6835, 0x07 },
 477	{ 0x6836, 0x01 },
 478	{ 0x6837, 0x04 },
 479	{ 0x684d, 0x07 },
 480	{ 0x684e, 0x01 },
 481	{ 0x684f, 0x04 },
 482};
 483
 484static const struct imx355_reg mode_1920x1080_regs[] = {
 485	{ 0x0112, 0x0a },
 486	{ 0x0113, 0x0a },
 487	{ 0x0114, 0x03 },
 488	{ 0x0342, 0x0e },
 489	{ 0x0343, 0x58 },
 490	{ 0x0340, 0x05 },
 491	{ 0x0341, 0x1a },
 492	{ 0x0344, 0x02 },
 493	{ 0x0345, 0xa8 },
 494	{ 0x0346, 0x02 },
 495	{ 0x0347, 0xb4 },
 496	{ 0x0348, 0x0a },
 497	{ 0x0349, 0x27 },
 498	{ 0x034a, 0x06 },
 499	{ 0x034b, 0xeb },
 500	{ 0x0220, 0x00 },
 501	{ 0x0222, 0x01 },
 502	{ 0x0900, 0x00 },
 503	{ 0x0901, 0x11 },
 504	{ 0x0902, 0x00 },
 505	{ 0x034c, 0x07 },
 506	{ 0x034d, 0x80 },
 507	{ 0x034e, 0x04 },
 508	{ 0x034f, 0x38 },
 509	{ 0x0301, 0x05 },
 510	{ 0x0303, 0x01 },
 511	{ 0x0305, 0x02 },
 512	{ 0x0306, 0x00 },
 513	{ 0x0307, 0x78 },
 514	{ 0x030b, 0x01 },
 515	{ 0x030d, 0x02 },
 516	{ 0x030e, 0x00 },
 517	{ 0x030f, 0x4b },
 518	{ 0x0310, 0x00 },
 519	{ 0x0700, 0x00 },
 520	{ 0x0701, 0x10 },
 521	{ 0x0820, 0x0b },
 522	{ 0x0821, 0x40 },
 523	{ 0x3088, 0x04 },
 524	{ 0x6813, 0x02 },
 525	{ 0x6835, 0x07 },
 526	{ 0x6836, 0x01 },
 527	{ 0x6837, 0x04 },
 528	{ 0x684d, 0x07 },
 529	{ 0x684e, 0x01 },
 530	{ 0x684f, 0x04 },
 531};
 532
 533static const struct imx355_reg mode_1640x1232_regs[] = {
 534	{ 0x0112, 0x0a },
 535	{ 0x0113, 0x0a },
 536	{ 0x0114, 0x03 },
 537	{ 0x0342, 0x07 },
 538	{ 0x0343, 0x2c },
 539	{ 0x0340, 0x05 },
 540	{ 0x0341, 0x1a },
 541	{ 0x0344, 0x00 },
 542	{ 0x0345, 0x00 },
 543	{ 0x0346, 0x00 },
 544	{ 0x0347, 0x00 },
 545	{ 0x0348, 0x0c },
 546	{ 0x0349, 0xcf },
 547	{ 0x034a, 0x09 },
 548	{ 0x034b, 0x9f },
 549	{ 0x0220, 0x00 },
 550	{ 0x0222, 0x01 },
 551	{ 0x0900, 0x01 },
 552	{ 0x0901, 0x22 },
 553	{ 0x0902, 0x00 },
 554	{ 0x034c, 0x06 },
 555	{ 0x034d, 0x68 },
 556	{ 0x034e, 0x04 },
 557	{ 0x034f, 0xd0 },
 558	{ 0x0301, 0x05 },
 559	{ 0x0303, 0x01 },
 560	{ 0x0305, 0x02 },
 561	{ 0x0306, 0x00 },
 562	{ 0x0307, 0x78 },
 563	{ 0x030b, 0x01 },
 564	{ 0x030d, 0x02 },
 565	{ 0x030e, 0x00 },
 566	{ 0x030f, 0x4b },
 567	{ 0x0310, 0x00 },
 568	{ 0x0700, 0x00 },
 569	{ 0x0701, 0x10 },
 570	{ 0x0820, 0x0b },
 571	{ 0x0821, 0x40 },
 572	{ 0x3088, 0x04 },
 573	{ 0x6813, 0x02 },
 574	{ 0x6835, 0x07 },
 575	{ 0x6836, 0x01 },
 576	{ 0x6837, 0x04 },
 577	{ 0x684d, 0x07 },
 578	{ 0x684e, 0x01 },
 579	{ 0x684f, 0x04 },
 580};
 581
 582static const struct imx355_reg mode_1640x922_regs[] = {
 583	{ 0x0112, 0x0a },
 584	{ 0x0113, 0x0a },
 585	{ 0x0114, 0x03 },
 586	{ 0x0342, 0x07 },
 587	{ 0x0343, 0x2c },
 588	{ 0x0340, 0x05 },
 589	{ 0x0341, 0x1a },
 590	{ 0x0344, 0x00 },
 591	{ 0x0345, 0x00 },
 592	{ 0x0346, 0x01 },
 593	{ 0x0347, 0x30 },
 594	{ 0x0348, 0x0c },
 595	{ 0x0349, 0xcf },
 596	{ 0x034a, 0x08 },
 597	{ 0x034b, 0x63 },
 598	{ 0x0220, 0x00 },
 599	{ 0x0222, 0x01 },
 600	{ 0x0900, 0x01 },
 601	{ 0x0901, 0x22 },
 602	{ 0x0902, 0x00 },
 603	{ 0x034c, 0x06 },
 604	{ 0x034d, 0x68 },
 605	{ 0x034e, 0x03 },
 606	{ 0x034f, 0x9a },
 607	{ 0x0301, 0x05 },
 608	{ 0x0303, 0x01 },
 609	{ 0x0305, 0x02 },
 610	{ 0x0306, 0x00 },
 611	{ 0x0307, 0x78 },
 612	{ 0x030b, 0x01 },
 613	{ 0x030d, 0x02 },
 614	{ 0x030e, 0x00 },
 615	{ 0x030f, 0x4b },
 616	{ 0x0310, 0x00 },
 617	{ 0x0700, 0x00 },
 618	{ 0x0701, 0x10 },
 619	{ 0x0820, 0x0b },
 620	{ 0x0821, 0x40 },
 621	{ 0x3088, 0x04 },
 622	{ 0x6813, 0x02 },
 623	{ 0x6835, 0x07 },
 624	{ 0x6836, 0x01 },
 625	{ 0x6837, 0x04 },
 626	{ 0x684d, 0x07 },
 627	{ 0x684e, 0x01 },
 628	{ 0x684f, 0x04 },
 629};
 630
 631static const struct imx355_reg mode_1300x736_regs[] = {
 632	{ 0x0112, 0x0a },
 633	{ 0x0113, 0x0a },
 634	{ 0x0114, 0x03 },
 635	{ 0x0342, 0x07 },
 636	{ 0x0343, 0x2c },
 637	{ 0x0340, 0x05 },
 638	{ 0x0341, 0x1a },
 639	{ 0x0344, 0x01 },
 640	{ 0x0345, 0x58 },
 641	{ 0x0346, 0x01 },
 642	{ 0x0347, 0xf0 },
 643	{ 0x0348, 0x0b },
 644	{ 0x0349, 0x7f },
 645	{ 0x034a, 0x07 },
 646	{ 0x034b, 0xaf },
 647	{ 0x0220, 0x00 },
 648	{ 0x0222, 0x01 },
 649	{ 0x0900, 0x01 },
 650	{ 0x0901, 0x22 },
 651	{ 0x0902, 0x00 },
 652	{ 0x034c, 0x05 },
 653	{ 0x034d, 0x14 },
 654	{ 0x034e, 0x02 },
 655	{ 0x034f, 0xe0 },
 656	{ 0x0301, 0x05 },
 657	{ 0x0303, 0x01 },
 658	{ 0x0305, 0x02 },
 659	{ 0x0306, 0x00 },
 660	{ 0x0307, 0x78 },
 661	{ 0x030b, 0x01 },
 662	{ 0x030d, 0x02 },
 663	{ 0x030e, 0x00 },
 664	{ 0x030f, 0x4b },
 665	{ 0x0310, 0x00 },
 666	{ 0x0700, 0x00 },
 667	{ 0x0701, 0x10 },
 668	{ 0x0820, 0x0b },
 669	{ 0x0821, 0x40 },
 670	{ 0x3088, 0x04 },
 671	{ 0x6813, 0x02 },
 672	{ 0x6835, 0x07 },
 673	{ 0x6836, 0x01 },
 674	{ 0x6837, 0x04 },
 675	{ 0x684d, 0x07 },
 676	{ 0x684e, 0x01 },
 677	{ 0x684f, 0x04 },
 678};
 679
 680static const struct imx355_reg mode_1296x736_regs[] = {
 681	{ 0x0112, 0x0a },
 682	{ 0x0113, 0x0a },
 683	{ 0x0114, 0x03 },
 684	{ 0x0342, 0x07 },
 685	{ 0x0343, 0x2c },
 686	{ 0x0340, 0x05 },
 687	{ 0x0341, 0x1a },
 688	{ 0x0344, 0x01 },
 689	{ 0x0345, 0x58 },
 690	{ 0x0346, 0x01 },
 691	{ 0x0347, 0xf0 },
 692	{ 0x0348, 0x0b },
 693	{ 0x0349, 0x77 },
 694	{ 0x034a, 0x07 },
 695	{ 0x034b, 0xaf },
 696	{ 0x0220, 0x00 },
 697	{ 0x0222, 0x01 },
 698	{ 0x0900, 0x01 },
 699	{ 0x0901, 0x22 },
 700	{ 0x0902, 0x00 },
 701	{ 0x034c, 0x05 },
 702	{ 0x034d, 0x10 },
 703	{ 0x034e, 0x02 },
 704	{ 0x034f, 0xe0 },
 705	{ 0x0301, 0x05 },
 706	{ 0x0303, 0x01 },
 707	{ 0x0305, 0x02 },
 708	{ 0x0306, 0x00 },
 709	{ 0x0307, 0x78 },
 710	{ 0x030b, 0x01 },
 711	{ 0x030d, 0x02 },
 712	{ 0x030e, 0x00 },
 713	{ 0x030f, 0x4b },
 714	{ 0x0310, 0x00 },
 715	{ 0x0700, 0x00 },
 716	{ 0x0701, 0x10 },
 717	{ 0x0820, 0x0b },
 718	{ 0x0821, 0x40 },
 719	{ 0x3088, 0x04 },
 720	{ 0x6813, 0x02 },
 721	{ 0x6835, 0x07 },
 722	{ 0x6836, 0x01 },
 723	{ 0x6837, 0x04 },
 724	{ 0x684d, 0x07 },
 725	{ 0x684e, 0x01 },
 726	{ 0x684f, 0x04 },
 727};
 728
 729static const struct imx355_reg mode_1284x720_regs[] = {
 730	{ 0x0112, 0x0a },
 731	{ 0x0113, 0x0a },
 732	{ 0x0114, 0x03 },
 733	{ 0x0342, 0x07 },
 734	{ 0x0343, 0x2c },
 735	{ 0x0340, 0x05 },
 736	{ 0x0341, 0x1a },
 737	{ 0x0344, 0x01 },
 738	{ 0x0345, 0x68 },
 739	{ 0x0346, 0x02 },
 740	{ 0x0347, 0x00 },
 741	{ 0x0348, 0x0b },
 742	{ 0x0349, 0x6f },
 743	{ 0x034a, 0x07 },
 744	{ 0x034b, 0x9f },
 745	{ 0x0220, 0x00 },
 746	{ 0x0222, 0x01 },
 747	{ 0x0900, 0x01 },
 748	{ 0x0901, 0x22 },
 749	{ 0x0902, 0x00 },
 750	{ 0x034c, 0x05 },
 751	{ 0x034d, 0x04 },
 752	{ 0x034e, 0x02 },
 753	{ 0x034f, 0xd0 },
 754	{ 0x0301, 0x05 },
 755	{ 0x0303, 0x01 },
 756	{ 0x0305, 0x02 },
 757	{ 0x0306, 0x00 },
 758	{ 0x0307, 0x78 },
 759	{ 0x030b, 0x01 },
 760	{ 0x030d, 0x02 },
 761	{ 0x030e, 0x00 },
 762	{ 0x030f, 0x4b },
 763	{ 0x0310, 0x00 },
 764	{ 0x0700, 0x00 },
 765	{ 0x0701, 0x10 },
 766	{ 0x0820, 0x0b },
 767	{ 0x0821, 0x40 },
 768	{ 0x3088, 0x04 },
 769	{ 0x6813, 0x02 },
 770	{ 0x6835, 0x07 },
 771	{ 0x6836, 0x01 },
 772	{ 0x6837, 0x04 },
 773	{ 0x684d, 0x07 },
 774	{ 0x684e, 0x01 },
 775	{ 0x684f, 0x04 },
 776};
 777
 778static const struct imx355_reg mode_1280x720_regs[] = {
 779	{ 0x0112, 0x0a },
 780	{ 0x0113, 0x0a },
 781	{ 0x0114, 0x03 },
 782	{ 0x0342, 0x07 },
 783	{ 0x0343, 0x2c },
 784	{ 0x0340, 0x05 },
 785	{ 0x0341, 0x1a },
 786	{ 0x0344, 0x01 },
 787	{ 0x0345, 0x68 },
 788	{ 0x0346, 0x02 },
 789	{ 0x0347, 0x00 },
 790	{ 0x0348, 0x0b },
 791	{ 0x0349, 0x67 },
 792	{ 0x034a, 0x07 },
 793	{ 0x034b, 0x9f },
 794	{ 0x0220, 0x00 },
 795	{ 0x0222, 0x01 },
 796	{ 0x0900, 0x01 },
 797	{ 0x0901, 0x22 },
 798	{ 0x0902, 0x00 },
 799	{ 0x034c, 0x05 },
 800	{ 0x034d, 0x00 },
 801	{ 0x034e, 0x02 },
 802	{ 0x034f, 0xd0 },
 803	{ 0x0301, 0x05 },
 804	{ 0x0303, 0x01 },
 805	{ 0x0305, 0x02 },
 806	{ 0x0306, 0x00 },
 807	{ 0x0307, 0x78 },
 808	{ 0x030b, 0x01 },
 809	{ 0x030d, 0x02 },
 810	{ 0x030e, 0x00 },
 811	{ 0x030f, 0x4b },
 812	{ 0x0310, 0x00 },
 813	{ 0x0700, 0x00 },
 814	{ 0x0701, 0x10 },
 815	{ 0x0820, 0x0b },
 816	{ 0x0821, 0x40 },
 817	{ 0x3088, 0x04 },
 818	{ 0x6813, 0x02 },
 819	{ 0x6835, 0x07 },
 820	{ 0x6836, 0x01 },
 821	{ 0x6837, 0x04 },
 822	{ 0x684d, 0x07 },
 823	{ 0x684e, 0x01 },
 824	{ 0x684f, 0x04 },
 825};
 826
 827static const struct imx355_reg mode_820x616_regs[] = {
 828	{ 0x0112, 0x0a },
 829	{ 0x0113, 0x0a },
 830	{ 0x0114, 0x03 },
 831	{ 0x0342, 0x0e },
 832	{ 0x0343, 0x58 },
 833	{ 0x0340, 0x02 },
 834	{ 0x0341, 0x8c },
 835	{ 0x0344, 0x00 },
 836	{ 0x0345, 0x00 },
 837	{ 0x0346, 0x00 },
 838	{ 0x0347, 0x00 },
 839	{ 0x0348, 0x0c },
 840	{ 0x0349, 0xcf },
 841	{ 0x034a, 0x09 },
 842	{ 0x034b, 0x9f },
 843	{ 0x0220, 0x00 },
 844	{ 0x0222, 0x01 },
 845	{ 0x0900, 0x01 },
 846	{ 0x0901, 0x44 },
 847	{ 0x0902, 0x00 },
 848	{ 0x034c, 0x03 },
 849	{ 0x034d, 0x34 },
 850	{ 0x034e, 0x02 },
 851	{ 0x034f, 0x68 },
 852	{ 0x0301, 0x05 },
 853	{ 0x0303, 0x01 },
 854	{ 0x0305, 0x02 },
 855	{ 0x0306, 0x00 },
 856	{ 0x0307, 0x78 },
 857	{ 0x030b, 0x01 },
 858	{ 0x030d, 0x02 },
 859	{ 0x030e, 0x00 },
 860	{ 0x030f, 0x4b },
 861	{ 0x0310, 0x00 },
 862	{ 0x0700, 0x02 },
 863	{ 0x0701, 0x78 },
 864	{ 0x0820, 0x0b },
 865	{ 0x0821, 0x40 },
 866	{ 0x3088, 0x04 },
 867	{ 0x6813, 0x02 },
 868	{ 0x6835, 0x07 },
 869	{ 0x6836, 0x01 },
 870	{ 0x6837, 0x04 },
 871	{ 0x684d, 0x07 },
 872	{ 0x684e, 0x01 },
 873	{ 0x684f, 0x04 },
 874};
 875
 876static const char * const imx355_test_pattern_menu[] = {
 877	"Disabled",
 878	"Solid Colour",
 879	"Eight Vertical Colour Bars",
 880	"Colour Bars With Fade to Grey",
 881	"Pseudorandom Sequence (PN9)",
 882};
 883
 884/*
 885 * When adding more than the one below, make sure the disallowed ones will
 886 * actually be disabled in the LINK_FREQ control.
 887 */
 888static const s64 link_freq_menu_items[] = {
 889	IMX355_LINK_FREQ_DEFAULT,
 890};
 891
 892/* Mode configs */
 893static const struct imx355_mode supported_modes[] = {
 894	{
 895		.width = 3280,
 896		.height = 2464,
 897		.fll_def = 2615,
 898		.fll_min = 2615,
 899		.llp = 3672,
 900		.link_freq_index = IMX355_LINK_FREQ_INDEX,
 901		.reg_list = {
 902			.num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
 903			.regs = mode_3280x2464_regs,
 904		},
 905	},
 906	{
 907		.width = 3268,
 908		.height = 2448,
 909		.fll_def = 2615,
 910		.fll_min = 2615,
 911		.llp = 3672,
 912		.link_freq_index = IMX355_LINK_FREQ_INDEX,
 913		.reg_list = {
 914			.num_of_regs = ARRAY_SIZE(mode_3268x2448_regs),
 915			.regs = mode_3268x2448_regs,
 916		},
 917	},
 918	{
 919		.width = 3264,
 920		.height = 2448,
 921		.fll_def = 2615,
 922		.fll_min = 2615,
 923		.llp = 3672,
 924		.link_freq_index = IMX355_LINK_FREQ_INDEX,
 925		.reg_list = {
 926			.num_of_regs = ARRAY_SIZE(mode_3264x2448_regs),
 927			.regs = mode_3264x2448_regs,
 928		},
 929	},
 930	{
 931		.width = 1940,
 932		.height = 1096,
 933		.fll_def = 1306,
 934		.fll_min = 1306,
 935		.llp = 3672,
 936		.link_freq_index = IMX355_LINK_FREQ_INDEX,
 937		.reg_list = {
 938			.num_of_regs = ARRAY_SIZE(mode_1940x1096_regs),
 939			.regs = mode_1940x1096_regs,
 940		},
 941	},
 942	{
 943		.width = 1936,
 944		.height = 1096,
 945		.fll_def = 1306,
 946		.fll_min = 1306,
 947		.llp = 3672,
 948		.link_freq_index = IMX355_LINK_FREQ_INDEX,
 949		.reg_list = {
 950			.num_of_regs = ARRAY_SIZE(mode_1936x1096_regs),
 951			.regs = mode_1936x1096_regs,
 952		},
 953	},
 954	{
 955		.width = 1924,
 956		.height = 1080,
 957		.fll_def = 1306,
 958		.fll_min = 1306,
 959		.llp = 3672,
 960		.link_freq_index = IMX355_LINK_FREQ_INDEX,
 961		.reg_list = {
 962			.num_of_regs = ARRAY_SIZE(mode_1924x1080_regs),
 963			.regs = mode_1924x1080_regs,
 964		},
 965	},
 966	{
 967		.width = 1920,
 968		.height = 1080,
 969		.fll_def = 1306,
 970		.fll_min = 1306,
 971		.llp = 3672,
 972		.link_freq_index = IMX355_LINK_FREQ_INDEX,
 973		.reg_list = {
 974			.num_of_regs = ARRAY_SIZE(mode_1920x1080_regs),
 975			.regs = mode_1920x1080_regs,
 976		},
 977	},
 978	{
 979		.width = 1640,
 980		.height = 1232,
 981		.fll_def = 1306,
 982		.fll_min = 1306,
 983		.llp = 1836,
 984		.link_freq_index = IMX355_LINK_FREQ_INDEX,
 985		.reg_list = {
 986			.num_of_regs = ARRAY_SIZE(mode_1640x1232_regs),
 987			.regs = mode_1640x1232_regs,
 988		},
 989	},
 990	{
 991		.width = 1640,
 992		.height = 922,
 993		.fll_def = 1306,
 994		.fll_min = 1306,
 995		.llp = 1836,
 996		.link_freq_index = IMX355_LINK_FREQ_INDEX,
 997		.reg_list = {
 998			.num_of_regs = ARRAY_SIZE(mode_1640x922_regs),
 999			.regs = mode_1640x922_regs,
1000		},
1001	},
1002	{
1003		.width = 1300,
1004		.height = 736,
1005		.fll_def = 1306,
1006		.fll_min = 1306,
1007		.llp = 1836,
1008		.link_freq_index = IMX355_LINK_FREQ_INDEX,
1009		.reg_list = {
1010			.num_of_regs = ARRAY_SIZE(mode_1300x736_regs),
1011			.regs = mode_1300x736_regs,
1012		},
1013	},
1014	{
1015		.width = 1296,
1016		.height = 736,
1017		.fll_def = 1306,
1018		.fll_min = 1306,
1019		.llp = 1836,
1020		.link_freq_index = IMX355_LINK_FREQ_INDEX,
1021		.reg_list = {
1022			.num_of_regs = ARRAY_SIZE(mode_1296x736_regs),
1023			.regs = mode_1296x736_regs,
1024		},
1025	},
1026	{
1027		.width = 1284,
1028		.height = 720,
1029		.fll_def = 1306,
1030		.fll_min = 1306,
1031		.llp = 1836,
1032		.link_freq_index = IMX355_LINK_FREQ_INDEX,
1033		.reg_list = {
1034			.num_of_regs = ARRAY_SIZE(mode_1284x720_regs),
1035			.regs = mode_1284x720_regs,
1036		},
1037	},
1038	{
1039		.width = 1280,
1040		.height = 720,
1041		.fll_def = 1306,
1042		.fll_min = 1306,
1043		.llp = 1836,
1044		.link_freq_index = IMX355_LINK_FREQ_INDEX,
1045		.reg_list = {
1046			.num_of_regs = ARRAY_SIZE(mode_1280x720_regs),
1047			.regs = mode_1280x720_regs,
1048		},
1049	},
1050	{
1051		.width = 820,
1052		.height = 616,
1053		.fll_def = 652,
1054		.fll_min = 652,
1055		.llp = 3672,
1056		.link_freq_index = IMX355_LINK_FREQ_INDEX,
1057		.reg_list = {
1058			.num_of_regs = ARRAY_SIZE(mode_820x616_regs),
1059			.regs = mode_820x616_regs,
1060		},
1061	},
1062};
1063
1064static inline struct imx355 *to_imx355(struct v4l2_subdev *_sd)
1065{
1066	return container_of(_sd, struct imx355, sd);
1067}
1068
1069/* Get bayer order based on flip setting. */
1070static u32 imx355_get_format_code(struct imx355 *imx355)
1071{
1072	/*
1073	 * Only one bayer order is supported.
1074	 * It depends on the flip settings.
1075	 */
1076	u32 code;
1077	static const u32 codes[2][2] = {
1078		{ MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, },
1079		{ MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, },
1080	};
1081
1082	lockdep_assert_held(&imx355->mutex);
1083	code = codes[imx355->vflip->val][imx355->hflip->val];
1084
1085	return code;
1086}
1087
1088/* Read registers up to 4 at a time */
1089static int imx355_read_reg(struct imx355 *imx355, u16 reg, u32 len, u32 *val)
1090{
1091	struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);
1092	struct i2c_msg msgs[2];
1093	u8 addr_buf[2];
1094	u8 data_buf[4] = { 0 };
1095	int ret;
1096
1097	if (len > 4)
1098		return -EINVAL;
1099
1100	put_unaligned_be16(reg, addr_buf);
1101	/* Write register address */
1102	msgs[0].addr = client->addr;
1103	msgs[0].flags = 0;
1104	msgs[0].len = ARRAY_SIZE(addr_buf);
1105	msgs[0].buf = addr_buf;
1106
1107	/* Read data from register */
1108	msgs[1].addr = client->addr;
1109	msgs[1].flags = I2C_M_RD;
1110	msgs[1].len = len;
1111	msgs[1].buf = &data_buf[4 - len];
1112
1113	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
1114	if (ret != ARRAY_SIZE(msgs))
1115		return -EIO;
1116
1117	*val = get_unaligned_be32(data_buf);
1118
1119	return 0;
1120}
1121
1122/* Write registers up to 4 at a time */
1123static int imx355_write_reg(struct imx355 *imx355, u16 reg, u32 len, u32 val)
1124{
1125	struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd);
1126	u8 buf[6];
1127
1128	if (len > 4)
1129		return -EINVAL;
1130
1131	put_unaligned_be16(reg, buf);
1132	put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
1133	if (i2c_master_send(client, buf, len + 2) != len + 2)
1134		return -EIO;
1135
1136	return 0;
1137}
1138
1139/* Write a list of registers */
1140static int imx355_write_regs(struct imx355 *imx355,
1141			     const struct imx355_reg *regs, u32 len)
1142{
1143	int ret;
1144	u32 i;
1145
1146	for (i = 0; i < len; i++) {
1147		ret = imx355_write_reg(imx355, regs[i].address, 1, regs[i].val);
1148		if (ret) {
1149			dev_err_ratelimited(imx355->dev,
1150					    "write reg 0x%4.4x return err %d",
1151					    regs[i].address, ret);
1152
1153			return ret;
1154		}
1155	}
1156
1157	return 0;
1158}
1159
1160/* Open sub-device */
1161static int imx355_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1162{
1163	struct imx355 *imx355 = to_imx355(sd);
1164	struct v4l2_mbus_framefmt *try_fmt =
1165		v4l2_subdev_state_get_format(fh->state, 0);
1166
1167	mutex_lock(&imx355->mutex);
1168
1169	/* Initialize try_fmt */
1170	try_fmt->width = imx355->cur_mode->width;
1171	try_fmt->height = imx355->cur_mode->height;
1172	try_fmt->code = imx355_get_format_code(imx355);
1173	try_fmt->field = V4L2_FIELD_NONE;
1174
1175	mutex_unlock(&imx355->mutex);
1176
1177	return 0;
1178}
1179
1180static int imx355_set_ctrl(struct v4l2_ctrl *ctrl)
1181{
1182	struct imx355 *imx355 = container_of(ctrl->handler,
1183					     struct imx355, ctrl_handler);
1184	s64 max;
1185	int ret;
1186
1187	/* Propagate change of current control to all related controls */
1188	switch (ctrl->id) {
1189	case V4L2_CID_VBLANK:
1190		/* Update max exposure while meeting expected vblanking */
1191		max = imx355->cur_mode->height + ctrl->val - 10;
1192		__v4l2_ctrl_modify_range(imx355->exposure,
1193					 imx355->exposure->minimum,
1194					 max, imx355->exposure->step, max);
1195		break;
1196	}
1197
1198	/*
1199	 * Applying V4L2 control value only happens
1200	 * when power is up for streaming
1201	 */
1202	if (!pm_runtime_get_if_in_use(imx355->dev))
1203		return 0;
1204
1205	switch (ctrl->id) {
1206	case V4L2_CID_ANALOGUE_GAIN:
1207		/* Analog gain = 1024/(1024 - ctrl->val) times */
1208		ret = imx355_write_reg(imx355, IMX355_REG_ANALOG_GAIN, 2,
1209				       ctrl->val);
1210		break;
1211	case V4L2_CID_DIGITAL_GAIN:
1212		ret = imx355_write_reg(imx355, IMX355_REG_DIG_GAIN_GLOBAL, 2,
1213				       ctrl->val);
1214		break;
1215	case V4L2_CID_EXPOSURE:
1216		ret = imx355_write_reg(imx355, IMX355_REG_EXPOSURE, 2,
1217				       ctrl->val);
1218		break;
1219	case V4L2_CID_VBLANK:
1220		/* Update FLL that meets expected vertical blanking */
1221		ret = imx355_write_reg(imx355, IMX355_REG_FLL, 2,
1222				       imx355->cur_mode->height + ctrl->val);
1223		break;
1224	case V4L2_CID_TEST_PATTERN:
1225		ret = imx355_write_reg(imx355, IMX355_REG_TEST_PATTERN,
1226				       2, ctrl->val);
1227		break;
1228	case V4L2_CID_HFLIP:
1229	case V4L2_CID_VFLIP:
1230		ret = imx355_write_reg(imx355, IMX355_REG_ORIENTATION, 1,
1231				       imx355->hflip->val |
1232				       imx355->vflip->val << 1);
1233		break;
1234	default:
1235		ret = -EINVAL;
1236		dev_info(imx355->dev, "ctrl(id:0x%x,val:0x%x) is not handled",
1237			 ctrl->id, ctrl->val);
1238		break;
1239	}
1240
1241	pm_runtime_put(imx355->dev);
1242
1243	return ret;
1244}
1245
1246static const struct v4l2_ctrl_ops imx355_ctrl_ops = {
1247	.s_ctrl = imx355_set_ctrl,
1248};
1249
1250static int imx355_enum_mbus_code(struct v4l2_subdev *sd,
1251				 struct v4l2_subdev_state *sd_state,
1252				 struct v4l2_subdev_mbus_code_enum *code)
1253{
1254	struct imx355 *imx355 = to_imx355(sd);
1255
1256	if (code->index > 0)
1257		return -EINVAL;
1258
1259	mutex_lock(&imx355->mutex);
1260	code->code = imx355_get_format_code(imx355);
1261	mutex_unlock(&imx355->mutex);
1262
1263	return 0;
1264}
1265
1266static int imx355_enum_frame_size(struct v4l2_subdev *sd,
1267				  struct v4l2_subdev_state *sd_state,
1268				  struct v4l2_subdev_frame_size_enum *fse)
1269{
1270	struct imx355 *imx355 = to_imx355(sd);
1271
1272	if (fse->index >= ARRAY_SIZE(supported_modes))
1273		return -EINVAL;
1274
1275	mutex_lock(&imx355->mutex);
1276	if (fse->code != imx355_get_format_code(imx355)) {
1277		mutex_unlock(&imx355->mutex);
1278		return -EINVAL;
1279	}
1280	mutex_unlock(&imx355->mutex);
1281
1282	fse->min_width = supported_modes[fse->index].width;
1283	fse->max_width = fse->min_width;
1284	fse->min_height = supported_modes[fse->index].height;
1285	fse->max_height = fse->min_height;
1286
1287	return 0;
1288}
1289
1290static void imx355_update_pad_format(struct imx355 *imx355,
1291				     const struct imx355_mode *mode,
1292				     struct v4l2_subdev_format *fmt)
1293{
1294	fmt->format.width = mode->width;
1295	fmt->format.height = mode->height;
1296	fmt->format.code = imx355_get_format_code(imx355);
1297	fmt->format.field = V4L2_FIELD_NONE;
1298}
1299
1300static int imx355_do_get_pad_format(struct imx355 *imx355,
1301				    struct v4l2_subdev_state *sd_state,
1302				    struct v4l2_subdev_format *fmt)
1303{
1304	struct v4l2_mbus_framefmt *framefmt;
1305
1306	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1307		framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
1308		fmt->format = *framefmt;
1309	} else {
1310		imx355_update_pad_format(imx355, imx355->cur_mode, fmt);
1311	}
1312
1313	return 0;
1314}
1315
1316static int imx355_get_pad_format(struct v4l2_subdev *sd,
1317				 struct v4l2_subdev_state *sd_state,
1318				 struct v4l2_subdev_format *fmt)
1319{
1320	struct imx355 *imx355 = to_imx355(sd);
1321	int ret;
1322
1323	mutex_lock(&imx355->mutex);
1324	ret = imx355_do_get_pad_format(imx355, sd_state, fmt);
1325	mutex_unlock(&imx355->mutex);
1326
1327	return ret;
1328}
1329
1330static int
1331imx355_set_pad_format(struct v4l2_subdev *sd,
1332		      struct v4l2_subdev_state *sd_state,
1333		      struct v4l2_subdev_format *fmt)
1334{
1335	struct imx355 *imx355 = to_imx355(sd);
1336	const struct imx355_mode *mode;
1337	struct v4l2_mbus_framefmt *framefmt;
1338	s32 vblank_def;
1339	s32 vblank_min;
1340	s64 h_blank;
1341	u64 pixel_rate;
1342	u32 height;
1343
1344	mutex_lock(&imx355->mutex);
1345
1346	/*
1347	 * Only one bayer order is supported.
1348	 * It depends on the flip settings.
1349	 */
1350	fmt->format.code = imx355_get_format_code(imx355);
1351
1352	mode = v4l2_find_nearest_size(supported_modes,
1353				      ARRAY_SIZE(supported_modes),
1354				      width, height,
1355				      fmt->format.width, fmt->format.height);
1356	imx355_update_pad_format(imx355, mode, fmt);
1357	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
1358		framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad);
1359		*framefmt = fmt->format;
1360	} else {
1361		imx355->cur_mode = mode;
1362		pixel_rate = IMX355_LINK_FREQ_DEFAULT * 2 * 4;
1363		do_div(pixel_rate, 10);
1364		__v4l2_ctrl_s_ctrl_int64(imx355->pixel_rate, pixel_rate);
1365		/* Update limits and set FPS to default */
1366		height = imx355->cur_mode->height;
1367		vblank_def = imx355->cur_mode->fll_def - height;
1368		vblank_min = imx355->cur_mode->fll_min - height;
1369		height = IMX355_FLL_MAX - height;
1370		__v4l2_ctrl_modify_range(imx355->vblank, vblank_min, height, 1,
1371					 vblank_def);
1372		__v4l2_ctrl_s_ctrl(imx355->vblank, vblank_def);
1373		h_blank = mode->llp - imx355->cur_mode->width;
1374		/*
1375		 * Currently hblank is not changeable.
1376		 * So FPS control is done only by vblank.
1377		 */
1378		__v4l2_ctrl_modify_range(imx355->hblank, h_blank,
1379					 h_blank, 1, h_blank);
1380	}
1381
1382	mutex_unlock(&imx355->mutex);
1383
1384	return 0;
1385}
1386
1387/* Start streaming */
1388static int imx355_start_streaming(struct imx355 *imx355)
1389{
1390	const struct imx355_reg_list *reg_list;
1391	int ret;
1392
1393	/* Global Setting */
1394	reg_list = &imx355_global_setting;
1395	ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs);
1396	if (ret) {
1397		dev_err(imx355->dev, "failed to set global settings");
1398		return ret;
1399	}
1400
1401	/* Apply default values of current mode */
1402	reg_list = &imx355->cur_mode->reg_list;
1403	ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs);
1404	if (ret) {
1405		dev_err(imx355->dev, "failed to set mode");
1406		return ret;
1407	}
1408
1409	/* set digital gain control to all color mode */
1410	ret = imx355_write_reg(imx355, IMX355_REG_DPGA_USE_GLOBAL_GAIN, 1, 1);
1411	if (ret)
1412		return ret;
1413
1414	/* Apply customized values from user */
1415	ret =  __v4l2_ctrl_handler_setup(imx355->sd.ctrl_handler);
1416	if (ret)
1417		return ret;
1418
1419	return imx355_write_reg(imx355, IMX355_REG_MODE_SELECT,
1420				1, IMX355_MODE_STREAMING);
1421}
1422
1423/* Stop streaming */
1424static int imx355_stop_streaming(struct imx355 *imx355)
1425{
1426	return imx355_write_reg(imx355, IMX355_REG_MODE_SELECT,
1427				1, IMX355_MODE_STANDBY);
1428}
1429
1430static int imx355_set_stream(struct v4l2_subdev *sd, int enable)
1431{
1432	struct imx355 *imx355 = to_imx355(sd);
1433	int ret = 0;
1434
1435	mutex_lock(&imx355->mutex);
1436
1437	if (enable) {
1438		ret = pm_runtime_resume_and_get(imx355->dev);
1439		if (ret < 0)
1440			goto err_unlock;
1441
1442		/*
1443		 * Apply default & customized values
1444		 * and then start streaming.
1445		 */
1446		ret = imx355_start_streaming(imx355);
1447		if (ret)
1448			goto err_rpm_put;
1449	} else {
1450		imx355_stop_streaming(imx355);
1451		pm_runtime_put(imx355->dev);
1452	}
1453
1454	/* vflip and hflip cannot change during streaming */
1455	__v4l2_ctrl_grab(imx355->vflip, enable);
1456	__v4l2_ctrl_grab(imx355->hflip, enable);
1457
1458	mutex_unlock(&imx355->mutex);
1459
1460	return ret;
1461
1462err_rpm_put:
1463	pm_runtime_put(imx355->dev);
1464err_unlock:
1465	mutex_unlock(&imx355->mutex);
1466
1467	return ret;
1468}
1469
1470/* Verify chip ID */
1471static int imx355_identify_module(struct imx355 *imx355)
1472{
1473	int ret;
1474	u32 val;
1475
1476	ret = imx355_read_reg(imx355, IMX355_REG_CHIP_ID, 2, &val);
1477	if (ret)
1478		return ret;
1479
1480	if (val != IMX355_CHIP_ID) {
1481		dev_err(imx355->dev, "chip id mismatch: %x!=%x",
1482			IMX355_CHIP_ID, val);
1483		return -EIO;
1484	}
1485	return 0;
1486}
1487
1488static const struct v4l2_subdev_core_ops imx355_subdev_core_ops = {
1489	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
1490	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
1491};
1492
1493static const struct v4l2_subdev_video_ops imx355_video_ops = {
1494	.s_stream = imx355_set_stream,
1495};
1496
1497static const struct v4l2_subdev_pad_ops imx355_pad_ops = {
1498	.enum_mbus_code = imx355_enum_mbus_code,
1499	.get_fmt = imx355_get_pad_format,
1500	.set_fmt = imx355_set_pad_format,
1501	.enum_frame_size = imx355_enum_frame_size,
1502};
1503
1504static const struct v4l2_subdev_ops imx355_subdev_ops = {
1505	.core = &imx355_subdev_core_ops,
1506	.video = &imx355_video_ops,
1507	.pad = &imx355_pad_ops,
1508};
1509
1510static const struct media_entity_operations imx355_subdev_entity_ops = {
1511	.link_validate = v4l2_subdev_link_validate,
1512};
1513
1514static const struct v4l2_subdev_internal_ops imx355_internal_ops = {
1515	.open = imx355_open,
1516};
1517
1518/* Initialize control handlers */
1519static int imx355_init_controls(struct imx355 *imx355)
1520{
1521	struct v4l2_fwnode_device_properties props;
1522	struct v4l2_ctrl_handler *ctrl_hdlr;
1523	s64 exposure_max;
1524	s64 vblank_def;
1525	s64 vblank_min;
1526	s64 hblank;
1527	u64 pixel_rate;
1528	const struct imx355_mode *mode;
1529	u32 max;
1530	int ret;
1531
1532	ctrl_hdlr = &imx355->ctrl_handler;
1533	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
1534	if (ret)
1535		return ret;
1536
1537	ctrl_hdlr->lock = &imx355->mutex;
1538	max = ARRAY_SIZE(link_freq_menu_items) - 1;
1539	imx355->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx355_ctrl_ops,
1540						   V4L2_CID_LINK_FREQ, max, 0,
1541						   link_freq_menu_items);
1542	if (imx355->link_freq)
1543		imx355->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1544
1545	/* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
1546	pixel_rate = IMX355_LINK_FREQ_DEFAULT * 2 * 4;
1547	do_div(pixel_rate, 10);
1548	/* By default, PIXEL_RATE is read only */
1549	imx355->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
1550					       V4L2_CID_PIXEL_RATE, pixel_rate,
1551					       pixel_rate, 1, pixel_rate);
1552
1553	/* Initialize vblank/hblank/exposure parameters based on current mode */
1554	mode = imx355->cur_mode;
1555	vblank_def = mode->fll_def - mode->height;
1556	vblank_min = mode->fll_min - mode->height;
1557	imx355->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
1558					   V4L2_CID_VBLANK, vblank_min,
1559					   IMX355_FLL_MAX - mode->height,
1560					   1, vblank_def);
1561
1562	hblank = mode->llp - mode->width;
1563	imx355->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
1564					   V4L2_CID_HBLANK, hblank, hblank,
1565					   1, hblank);
1566	if (imx355->hblank)
1567		imx355->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1568
1569	/* fll >= exposure time + adjust parameter (default value is 10) */
1570	exposure_max = mode->fll_def - 10;
1571	imx355->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
1572					     V4L2_CID_EXPOSURE,
1573					     IMX355_EXPOSURE_MIN, exposure_max,
1574					     IMX355_EXPOSURE_STEP,
1575					     IMX355_EXPOSURE_DEFAULT);
1576
1577	imx355->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
1578					  V4L2_CID_HFLIP, 0, 1, 1, 0);
1579	if (imx355->hflip)
1580		imx355->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
1581	imx355->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops,
1582					  V4L2_CID_VFLIP, 0, 1, 1, 0);
1583	if (imx355->vflip)
1584		imx355->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
1585
1586	v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
1587			  IMX355_ANA_GAIN_MIN, IMX355_ANA_GAIN_MAX,
1588			  IMX355_ANA_GAIN_STEP, IMX355_ANA_GAIN_DEFAULT);
1589
1590	/* Digital gain */
1591	v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
1592			  IMX355_DGTL_GAIN_MIN, IMX355_DGTL_GAIN_MAX,
1593			  IMX355_DGTL_GAIN_STEP, IMX355_DGTL_GAIN_DEFAULT);
1594
1595	v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx355_ctrl_ops,
1596				     V4L2_CID_TEST_PATTERN,
1597				     ARRAY_SIZE(imx355_test_pattern_menu) - 1,
1598				     0, 0, imx355_test_pattern_menu);
1599	if (ctrl_hdlr->error) {
1600		ret = ctrl_hdlr->error;
1601		dev_err(imx355->dev, "control init failed: %d", ret);
1602		goto error;
1603	}
1604
1605	ret = v4l2_fwnode_device_parse(imx355->dev, &props);
1606	if (ret)
1607		goto error;
1608
1609	ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx355_ctrl_ops,
1610					      &props);
1611	if (ret)
1612		goto error;
1613
1614	imx355->sd.ctrl_handler = ctrl_hdlr;
1615
1616	return 0;
1617
1618error:
1619	v4l2_ctrl_handler_free(ctrl_hdlr);
1620
1621	return ret;
1622}
1623
1624static struct imx355_hwcfg *imx355_get_hwcfg(struct device *dev)
1625{
1626	struct imx355_hwcfg *cfg;
1627	struct v4l2_fwnode_endpoint bus_cfg = {
1628		.bus_type = V4L2_MBUS_CSI2_DPHY
1629	};
1630	struct fwnode_handle *ep;
1631	struct fwnode_handle *fwnode = dev_fwnode(dev);
1632	int ret;
1633
1634	if (!fwnode)
1635		return NULL;
1636
1637	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
1638	if (!ep)
1639		return NULL;
1640
1641	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
1642	if (ret)
1643		goto out_err;
1644
1645	cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL);
1646	if (!cfg)
1647		goto out_err;
1648
1649	ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies,
1650				       bus_cfg.nr_of_link_frequencies,
1651				       link_freq_menu_items,
1652				       ARRAY_SIZE(link_freq_menu_items),
1653				       &cfg->link_freq_bitmap);
1654	if (ret)
1655		goto out_err;
1656
1657	v4l2_fwnode_endpoint_free(&bus_cfg);
1658	fwnode_handle_put(ep);
1659	return cfg;
1660
1661out_err:
1662	v4l2_fwnode_endpoint_free(&bus_cfg);
1663	fwnode_handle_put(ep);
1664	return NULL;
1665}
1666
1667static int imx355_probe(struct i2c_client *client)
1668{
1669	struct imx355 *imx355;
1670	unsigned long freq;
1671	int ret;
1672
1673	imx355 = devm_kzalloc(&client->dev, sizeof(*imx355), GFP_KERNEL);
1674	if (!imx355)
1675		return -ENOMEM;
1676
1677	imx355->dev = &client->dev;
1678
1679	mutex_init(&imx355->mutex);
1680
1681	imx355->clk = devm_v4l2_sensor_clk_get(imx355->dev, NULL);
1682	if (IS_ERR(imx355->clk))
1683		return dev_err_probe(imx355->dev, PTR_ERR(imx355->clk),
1684				     "failed to get clock\n");
1685
1686	freq = clk_get_rate(imx355->clk);
1687	if (freq != IMX355_EXT_CLK)
1688		return dev_err_probe(imx355->dev, -EINVAL,
1689				     "external clock %lu is not supported\n",
1690				     freq);
1691
1692	/* Initialize subdev */
1693	v4l2_i2c_subdev_init(&imx355->sd, client, &imx355_subdev_ops);
1694
1695	/* Check module identity */
1696	ret = imx355_identify_module(imx355);
1697	if (ret) {
1698		dev_err(imx355->dev, "failed to find sensor: %d", ret);
1699		goto error_probe;
1700	}
1701
1702	imx355->hwcfg = imx355_get_hwcfg(imx355->dev);
1703	if (!imx355->hwcfg) {
1704		dev_err(imx355->dev, "failed to get hwcfg");
1705		ret = -ENODEV;
1706		goto error_probe;
1707	}
1708
1709	/* Set default mode to max resolution */
1710	imx355->cur_mode = &supported_modes[0];
1711
1712	ret = imx355_init_controls(imx355);
1713	if (ret) {
1714		dev_err(imx355->dev, "failed to init controls: %d", ret);
1715		goto error_probe;
1716	}
1717
1718	/* Initialize subdev */
1719	imx355->sd.internal_ops = &imx355_internal_ops;
1720	imx355->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
1721		V4L2_SUBDEV_FL_HAS_EVENTS;
1722	imx355->sd.entity.ops = &imx355_subdev_entity_ops;
1723	imx355->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
1724
1725	/* Initialize source pad */
1726	imx355->pad.flags = MEDIA_PAD_FL_SOURCE;
1727	ret = media_entity_pads_init(&imx355->sd.entity, 1, &imx355->pad);
1728	if (ret) {
1729		dev_err(imx355->dev, "failed to init entity pads: %d", ret);
1730		goto error_handler_free;
1731	}
1732
1733	/*
1734	 * Device is already turned on by i2c-core with ACPI domain PM.
1735	 * Enable runtime PM and turn off the device.
1736	 */
1737	pm_runtime_set_active(imx355->dev);
1738	pm_runtime_enable(imx355->dev);
1739	pm_runtime_idle(imx355->dev);
1740
1741	ret = v4l2_async_register_subdev_sensor(&imx355->sd);
1742	if (ret < 0)
1743		goto error_media_entity_runtime_pm;
1744
1745	return 0;
1746
1747error_media_entity_runtime_pm:
1748	pm_runtime_disable(imx355->dev);
1749	pm_runtime_set_suspended(imx355->dev);
1750	media_entity_cleanup(&imx355->sd.entity);
1751
1752error_handler_free:
1753	v4l2_ctrl_handler_free(imx355->sd.ctrl_handler);
1754
1755error_probe:
1756	mutex_destroy(&imx355->mutex);
1757
1758	return ret;
1759}
1760
1761static void imx355_remove(struct i2c_client *client)
1762{
1763	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1764	struct imx355 *imx355 = to_imx355(sd);
1765
1766	v4l2_async_unregister_subdev(sd);
1767	media_entity_cleanup(&sd->entity);
1768	v4l2_ctrl_handler_free(sd->ctrl_handler);
1769
1770	pm_runtime_disable(imx355->dev);
1771	pm_runtime_set_suspended(imx355->dev);
1772
1773	mutex_destroy(&imx355->mutex);
1774}
1775
1776static const struct acpi_device_id imx355_acpi_ids[] __maybe_unused = {
1777	{ "SONY355A" },
1778	{ /* sentinel */ }
1779};
1780MODULE_DEVICE_TABLE(acpi, imx355_acpi_ids);
1781
1782static struct i2c_driver imx355_i2c_driver = {
1783	.driver = {
1784		.name = "imx355",
1785		.acpi_match_table = ACPI_PTR(imx355_acpi_ids),
1786	},
1787	.probe = imx355_probe,
1788	.remove = imx355_remove,
1789};
1790module_i2c_driver(imx355_i2c_driver);
1791
1792MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");
1793MODULE_AUTHOR("Rapolu, Chiranjeevi");
1794MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
1795MODULE_AUTHOR("Yang, Hyungwoo");
1796MODULE_DESCRIPTION("Sony imx355 sensor driver");
1797MODULE_LICENSE("GPL v2");
~/ Read-only file preview.