cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hi846.c (53908B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (c) 2021 Purism SPC
      3
      4#include <asm/unaligned.h>
      5#include <linux/clk.h>
      6#include <linux/delay.h>
      7#include <linux/gpio/consumer.h>
      8#include <linux/i2c.h>
      9#include <linux/module.h>
     10#include <linux/pm_runtime.h>
     11#include <linux/pm.h>
     12#include <linux/property.h>
     13#include <linux/regulator/consumer.h>
     14#include <media/v4l2-ctrls.h>
     15#include <media/v4l2-device.h>
     16#include <media/v4l2-fwnode.h>
     17
     18#define HI846_MEDIA_BUS_FORMAT		MEDIA_BUS_FMT_SGBRG10_1X10
     19#define HI846_RGB_DEPTH			10
     20
     21/* Frame length lines / vertical timings */
     22#define HI846_REG_FLL			0x0006
     23#define HI846_FLL_MAX			0xffff
     24
     25/* Horizontal timing */
     26#define HI846_REG_LLP			0x0008
     27#define HI846_LINE_LENGTH		3800
     28
     29#define HI846_REG_BINNING_MODE		0x000c
     30
     31#define HI846_REG_IMAGE_ORIENTATION	0x000e
     32
     33#define HI846_REG_UNKNOWN_0022		0x0022
     34
     35#define HI846_REG_Y_ADDR_START_VACT_H	0x0026
     36#define HI846_REG_Y_ADDR_START_VACT_L	0x0027
     37#define HI846_REG_UNKNOWN_0028		0x0028
     38
     39#define HI846_REG_Y_ADDR_END_VACT_H	0x002c
     40#define HI846_REG_Y_ADDR_END_VACT_L	0x002d
     41
     42#define HI846_REG_Y_ODD_INC_FOBP	0x002e
     43#define HI846_REG_Y_EVEN_INC_FOBP	0x002f
     44
     45#define HI846_REG_Y_ODD_INC_VACT	0x0032
     46#define HI846_REG_Y_EVEN_INC_VACT	0x0033
     47
     48#define HI846_REG_GROUPED_PARA_HOLD	0x0046
     49
     50#define HI846_REG_TG_ENABLE		0x004c
     51
     52#define HI846_REG_UNKNOWN_005C		0x005c
     53
     54#define HI846_REG_UNKNOWN_006A		0x006a
     55
     56/*
     57 * Long exposure time. Actually, exposure is a 20 bit value that
     58 * includes the lower 4 bits of 0x0073 too. Only 16 bits are used
     59 * right now
     60 */
     61#define HI846_REG_EXPOSURE		0x0074
     62#define HI846_EXPOSURE_MIN		6
     63#define HI846_EXPOSURE_MAX_MARGIN	2
     64#define HI846_EXPOSURE_STEP		1
     65
     66/* Analog gain controls from sensor */
     67#define HI846_REG_ANALOG_GAIN		0x0077
     68#define HI846_ANAL_GAIN_MIN		0
     69#define HI846_ANAL_GAIN_MAX		240
     70#define HI846_ANAL_GAIN_STEP		8
     71
     72/* Digital gain controls from sensor */
     73#define HI846_REG_MWB_GR_GAIN_H		0x0078
     74#define HI846_REG_MWB_GR_GAIN_L		0x0079
     75#define HI846_REG_MWB_GB_GAIN_H		0x007a
     76#define HI846_REG_MWB_GB_GAIN_L		0x007b
     77#define HI846_REG_MWB_R_GAIN_H		0x007c
     78#define HI846_REG_MWB_R_GAIN_L		0x007d
     79#define HI846_REG_MWB_B_GAIN_H		0x007e
     80#define HI846_REG_MWB_B_GAIN_L		0x007f
     81#define HI846_DGTL_GAIN_MIN		512
     82#define HI846_DGTL_GAIN_MAX		8191
     83#define HI846_DGTL_GAIN_STEP		1
     84#define HI846_DGTL_GAIN_DEFAULT		512
     85
     86#define HI846_REG_X_ADDR_START_HACT_H	0x0120
     87#define HI846_REG_X_ADDR_END_HACT_H	0x0122
     88
     89#define HI846_REG_UNKNOWN_012A		0x012a
     90
     91#define HI846_REG_UNKNOWN_0200		0x0200
     92
     93#define HI846_REG_UNKNOWN_021C		0x021c
     94#define HI846_REG_UNKNOWN_021E		0x021e
     95
     96#define HI846_REG_UNKNOWN_0402		0x0402
     97#define HI846_REG_UNKNOWN_0404		0x0404
     98#define HI846_REG_UNKNOWN_0408		0x0408
     99#define HI846_REG_UNKNOWN_0410		0x0410
    100#define HI846_REG_UNKNOWN_0412		0x0412
    101#define HI846_REG_UNKNOWN_0414		0x0414
    102
    103#define HI846_REG_UNKNOWN_0418		0x0418
    104
    105#define HI846_REG_UNKNOWN_051E		0x051e
    106
    107/* Formatter */
    108#define HI846_REG_X_START_H		0x0804
    109#define HI846_REG_X_START_L		0x0805
    110
    111/* MIPI */
    112#define HI846_REG_UNKNOWN_0900		0x0900
    113#define HI846_REG_MIPI_TX_OP_EN		0x0901
    114#define HI846_REG_MIPI_TX_OP_MODE	0x0902
    115#define HI846_RAW8			BIT(5)
    116
    117#define HI846_REG_UNKNOWN_090C		0x090c
    118#define HI846_REG_UNKNOWN_090E		0x090e
    119
    120#define HI846_REG_UNKNOWN_0914		0x0914
    121#define HI846_REG_TLPX			0x0915
    122#define HI846_REG_TCLK_PREPARE		0x0916
    123#define HI846_REG_TCLK_ZERO		0x0917
    124#define HI846_REG_UNKNOWN_0918		0x0918
    125#define HI846_REG_THS_PREPARE		0x0919
    126#define HI846_REG_THS_ZERO		0x091a
    127#define HI846_REG_THS_TRAIL		0x091b
    128#define HI846_REG_TCLK_POST		0x091c
    129#define HI846_REG_TCLK_TRAIL_MIN	0x091d
    130#define HI846_REG_UNKNOWN_091E		0x091e
    131
    132#define HI846_REG_UNKNOWN_0954		0x0954
    133#define HI846_REG_UNKNOWN_0956		0x0956
    134#define HI846_REG_UNKNOWN_0958		0x0958
    135#define HI846_REG_UNKNOWN_095A		0x095a
    136
    137/* ISP Common */
    138#define HI846_REG_MODE_SELECT		0x0a00
    139#define HI846_MODE_STANDBY		0x00
    140#define HI846_MODE_STREAMING		0x01
    141#define HI846_REG_FAST_STANDBY_MODE	0x0a02
    142#define HI846_REG_ISP_EN_H		0x0a04
    143
    144/* Test Pattern Control */
    145#define HI846_REG_ISP			0x0a05
    146#define HI846_REG_ISP_TPG_EN		0x01
    147#define HI846_REG_TEST_PATTERN		0x020a /* 1-9 */
    148
    149#define HI846_REG_UNKNOWN_0A0C		0x0a0c
    150
    151/* Windowing */
    152#define HI846_REG_X_OUTPUT_SIZE_H	0x0a12
    153#define HI846_REG_X_OUTPUT_SIZE_L	0x0a13
    154#define HI846_REG_Y_OUTPUT_SIZE_H	0x0a14
    155#define HI846_REG_Y_OUTPUT_SIZE_L	0x0a15
    156
    157/* ISP Common */
    158#define HI846_REG_PEDESTAL_EN		0x0a1a
    159
    160#define HI846_REG_UNKNOWN_0A1E		0x0a1e
    161
    162/* Horizontal Binning Mode */
    163#define HI846_REG_HBIN_MODE		0x0a22
    164
    165#define HI846_REG_UNKNOWN_0A24		0x0a24
    166#define HI846_REG_UNKNOWN_0B02		0x0b02
    167#define HI846_REG_UNKNOWN_0B10		0x0b10
    168#define HI846_REG_UNKNOWN_0B12		0x0b12
    169#define HI846_REG_UNKNOWN_0B14		0x0b14
    170
    171/* BLC (Black Level Calibration) */
    172#define HI846_REG_BLC_CTL0		0x0c00
    173
    174#define HI846_REG_UNKNOWN_0C06		0x0c06
    175#define HI846_REG_UNKNOWN_0C10		0x0c10
    176#define HI846_REG_UNKNOWN_0C12		0x0c12
    177#define HI846_REG_UNKNOWN_0C14		0x0c14
    178#define HI846_REG_UNKNOWN_0C16		0x0c16
    179
    180#define HI846_REG_UNKNOWN_0E04		0x0e04
    181
    182#define HI846_REG_CHIP_ID_L		0x0f16
    183#define HI846_REG_CHIP_ID_H		0x0f17
    184#define HI846_CHIP_ID_L			0x46
    185#define HI846_CHIP_ID_H			0x08
    186
    187#define HI846_REG_UNKNOWN_0F04		0x0f04
    188#define HI846_REG_UNKNOWN_0F08		0x0f08
    189
    190/* PLL */
    191#define HI846_REG_PLL_CFG_MIPI2_H	0x0f2a
    192#define HI846_REG_PLL_CFG_MIPI2_L	0x0f2b
    193
    194#define HI846_REG_UNKNOWN_0F30		0x0f30
    195#define HI846_REG_PLL_CFG_RAMP1_H	0x0f32
    196#define HI846_REG_UNKNOWN_0F36		0x0f36
    197#define HI846_REG_PLL_CFG_MIPI1_H	0x0f38
    198
    199#define HI846_REG_UNKNOWN_2008		0x2008
    200#define HI846_REG_UNKNOWN_326E		0x326e
    201
    202struct hi846_reg {
    203	u16 address;
    204	u16 val;
    205};
    206
    207struct hi846_reg_list {
    208	u32 num_of_regs;
    209	const struct hi846_reg *regs;
    210};
    211
    212struct hi846_mode {
    213	/* Frame width in pixels */
    214	u32 width;
    215
    216	/* Frame height in pixels */
    217	u32 height;
    218
    219	/* Horizontal timing size */
    220	u32 llp;
    221
    222	/* Link frequency needed for this resolution */
    223	u8 link_freq_index;
    224
    225	u16 fps;
    226
    227	/* Vertical timining size */
    228	u16 frame_len;
    229
    230	const struct hi846_reg_list reg_list_config;
    231	const struct hi846_reg_list reg_list_2lane;
    232	const struct hi846_reg_list reg_list_4lane;
    233
    234	/* Position inside of the 3264x2448 pixel array */
    235	struct v4l2_rect crop;
    236};
    237
    238static const struct hi846_reg hi846_init_2lane[] = {
    239	{HI846_REG_MODE_SELECT,		0x0000},
    240	/* regs below are unknown */
    241	{0x2000, 0x100a},
    242	{0x2002, 0x00ff},
    243	{0x2004, 0x0007},
    244	{0x2006, 0x3fff},
    245	{0x2008, 0x3fff},
    246	{0x200a, 0xc216},
    247	{0x200c, 0x1292},
    248	{0x200e, 0xc01a},
    249	{0x2010, 0x403d},
    250	{0x2012, 0x000e},
    251	{0x2014, 0x403e},
    252	{0x2016, 0x0b80},
    253	{0x2018, 0x403f},
    254	{0x201a, 0x82ae},
    255	{0x201c, 0x1292},
    256	{0x201e, 0xc00c},
    257	{0x2020, 0x4130},
    258	{0x2022, 0x43e2},
    259	{0x2024, 0x0180},
    260	{0x2026, 0x4130},
    261	{0x2028, 0x7400},
    262	{0x202a, 0x5000},
    263	{0x202c, 0x0253},
    264	{0x202e, 0x0ad1},
    265	{0x2030, 0x2360},
    266	{0x2032, 0x0009},
    267	{0x2034, 0x5020},
    268	{0x2036, 0x000b},
    269	{0x2038, 0x0002},
    270	{0x203a, 0x0044},
    271	{0x203c, 0x0016},
    272	{0x203e, 0x1792},
    273	{0x2040, 0x7002},
    274	{0x2042, 0x154f},
    275	{0x2044, 0x00d5},
    276	{0x2046, 0x000b},
    277	{0x2048, 0x0019},
    278	{0x204a, 0x1698},
    279	{0x204c, 0x000e},
    280	{0x204e, 0x099a},
    281	{0x2050, 0x0058},
    282	{0x2052, 0x7000},
    283	{0x2054, 0x1799},
    284	{0x2056, 0x0310},
    285	{0x2058, 0x03c3},
    286	{0x205a, 0x004c},
    287	{0x205c, 0x064a},
    288	{0x205e, 0x0001},
    289	{0x2060, 0x0007},
    290	{0x2062, 0x0bc7},
    291	{0x2064, 0x0055},
    292	{0x2066, 0x7000},
    293	{0x2068, 0x1550},
    294	{0x206a, 0x158a},
    295	{0x206c, 0x0004},
    296	{0x206e, 0x1488},
    297	{0x2070, 0x7010},
    298	{0x2072, 0x1508},
    299	{0x2074, 0x0004},
    300	{0x2076, 0x0016},
    301	{0x2078, 0x03d5},
    302	{0x207a, 0x0055},
    303	{0x207c, 0x08ca},
    304	{0x207e, 0x2019},
    305	{0x2080, 0x0007},
    306	{0x2082, 0x7057},
    307	{0x2084, 0x0fc7},
    308	{0x2086, 0x5041},
    309	{0x2088, 0x12c8},
    310	{0x208a, 0x5060},
    311	{0x208c, 0x5080},
    312	{0x208e, 0x2084},
    313	{0x2090, 0x12c8},
    314	{0x2092, 0x7800},
    315	{0x2094, 0x0802},
    316	{0x2096, 0x040f},
    317	{0x2098, 0x1007},
    318	{0x209a, 0x0803},
    319	{0x209c, 0x080b},
    320	{0x209e, 0x3803},
    321	{0x20a0, 0x0807},
    322	{0x20a2, 0x0404},
    323	{0x20a4, 0x0400},
    324	{0x20a6, 0xffff},
    325	{0x20a8, 0xf0b2},
    326	{0x20aa, 0xffef},
    327	{0x20ac, 0x0a84},
    328	{0x20ae, 0x1292},
    329	{0x20b0, 0xc02e},
    330	{0x20b2, 0x4130},
    331	{0x23fe, 0xc056},
    332	{0x3232, 0xfc0c},
    333	{0x3236, 0xfc22},
    334	{0x3248, 0xfca8},
    335	{0x326a, 0x8302},
    336	{0x326c, 0x830a},
    337	{0x326e, 0x0000},
    338	{0x32ca, 0xfc28},
    339	{0x32cc, 0xc3bc},
    340	{0x32ce, 0xc34c},
    341	{0x32d0, 0xc35a},
    342	{0x32d2, 0xc368},
    343	{0x32d4, 0xc376},
    344	{0x32d6, 0xc3c2},
    345	{0x32d8, 0xc3e6},
    346	{0x32da, 0x0003},
    347	{0x32dc, 0x0003},
    348	{0x32de, 0x00c7},
    349	{0x32e0, 0x0031},
    350	{0x32e2, 0x0031},
    351	{0x32e4, 0x0031},
    352	{0x32e6, 0xfc28},
    353	{0x32e8, 0xc3bc},
    354	{0x32ea, 0xc384},
    355	{0x32ec, 0xc392},
    356	{0x32ee, 0xc3a0},
    357	{0x32f0, 0xc3ae},
    358	{0x32f2, 0xc3c4},
    359	{0x32f4, 0xc3e6},
    360	{0x32f6, 0x0003},
    361	{0x32f8, 0x0003},
    362	{0x32fa, 0x00c7},
    363	{0x32fc, 0x0031},
    364	{0x32fe, 0x0031},
    365	{0x3300, 0x0031},
    366	{0x3302, 0x82ca},
    367	{0x3304, 0xc164},
    368	{0x3306, 0x82e6},
    369	{0x3308, 0xc19c},
    370	{0x330a, 0x001f},
    371	{0x330c, 0x001a},
    372	{0x330e, 0x0034},
    373	{0x3310, 0x0000},
    374	{0x3312, 0x0000},
    375	{0x3314, 0xfc94},
    376	{0x3316, 0xc3d8},
    377	/* regs above are unknown */
    378	{HI846_REG_MODE_SELECT,			0x0000},
    379	{HI846_REG_UNKNOWN_0E04,		0x0012},
    380	{HI846_REG_Y_ODD_INC_FOBP,		0x1111},
    381	{HI846_REG_Y_ODD_INC_VACT,		0x1111},
    382	{HI846_REG_UNKNOWN_0022,		0x0008},
    383	{HI846_REG_Y_ADDR_START_VACT_H,		0x0040},
    384	{HI846_REG_UNKNOWN_0028,		0x0017},
    385	{HI846_REG_Y_ADDR_END_VACT_H,		0x09cf},
    386	{HI846_REG_UNKNOWN_005C,		0x2101},
    387	{HI846_REG_FLL,				0x09de},
    388	{HI846_REG_LLP,				0x0ed8},
    389	{HI846_REG_IMAGE_ORIENTATION,		0x0100},
    390	{HI846_REG_BINNING_MODE,		0x0022},
    391	{HI846_REG_HBIN_MODE,			0x0000},
    392	{HI846_REG_UNKNOWN_0A24,		0x0000},
    393	{HI846_REG_X_START_H,			0x0000},
    394	{HI846_REG_X_OUTPUT_SIZE_H,		0x0cc0},
    395	{HI846_REG_Y_OUTPUT_SIZE_H,		0x0990},
    396	{HI846_REG_EXPOSURE,			0x09d8},
    397	{HI846_REG_ANALOG_GAIN,			0x0000},
    398	{HI846_REG_GROUPED_PARA_HOLD,		0x0000},
    399	{HI846_REG_UNKNOWN_051E,		0x0000},
    400	{HI846_REG_UNKNOWN_0200,		0x0400},
    401	{HI846_REG_PEDESTAL_EN,			0x0c00},
    402	{HI846_REG_UNKNOWN_0A0C,		0x0010},
    403	{HI846_REG_UNKNOWN_0A1E,		0x0ccf},
    404	{HI846_REG_UNKNOWN_0402,		0x0110},
    405	{HI846_REG_UNKNOWN_0404,		0x00f4},
    406	{HI846_REG_UNKNOWN_0408,		0x0000},
    407	{HI846_REG_UNKNOWN_0410,		0x008d},
    408	{HI846_REG_UNKNOWN_0412,		0x011a},
    409	{HI846_REG_UNKNOWN_0414,		0x864c},
    410	{HI846_REG_UNKNOWN_021C,		0x0003},
    411	{HI846_REG_UNKNOWN_021E,		0x0235},
    412	{HI846_REG_BLC_CTL0,			0x9150},
    413	{HI846_REG_UNKNOWN_0C06,		0x0021},
    414	{HI846_REG_UNKNOWN_0C10,		0x0040},
    415	{HI846_REG_UNKNOWN_0C12,		0x0040},
    416	{HI846_REG_UNKNOWN_0C14,		0x0040},
    417	{HI846_REG_UNKNOWN_0C16,		0x0040},
    418	{HI846_REG_FAST_STANDBY_MODE,		0x0100},
    419	{HI846_REG_ISP_EN_H,			0x014a},
    420	{HI846_REG_UNKNOWN_0418,		0x0000},
    421	{HI846_REG_UNKNOWN_012A,		0x03b4},
    422	{HI846_REG_X_ADDR_START_HACT_H,		0x0046},
    423	{HI846_REG_X_ADDR_END_HACT_H,		0x0376},
    424	{HI846_REG_UNKNOWN_0B02,		0xe04d},
    425	{HI846_REG_UNKNOWN_0B10,		0x6821},
    426	{HI846_REG_UNKNOWN_0B12,		0x0120},
    427	{HI846_REG_UNKNOWN_0B14,		0x0001},
    428	{HI846_REG_UNKNOWN_2008,		0x38fd},
    429	{HI846_REG_UNKNOWN_326E,		0x0000},
    430	{HI846_REG_UNKNOWN_0900,		0x0320},
    431	{HI846_REG_MIPI_TX_OP_MODE,		0xc31a},
    432	{HI846_REG_UNKNOWN_0914,		0xc109},
    433	{HI846_REG_TCLK_PREPARE,		0x061a},
    434	{HI846_REG_UNKNOWN_0918,		0x0306},
    435	{HI846_REG_THS_ZERO,			0x0b09},
    436	{HI846_REG_TCLK_POST,			0x0c07},
    437	{HI846_REG_UNKNOWN_091E,		0x0a00},
    438	{HI846_REG_UNKNOWN_090C,		0x042a},
    439	{HI846_REG_UNKNOWN_090E,		0x006b},
    440	{HI846_REG_UNKNOWN_0954,		0x0089},
    441	{HI846_REG_UNKNOWN_0956,		0x0000},
    442	{HI846_REG_UNKNOWN_0958,		0xca00},
    443	{HI846_REG_UNKNOWN_095A,		0x9240},
    444	{HI846_REG_UNKNOWN_0F08,		0x2f04},
    445	{HI846_REG_UNKNOWN_0F30,		0x001f},
    446	{HI846_REG_UNKNOWN_0F36,		0x001f},
    447	{HI846_REG_UNKNOWN_0F04,		0x3a00},
    448	{HI846_REG_PLL_CFG_RAMP1_H,		0x025a},
    449	{HI846_REG_PLL_CFG_MIPI1_H,		0x025a},
    450	{HI846_REG_PLL_CFG_MIPI2_H,		0x0024},
    451	{HI846_REG_UNKNOWN_006A,		0x0100},
    452	{HI846_REG_TG_ENABLE,			0x0100},
    453};
    454
    455static const struct hi846_reg hi846_init_4lane[] = {
    456	{0x2000, 0x987a},
    457	{0x2002, 0x00ff},
    458	{0x2004, 0x0047},
    459	{0x2006, 0x3fff},
    460	{0x2008, 0x3fff},
    461	{0x200a, 0xc216},
    462	{0x200c, 0x1292},
    463	{0x200e, 0xc01a},
    464	{0x2010, 0x403d},
    465	{0x2012, 0x000e},
    466	{0x2014, 0x403e},
    467	{0x2016, 0x0b80},
    468	{0x2018, 0x403f},
    469	{0x201a, 0x82ae},
    470	{0x201c, 0x1292},
    471	{0x201e, 0xc00c},
    472	{0x2020, 0x4130},
    473	{0x2022, 0x43e2},
    474	{0x2024, 0x0180},
    475	{0x2026, 0x4130},
    476	{0x2028, 0x7400},
    477	{0x202a, 0x5000},
    478	{0x202c, 0x0253},
    479	{0x202e, 0x0ad1},
    480	{0x2030, 0x2360},
    481	{0x2032, 0x0009},
    482	{0x2034, 0x5020},
    483	{0x2036, 0x000b},
    484	{0x2038, 0x0002},
    485	{0x203a, 0x0044},
    486	{0x203c, 0x0016},
    487	{0x203e, 0x1792},
    488	{0x2040, 0x7002},
    489	{0x2042, 0x154f},
    490	{0x2044, 0x00d5},
    491	{0x2046, 0x000b},
    492	{0x2048, 0x0019},
    493	{0x204a, 0x1698},
    494	{0x204c, 0x000e},
    495	{0x204e, 0x099a},
    496	{0x2050, 0x0058},
    497	{0x2052, 0x7000},
    498	{0x2054, 0x1799},
    499	{0x2056, 0x0310},
    500	{0x2058, 0x03c3},
    501	{0x205a, 0x004c},
    502	{0x205c, 0x064a},
    503	{0x205e, 0x0001},
    504	{0x2060, 0x0007},
    505	{0x2062, 0x0bc7},
    506	{0x2064, 0x0055},
    507	{0x2066, 0x7000},
    508	{0x2068, 0x1550},
    509	{0x206a, 0x158a},
    510	{0x206c, 0x0004},
    511	{0x206e, 0x1488},
    512	{0x2070, 0x7010},
    513	{0x2072, 0x1508},
    514	{0x2074, 0x0004},
    515	{0x2076, 0x0016},
    516	{0x2078, 0x03d5},
    517	{0x207a, 0x0055},
    518	{0x207c, 0x08ca},
    519	{0x207e, 0x2019},
    520	{0x2080, 0x0007},
    521	{0x2082, 0x7057},
    522	{0x2084, 0x0fc7},
    523	{0x2086, 0x5041},
    524	{0x2088, 0x12c8},
    525	{0x208a, 0x5060},
    526	{0x208c, 0x5080},
    527	{0x208e, 0x2084},
    528	{0x2090, 0x12c8},
    529	{0x2092, 0x7800},
    530	{0x2094, 0x0802},
    531	{0x2096, 0x040f},
    532	{0x2098, 0x1007},
    533	{0x209a, 0x0803},
    534	{0x209c, 0x080b},
    535	{0x209e, 0x3803},
    536	{0x20a0, 0x0807},
    537	{0x20a2, 0x0404},
    538	{0x20a4, 0x0400},
    539	{0x20a6, 0xffff},
    540	{0x20a8, 0xf0b2},
    541	{0x20aa, 0xffef},
    542	{0x20ac, 0x0a84},
    543	{0x20ae, 0x1292},
    544	{0x20b0, 0xc02e},
    545	{0x20b2, 0x4130},
    546	{0x20b4, 0xf0b2},
    547	{0x20b6, 0xffbf},
    548	{0x20b8, 0x2004},
    549	{0x20ba, 0x403f},
    550	{0x20bc, 0x00c3},
    551	{0x20be, 0x4fe2},
    552	{0x20c0, 0x8318},
    553	{0x20c2, 0x43cf},
    554	{0x20c4, 0x0000},
    555	{0x20c6, 0x9382},
    556	{0x20c8, 0xc314},
    557	{0x20ca, 0x2003},
    558	{0x20cc, 0x12b0},
    559	{0x20ce, 0xcab0},
    560	{0x20d0, 0x4130},
    561	{0x20d2, 0x12b0},
    562	{0x20d4, 0xc90a},
    563	{0x20d6, 0x4130},
    564	{0x20d8, 0x42d2},
    565	{0x20da, 0x8318},
    566	{0x20dc, 0x00c3},
    567	{0x20de, 0x9382},
    568	{0x20e0, 0xc314},
    569	{0x20e2, 0x2009},
    570	{0x20e4, 0x120b},
    571	{0x20e6, 0x120a},
    572	{0x20e8, 0x1209},
    573	{0x20ea, 0x1208},
    574	{0x20ec, 0x1207},
    575	{0x20ee, 0x1206},
    576	{0x20f0, 0x4030},
    577	{0x20f2, 0xc15e},
    578	{0x20f4, 0x4130},
    579	{0x20f6, 0x1292},
    580	{0x20f8, 0xc008},
    581	{0x20fa, 0x4130},
    582	{0x20fc, 0x42d2},
    583	{0x20fe, 0x82a1},
    584	{0x2100, 0x00c2},
    585	{0x2102, 0x1292},
    586	{0x2104, 0xc040},
    587	{0x2106, 0x4130},
    588	{0x2108, 0x1292},
    589	{0x210a, 0xc006},
    590	{0x210c, 0x42a2},
    591	{0x210e, 0x7324},
    592	{0x2110, 0x9382},
    593	{0x2112, 0xc314},
    594	{0x2114, 0x2011},
    595	{0x2116, 0x425f},
    596	{0x2118, 0x82a1},
    597	{0x211a, 0xf25f},
    598	{0x211c, 0x00c1},
    599	{0x211e, 0xf35f},
    600	{0x2120, 0x2406},
    601	{0x2122, 0x425f},
    602	{0x2124, 0x00c0},
    603	{0x2126, 0xf37f},
    604	{0x2128, 0x522f},
    605	{0x212a, 0x4f82},
    606	{0x212c, 0x7324},
    607	{0x212e, 0x425f},
    608	{0x2130, 0x82d4},
    609	{0x2132, 0xf35f},
    610	{0x2134, 0x4fc2},
    611	{0x2136, 0x01b3},
    612	{0x2138, 0x93c2},
    613	{0x213a, 0x829f},
    614	{0x213c, 0x2421},
    615	{0x213e, 0x403e},
    616	{0x2140, 0xfffe},
    617	{0x2142, 0x40b2},
    618	{0x2144, 0xec78},
    619	{0x2146, 0x831c},
    620	{0x2148, 0x40b2},
    621	{0x214a, 0xec78},
    622	{0x214c, 0x831e},
    623	{0x214e, 0x40b2},
    624	{0x2150, 0xec78},
    625	{0x2152, 0x8320},
    626	{0x2154, 0xb3d2},
    627	{0x2156, 0x008c},
    628	{0x2158, 0x2405},
    629	{0x215a, 0x4e0f},
    630	{0x215c, 0x503f},
    631	{0x215e, 0xffd8},
    632	{0x2160, 0x4f82},
    633	{0x2162, 0x831c},
    634	{0x2164, 0x90f2},
    635	{0x2166, 0x0003},
    636	{0x2168, 0x008c},
    637	{0x216a, 0x2401},
    638	{0x216c, 0x4130},
    639	{0x216e, 0x421f},
    640	{0x2170, 0x831c},
    641	{0x2172, 0x5e0f},
    642	{0x2174, 0x4f82},
    643	{0x2176, 0x831e},
    644	{0x2178, 0x5e0f},
    645	{0x217a, 0x4f82},
    646	{0x217c, 0x8320},
    647	{0x217e, 0x3ff6},
    648	{0x2180, 0x432e},
    649	{0x2182, 0x3fdf},
    650	{0x2184, 0x421f},
    651	{0x2186, 0x7100},
    652	{0x2188, 0x4f0e},
    653	{0x218a, 0x503e},
    654	{0x218c, 0xffd8},
    655	{0x218e, 0x4e82},
    656	{0x2190, 0x7a04},
    657	{0x2192, 0x421e},
    658	{0x2194, 0x831c},
    659	{0x2196, 0x5f0e},
    660	{0x2198, 0x4e82},
    661	{0x219a, 0x7a06},
    662	{0x219c, 0x0b00},
    663	{0x219e, 0x7304},
    664	{0x21a0, 0x0050},
    665	{0x21a2, 0x40b2},
    666	{0x21a4, 0xd081},
    667	{0x21a6, 0x0b88},
    668	{0x21a8, 0x421e},
    669	{0x21aa, 0x831e},
    670	{0x21ac, 0x5f0e},
    671	{0x21ae, 0x4e82},
    672	{0x21b0, 0x7a0e},
    673	{0x21b2, 0x521f},
    674	{0x21b4, 0x8320},
    675	{0x21b6, 0x4f82},
    676	{0x21b8, 0x7a10},
    677	{0x21ba, 0x0b00},
    678	{0x21bc, 0x7304},
    679	{0x21be, 0x007a},
    680	{0x21c0, 0x40b2},
    681	{0x21c2, 0x0081},
    682	{0x21c4, 0x0b88},
    683	{0x21c6, 0x4392},
    684	{0x21c8, 0x7a0a},
    685	{0x21ca, 0x0800},
    686	{0x21cc, 0x7a0c},
    687	{0x21ce, 0x0b00},
    688	{0x21d0, 0x7304},
    689	{0x21d2, 0x022b},
    690	{0x21d4, 0x40b2},
    691	{0x21d6, 0xd081},
    692	{0x21d8, 0x0b88},
    693	{0x21da, 0x0b00},
    694	{0x21dc, 0x7304},
    695	{0x21de, 0x0255},
    696	{0x21e0, 0x40b2},
    697	{0x21e2, 0x0081},
    698	{0x21e4, 0x0b88},
    699	{0x21e6, 0x4130},
    700	{0x23fe, 0xc056},
    701	{0x3232, 0xfc0c},
    702	{0x3236, 0xfc22},
    703	{0x3238, 0xfcfc},
    704	{0x323a, 0xfd84},
    705	{0x323c, 0xfd08},
    706	{0x3246, 0xfcd8},
    707	{0x3248, 0xfca8},
    708	{0x324e, 0xfcb4},
    709	{0x326a, 0x8302},
    710	{0x326c, 0x830a},
    711	{0x326e, 0x0000},
    712	{0x32ca, 0xfc28},
    713	{0x32cc, 0xc3bc},
    714	{0x32ce, 0xc34c},
    715	{0x32d0, 0xc35a},
    716	{0x32d2, 0xc368},
    717	{0x32d4, 0xc376},
    718	{0x32d6, 0xc3c2},
    719	{0x32d8, 0xc3e6},
    720	{0x32da, 0x0003},
    721	{0x32dc, 0x0003},
    722	{0x32de, 0x00c7},
    723	{0x32e0, 0x0031},
    724	{0x32e2, 0x0031},
    725	{0x32e4, 0x0031},
    726	{0x32e6, 0xfc28},
    727	{0x32e8, 0xc3bc},
    728	{0x32ea, 0xc384},
    729	{0x32ec, 0xc392},
    730	{0x32ee, 0xc3a0},
    731	{0x32f0, 0xc3ae},
    732	{0x32f2, 0xc3c4},
    733	{0x32f4, 0xc3e6},
    734	{0x32f6, 0x0003},
    735	{0x32f8, 0x0003},
    736	{0x32fa, 0x00c7},
    737	{0x32fc, 0x0031},
    738	{0x32fe, 0x0031},
    739	{0x3300, 0x0031},
    740	{0x3302, 0x82ca},
    741	{0x3304, 0xc164},
    742	{0x3306, 0x82e6},
    743	{0x3308, 0xc19c},
    744	{0x330a, 0x001f},
    745	{0x330c, 0x001a},
    746	{0x330e, 0x0034},
    747	{0x3310, 0x0000},
    748	{0x3312, 0x0000},
    749	{0x3314, 0xfc94},
    750	{0x3316, 0xc3d8},
    751
    752	{0x0a00, 0x0000},
    753	{0x0e04, 0x0012},
    754	{0x002e, 0x1111},
    755	{0x0032, 0x1111},
    756	{0x0022, 0x0008},
    757	{0x0026, 0x0040},
    758	{0x0028, 0x0017},
    759	{0x002c, 0x09cf},
    760	{0x005c, 0x2101},
    761	{0x0006, 0x09de},
    762	{0x0008, 0x0ed8},
    763	{0x000e, 0x0100},
    764	{0x000c, 0x0022},
    765	{0x0a22, 0x0000},
    766	{0x0a24, 0x0000},
    767	{0x0804, 0x0000},
    768	{0x0a12, 0x0cc0},
    769	{0x0a14, 0x0990},
    770	{0x0074, 0x09d8},
    771	{0x0076, 0x0000},
    772	{0x051e, 0x0000},
    773	{0x0200, 0x0400},
    774	{0x0a1a, 0x0c00},
    775	{0x0a0c, 0x0010},
    776	{0x0a1e, 0x0ccf},
    777	{0x0402, 0x0110},
    778	{0x0404, 0x00f4},
    779	{0x0408, 0x0000},
    780	{0x0410, 0x008d},
    781	{0x0412, 0x011a},
    782	{0x0414, 0x864c},
    783	/* for OTP */
    784	{0x021c, 0x0003},
    785	{0x021e, 0x0235},
    786	/* for OTP */
    787	{0x0c00, 0x9950},
    788	{0x0c06, 0x0021},
    789	{0x0c10, 0x0040},
    790	{0x0c12, 0x0040},
    791	{0x0c14, 0x0040},
    792	{0x0c16, 0x0040},
    793	{0x0a02, 0x0100},
    794	{0x0a04, 0x015a},
    795	{0x0418, 0x0000},
    796	{0x0128, 0x0028},
    797	{0x012a, 0xffff},
    798	{0x0120, 0x0046},
    799	{0x0122, 0x0376},
    800	{0x012c, 0x0020},
    801	{0x012e, 0xffff},
    802	{0x0124, 0x0040},
    803	{0x0126, 0x0378},
    804	{0x0746, 0x0050},
    805	{0x0748, 0x01d5},
    806	{0x074a, 0x022b},
    807	{0x074c, 0x03b0},
    808	{0x0756, 0x043f},
    809	{0x0758, 0x3f1d},
    810	{0x0b02, 0xe04d},
    811	{0x0b10, 0x6821},
    812	{0x0b12, 0x0120},
    813	{0x0b14, 0x0001},
    814	{0x2008, 0x38fd},
    815	{0x326e, 0x0000},
    816	{0x0900, 0x0300},
    817	{0x0902, 0xc319},
    818	{0x0914, 0xc109},
    819	{0x0916, 0x061a},
    820	{0x0918, 0x0407},
    821	{0x091a, 0x0a0b},
    822	{0x091c, 0x0e08},
    823	{0x091e, 0x0a00},
    824	{0x090c, 0x0427},
    825	{0x090e, 0x0059},
    826	{0x0954, 0x0089},
    827	{0x0956, 0x0000},
    828	{0x0958, 0xca80},
    829	{0x095a, 0x9240},
    830	{0x0f08, 0x2f04},
    831	{0x0f30, 0x001f},
    832	{0x0f36, 0x001f},
    833	{0x0f04, 0x3a00},
    834	{0x0f32, 0x025a},
    835	{0x0f38, 0x025a},
    836	{0x0f2a, 0x4124},
    837	{0x006a, 0x0100},
    838	{0x004c, 0x0100},
    839	{0x0044, 0x0001},
    840};
    841
    842static const struct hi846_reg mode_640x480_config[] = {
    843	{HI846_REG_MODE_SELECT,			0x0000},
    844	{HI846_REG_Y_ODD_INC_FOBP,		0x7711},
    845	{HI846_REG_Y_ODD_INC_VACT,		0x7711},
    846	{HI846_REG_Y_ADDR_START_VACT_H,		0x0148},
    847	{HI846_REG_Y_ADDR_END_VACT_H,		0x08c7},
    848	{HI846_REG_UNKNOWN_005C,		0x4404},
    849	{HI846_REG_FLL,				0x0277},
    850	{HI846_REG_LLP,				0x0ed8},
    851	{HI846_REG_BINNING_MODE,		0x0322},
    852	{HI846_REG_HBIN_MODE,			0x0200},
    853	{HI846_REG_UNKNOWN_0A24,		0x0000},
    854	{HI846_REG_X_START_H,			0x0058},
    855	{HI846_REG_X_OUTPUT_SIZE_H,		0x0280},
    856	{HI846_REG_Y_OUTPUT_SIZE_H,		0x01e0},
    857
    858	/* For OTP */
    859	{HI846_REG_UNKNOWN_021C,		0x0003},
    860	{HI846_REG_UNKNOWN_021E,		0x0235},
    861
    862	{HI846_REG_ISP_EN_H,			0x016a},
    863	{HI846_REG_UNKNOWN_0418,		0x0210},
    864	{HI846_REG_UNKNOWN_0B02,		0xe04d},
    865	{HI846_REG_UNKNOWN_0B10,		0x7021},
    866	{HI846_REG_UNKNOWN_0B12,		0x0120},
    867	{HI846_REG_UNKNOWN_0B14,		0x0001},
    868	{HI846_REG_UNKNOWN_2008,		0x38fd},
    869	{HI846_REG_UNKNOWN_326E,		0x0000},
    870};
    871
    872static const struct hi846_reg mode_640x480_mipi_2lane[] = {
    873	{HI846_REG_UNKNOWN_0900,		0x0300},
    874	{HI846_REG_MIPI_TX_OP_MODE,		0x4319},
    875	{HI846_REG_UNKNOWN_0914,		0xc105},
    876	{HI846_REG_TCLK_PREPARE,		0x030c},
    877	{HI846_REG_UNKNOWN_0918,		0x0304},
    878	{HI846_REG_THS_ZERO,			0x0708},
    879	{HI846_REG_TCLK_POST,			0x0b04},
    880	{HI846_REG_UNKNOWN_091E,		0x0500},
    881	{HI846_REG_UNKNOWN_090C,		0x0208},
    882	{HI846_REG_UNKNOWN_090E,		0x009a},
    883	{HI846_REG_UNKNOWN_0954,		0x0089},
    884	{HI846_REG_UNKNOWN_0956,		0x0000},
    885	{HI846_REG_UNKNOWN_0958,		0xca80},
    886	{HI846_REG_UNKNOWN_095A,		0x9240},
    887	{HI846_REG_PLL_CFG_MIPI2_H,		0x4924},
    888	{HI846_REG_TG_ENABLE,			0x0100},
    889};
    890
    891static const struct hi846_reg mode_1280x720_config[] = {
    892	{HI846_REG_MODE_SELECT,			0x0000},
    893	{HI846_REG_Y_ODD_INC_FOBP,		0x3311},
    894	{HI846_REG_Y_ODD_INC_VACT,		0x3311},
    895	{HI846_REG_Y_ADDR_START_VACT_H,		0x0238},
    896	{HI846_REG_Y_ADDR_END_VACT_H,		0x07d7},
    897	{HI846_REG_UNKNOWN_005C,		0x4202},
    898	{HI846_REG_FLL,				0x034a},
    899	{HI846_REG_LLP,				0x0ed8},
    900	{HI846_REG_BINNING_MODE,		0x0122},
    901	{HI846_REG_HBIN_MODE,			0x0100},
    902	{HI846_REG_UNKNOWN_0A24,		0x0000},
    903	{HI846_REG_X_START_H,			0x00b0},
    904	{HI846_REG_X_OUTPUT_SIZE_H,		0x0500},
    905	{HI846_REG_Y_OUTPUT_SIZE_H,		0x02d0},
    906	{HI846_REG_EXPOSURE,			0x0344},
    907
    908	/* For OTP */
    909	{HI846_REG_UNKNOWN_021C,		0x0003},
    910	{HI846_REG_UNKNOWN_021E,		0x0235},
    911
    912	{HI846_REG_ISP_EN_H,			0x016a},
    913	{HI846_REG_UNKNOWN_0418,		0x0410},
    914	{HI846_REG_UNKNOWN_0B02,		0xe04d},
    915	{HI846_REG_UNKNOWN_0B10,		0x6c21},
    916	{HI846_REG_UNKNOWN_0B12,		0x0120},
    917	{HI846_REG_UNKNOWN_0B14,		0x0005},
    918	{HI846_REG_UNKNOWN_2008,		0x38fd},
    919	{HI846_REG_UNKNOWN_326E,		0x0000},
    920};
    921
    922static const struct hi846_reg mode_1280x720_mipi_2lane[] = {
    923	{HI846_REG_UNKNOWN_0900,		0x0300},
    924	{HI846_REG_MIPI_TX_OP_MODE,		0x4319},
    925	{HI846_REG_UNKNOWN_0914,		0xc109},
    926	{HI846_REG_TCLK_PREPARE,		0x061a},
    927	{HI846_REG_UNKNOWN_0918,		0x0407},
    928	{HI846_REG_THS_ZERO,			0x0a0b},
    929	{HI846_REG_TCLK_POST,			0x0e08},
    930	{HI846_REG_UNKNOWN_091E,		0x0a00},
    931	{HI846_REG_UNKNOWN_090C,		0x0427},
    932	{HI846_REG_UNKNOWN_090E,		0x0145},
    933	{HI846_REG_UNKNOWN_0954,		0x0089},
    934	{HI846_REG_UNKNOWN_0956,		0x0000},
    935	{HI846_REG_UNKNOWN_0958,		0xca80},
    936	{HI846_REG_UNKNOWN_095A,		0x9240},
    937	{HI846_REG_PLL_CFG_MIPI2_H,		0x4124},
    938	{HI846_REG_TG_ENABLE,			0x0100},
    939};
    940
    941static const struct hi846_reg mode_1280x720_mipi_4lane[] = {
    942	/* 360Mbps */
    943	{HI846_REG_UNKNOWN_0900,		0x0300},
    944	{HI846_REG_MIPI_TX_OP_MODE,		0xc319},
    945	{HI846_REG_UNKNOWN_0914,		0xc105},
    946	{HI846_REG_TCLK_PREPARE,		0x030c},
    947	{HI846_REG_UNKNOWN_0918,		0x0304},
    948	{HI846_REG_THS_ZERO,			0x0708},
    949	{HI846_REG_TCLK_POST,			0x0b04},
    950	{HI846_REG_UNKNOWN_091E,		0x0500},
    951	{HI846_REG_UNKNOWN_090C,		0x0208},
    952	{HI846_REG_UNKNOWN_090E,		0x008a},
    953	{HI846_REG_UNKNOWN_0954,		0x0089},
    954	{HI846_REG_UNKNOWN_0956,		0x0000},
    955	{HI846_REG_UNKNOWN_0958,		0xca80},
    956	{HI846_REG_UNKNOWN_095A,		0x9240},
    957	{HI846_REG_PLL_CFG_MIPI2_H,		0x4924},
    958	{HI846_REG_TG_ENABLE,			0x0100},
    959};
    960
    961static const struct hi846_reg mode_1632x1224_config[] = {
    962	{HI846_REG_MODE_SELECT,			0x0000},
    963	{HI846_REG_Y_ODD_INC_FOBP,		0x3311},
    964	{HI846_REG_Y_ODD_INC_VACT,		0x3311},
    965	{HI846_REG_Y_ADDR_START_VACT_H,		0x0040},
    966	{HI846_REG_Y_ADDR_END_VACT_H,		0x09cf},
    967	{HI846_REG_UNKNOWN_005C,		0x4202},
    968	{HI846_REG_FLL,				0x09de},
    969	{HI846_REG_LLP,				0x0ed8},
    970	{HI846_REG_BINNING_MODE,		0x0122},
    971	{HI846_REG_HBIN_MODE,			0x0100},
    972	{HI846_REG_UNKNOWN_0A24,		0x0000},
    973	{HI846_REG_X_START_H,			0x0000},
    974	{HI846_REG_X_OUTPUT_SIZE_H,		0x0660},
    975	{HI846_REG_Y_OUTPUT_SIZE_H,		0x04c8},
    976	{HI846_REG_EXPOSURE,			0x09d8},
    977
    978	/* For OTP */
    979	{HI846_REG_UNKNOWN_021C,		0x0003},
    980	{HI846_REG_UNKNOWN_021E,		0x0235},
    981
    982	{HI846_REG_ISP_EN_H,			0x016a},
    983	{HI846_REG_UNKNOWN_0418,		0x0000},
    984	{HI846_REG_UNKNOWN_0B02,		0xe04d},
    985	{HI846_REG_UNKNOWN_0B10,		0x6c21},
    986	{HI846_REG_UNKNOWN_0B12,		0x0120},
    987	{HI846_REG_UNKNOWN_0B14,		0x0005},
    988	{HI846_REG_UNKNOWN_2008,		0x38fd},
    989	{HI846_REG_UNKNOWN_326E,		0x0000},
    990};
    991
    992static const struct hi846_reg mode_1632x1224_mipi_2lane[] = {
    993	{HI846_REG_UNKNOWN_0900,		0x0300},
    994	{HI846_REG_MIPI_TX_OP_MODE,		0x4319},
    995	{HI846_REG_UNKNOWN_0914,		0xc109},
    996	{HI846_REG_TCLK_PREPARE,		0x061a},
    997	{HI846_REG_UNKNOWN_0918,		0x0407},
    998	{HI846_REG_THS_ZERO,			0x0a0b},
    999	{HI846_REG_TCLK_POST,			0x0e08},
   1000	{HI846_REG_UNKNOWN_091E,		0x0a00},
   1001	{HI846_REG_UNKNOWN_090C,		0x0427},
   1002	{HI846_REG_UNKNOWN_090E,		0x0069},
   1003	{HI846_REG_UNKNOWN_0954,		0x0089},
   1004	{HI846_REG_UNKNOWN_0956,		0x0000},
   1005	{HI846_REG_UNKNOWN_0958,		0xca80},
   1006	{HI846_REG_UNKNOWN_095A,		0x9240},
   1007	{HI846_REG_PLL_CFG_MIPI2_H,		0x4124},
   1008	{HI846_REG_TG_ENABLE,			0x0100},
   1009};
   1010
   1011static const struct hi846_reg mode_1632x1224_mipi_4lane[] = {
   1012	{HI846_REG_UNKNOWN_0900,		0x0300},
   1013	{HI846_REG_MIPI_TX_OP_MODE,		0xc319},
   1014	{HI846_REG_UNKNOWN_0914,		0xc105},
   1015	{HI846_REG_TCLK_PREPARE,		0x030c},
   1016	{HI846_REG_UNKNOWN_0918,		0x0304},
   1017	{HI846_REG_THS_ZERO,			0x0708},
   1018	{HI846_REG_TCLK_POST,			0x0b04},
   1019	{HI846_REG_UNKNOWN_091E,		0x0500},
   1020	{HI846_REG_UNKNOWN_090C,		0x0208},
   1021	{HI846_REG_UNKNOWN_090E,		0x001c},
   1022	{HI846_REG_UNKNOWN_0954,		0x0089},
   1023	{HI846_REG_UNKNOWN_0956,		0x0000},
   1024	{HI846_REG_UNKNOWN_0958,		0xca80},
   1025	{HI846_REG_UNKNOWN_095A,		0x9240},
   1026	{HI846_REG_PLL_CFG_MIPI2_H,		0x4924},
   1027	{HI846_REG_TG_ENABLE,			0x0100},
   1028};
   1029
   1030static const char * const hi846_test_pattern_menu[] = {
   1031	"Disabled",
   1032	"Solid Colour",
   1033	"100% Colour Bars",
   1034	"Fade To Grey Colour Bars",
   1035	"PN9",
   1036	"Gradient Horizontal",
   1037	"Gradient Vertical",
   1038	"Check Board",
   1039	"Slant Pattern",
   1040	"Resolution Pattern",
   1041};
   1042
   1043#define FREQ_INDEX_640	0
   1044#define FREQ_INDEX_1280	1
   1045static const s64 hi846_link_freqs[] = {
   1046	[FREQ_INDEX_640] = 80000000,
   1047	[FREQ_INDEX_1280] = 200000000,
   1048};
   1049
   1050static const struct hi846_reg_list hi846_init_regs_list_2lane = {
   1051	.num_of_regs = ARRAY_SIZE(hi846_init_2lane),
   1052	.regs = hi846_init_2lane,
   1053};
   1054
   1055static const struct hi846_reg_list hi846_init_regs_list_4lane = {
   1056	.num_of_regs = ARRAY_SIZE(hi846_init_4lane),
   1057	.regs = hi846_init_4lane,
   1058};
   1059
   1060static const struct hi846_mode supported_modes[] = {
   1061	{
   1062		.width = 640,
   1063		.height = 480,
   1064		.link_freq_index = FREQ_INDEX_640,
   1065		.fps = 120,
   1066		.frame_len = 631,
   1067		.llp = HI846_LINE_LENGTH,
   1068		.reg_list_config = {
   1069			.num_of_regs = ARRAY_SIZE(mode_640x480_config),
   1070			.regs = mode_640x480_config,
   1071		},
   1072		.reg_list_2lane = {
   1073			.num_of_regs = ARRAY_SIZE(mode_640x480_mipi_2lane),
   1074			.regs = mode_640x480_mipi_2lane,
   1075		},
   1076		.reg_list_4lane = {
   1077			.num_of_regs = 0,
   1078		},
   1079		.crop = {
   1080			.left = 0x58,
   1081			.top = 0x148,
   1082			.width = 640 * 4,
   1083			.height = 480 * 4,
   1084		},
   1085	},
   1086	{
   1087		.width = 1280,
   1088		.height = 720,
   1089		.link_freq_index = FREQ_INDEX_1280,
   1090		.fps = 90,
   1091		.frame_len = 842,
   1092		.llp = HI846_LINE_LENGTH,
   1093		.reg_list_config = {
   1094			.num_of_regs = ARRAY_SIZE(mode_1280x720_config),
   1095			.regs = mode_1280x720_config,
   1096		},
   1097		.reg_list_2lane = {
   1098			.num_of_regs = ARRAY_SIZE(mode_1280x720_mipi_2lane),
   1099			.regs = mode_1280x720_mipi_2lane,
   1100		},
   1101		.reg_list_4lane = {
   1102			.num_of_regs = ARRAY_SIZE(mode_1280x720_mipi_4lane),
   1103			.regs = mode_1280x720_mipi_4lane,
   1104		},
   1105		.crop = {
   1106			.left = 0xb0,
   1107			.top = 0x238,
   1108			.width = 1280 * 2,
   1109			.height = 720 * 2,
   1110		},
   1111	},
   1112	{
   1113		.width = 1632,
   1114		.height = 1224,
   1115		.link_freq_index = FREQ_INDEX_1280,
   1116		.fps = 30,
   1117		.frame_len = 2526,
   1118		.llp = HI846_LINE_LENGTH,
   1119		.reg_list_config = {
   1120			.num_of_regs = ARRAY_SIZE(mode_1632x1224_config),
   1121			.regs = mode_1632x1224_config,
   1122		},
   1123		.reg_list_2lane = {
   1124			.num_of_regs = ARRAY_SIZE(mode_1632x1224_mipi_2lane),
   1125			.regs = mode_1632x1224_mipi_2lane,
   1126		},
   1127		.reg_list_4lane = {
   1128			.num_of_regs = ARRAY_SIZE(mode_1632x1224_mipi_4lane),
   1129			.regs = mode_1632x1224_mipi_4lane,
   1130		},
   1131		.crop = {
   1132			.left = 0x0,
   1133			.top = 0x0,
   1134			.width = 1632 * 2,
   1135			.height = 1224 * 2,
   1136		},
   1137	}
   1138};
   1139
   1140struct hi846_datafmt {
   1141	u32 code;
   1142	enum v4l2_colorspace colorspace;
   1143};
   1144
   1145static const char * const hi846_supply_names[] = {
   1146	"vddio", /* Digital I/O (1.8V or 2.8V) */
   1147	"vdda", /* Analog (2.8V) */
   1148	"vddd", /* Digital Core (1.2V) */
   1149};
   1150
   1151#define HI846_NUM_SUPPLIES ARRAY_SIZE(hi846_supply_names)
   1152
   1153struct hi846 {
   1154	struct gpio_desc *rst_gpio;
   1155	struct gpio_desc *shutdown_gpio;
   1156	struct regulator_bulk_data supplies[HI846_NUM_SUPPLIES];
   1157	struct clk *clock;
   1158	const struct hi846_datafmt *fmt;
   1159	struct v4l2_subdev sd;
   1160	struct media_pad pad;
   1161	struct v4l2_ctrl_handler ctrl_handler;
   1162	u8 nr_lanes;
   1163
   1164	struct v4l2_ctrl *link_freq;
   1165	struct v4l2_ctrl *pixel_rate;
   1166	struct v4l2_ctrl *vblank;
   1167	struct v4l2_ctrl *hblank;
   1168	struct v4l2_ctrl *exposure;
   1169
   1170	struct mutex mutex; /* protect cur_mode, streaming and chip access */
   1171	const struct hi846_mode *cur_mode;
   1172	bool streaming;
   1173};
   1174
   1175static inline struct hi846 *to_hi846(struct v4l2_subdev *sd)
   1176{
   1177	return container_of(sd, struct hi846, sd);
   1178}
   1179
   1180static const struct hi846_datafmt hi846_colour_fmts[] = {
   1181	{ HI846_MEDIA_BUS_FORMAT, V4L2_COLORSPACE_RAW },
   1182};
   1183
   1184static const struct hi846_datafmt *hi846_find_datafmt(u32 code)
   1185{
   1186	unsigned int i;
   1187
   1188	for (i = 0; i < ARRAY_SIZE(hi846_colour_fmts); i++)
   1189		if (hi846_colour_fmts[i].code == code)
   1190			return &hi846_colour_fmts[i];
   1191
   1192	return NULL;
   1193}
   1194
   1195static inline u8 hi846_get_link_freq_index(struct hi846 *hi846)
   1196{
   1197	return hi846->cur_mode->link_freq_index;
   1198}
   1199
   1200static u64 hi846_get_link_freq(struct hi846 *hi846)
   1201{
   1202	u8 index = hi846_get_link_freq_index(hi846);
   1203
   1204	return hi846_link_freqs[index];
   1205}
   1206
   1207static u64 hi846_calc_pixel_rate(struct hi846 *hi846)
   1208{
   1209	u64 link_freq = hi846_get_link_freq(hi846);
   1210	u64 pixel_rate = link_freq * 2 * hi846->nr_lanes;
   1211
   1212	do_div(pixel_rate, HI846_RGB_DEPTH);
   1213
   1214	return pixel_rate;
   1215}
   1216
   1217static int hi846_read_reg(struct hi846 *hi846, u16 reg, u8 *val)
   1218{
   1219	struct i2c_client *client = v4l2_get_subdevdata(&hi846->sd);
   1220	struct i2c_msg msgs[2];
   1221	u8 addr_buf[2];
   1222	u8 data_buf[1] = {0};
   1223	int ret;
   1224
   1225	put_unaligned_be16(reg, addr_buf);
   1226	msgs[0].addr = client->addr;
   1227	msgs[0].flags = 0;
   1228	msgs[0].len = sizeof(addr_buf);
   1229	msgs[0].buf = addr_buf;
   1230	msgs[1].addr = client->addr;
   1231	msgs[1].flags = I2C_M_RD;
   1232	msgs[1].len = 1;
   1233	msgs[1].buf = data_buf;
   1234
   1235	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
   1236	if (ret != ARRAY_SIZE(msgs)) {
   1237		dev_err(&client->dev, "i2c read error: %d\n", ret);
   1238		return -EIO;
   1239	}
   1240
   1241	*val = data_buf[0];
   1242
   1243	return 0;
   1244}
   1245
   1246static int hi846_write_reg(struct hi846 *hi846, u16 reg, u8 val)
   1247{
   1248	struct i2c_client *client = v4l2_get_subdevdata(&hi846->sd);
   1249	u8 buf[3] = { reg >> 8, reg & 0xff, val };
   1250	struct i2c_msg msg[] = {
   1251		{ .addr = client->addr, .flags = 0,
   1252		  .len = ARRAY_SIZE(buf), .buf = buf },
   1253	};
   1254	int ret;
   1255
   1256	ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
   1257	if (ret != ARRAY_SIZE(msg)) {
   1258		dev_err(&client->dev, "i2c write error\n");
   1259		return -EIO;
   1260	}
   1261
   1262	return 0;
   1263}
   1264
   1265static void hi846_write_reg_16(struct hi846 *hi846, u16 reg, u16 val, int *err)
   1266{
   1267	struct i2c_client *client = v4l2_get_subdevdata(&hi846->sd);
   1268	u8 buf[4];
   1269	int ret;
   1270
   1271	if (*err < 0)
   1272		return;
   1273
   1274	put_unaligned_be16(reg, buf);
   1275	put_unaligned_be16(val, buf + 2);
   1276	ret = i2c_master_send(client, buf, sizeof(buf));
   1277	if (ret != sizeof(buf)) {
   1278		dev_err(&client->dev, "i2c_master_send != %zu: %d\n",
   1279			sizeof(buf), ret);
   1280		*err = -EIO;
   1281	}
   1282}
   1283
   1284static int hi846_write_reg_list(struct hi846 *hi846,
   1285				const struct hi846_reg_list *r_list)
   1286{
   1287	struct i2c_client *client = v4l2_get_subdevdata(&hi846->sd);
   1288	unsigned int i;
   1289	int ret = 0;
   1290
   1291	for (i = 0; i < r_list->num_of_regs; i++) {
   1292		hi846_write_reg_16(hi846, r_list->regs[i].address,
   1293				   r_list->regs[i].val, &ret);
   1294		if (ret) {
   1295			dev_err_ratelimited(&client->dev,
   1296					    "failed to write reg 0x%4.4x: %d",
   1297					    r_list->regs[i].address, ret);
   1298			return ret;
   1299		}
   1300	}
   1301
   1302	return 0;
   1303}
   1304
   1305static int hi846_update_digital_gain(struct hi846 *hi846, u16 d_gain)
   1306{
   1307	int ret = 0;
   1308
   1309	hi846_write_reg_16(hi846, HI846_REG_MWB_GR_GAIN_H, d_gain, &ret);
   1310	hi846_write_reg_16(hi846, HI846_REG_MWB_GB_GAIN_H, d_gain, &ret);
   1311	hi846_write_reg_16(hi846, HI846_REG_MWB_R_GAIN_H, d_gain, &ret);
   1312	hi846_write_reg_16(hi846, HI846_REG_MWB_B_GAIN_H, d_gain, &ret);
   1313
   1314	return ret;
   1315}
   1316
   1317static int hi846_test_pattern(struct hi846 *hi846, u32 pattern)
   1318{
   1319	int ret;
   1320	u8 val;
   1321
   1322	if (pattern) {
   1323		ret = hi846_read_reg(hi846, HI846_REG_ISP, &val);
   1324		if (ret)
   1325			return ret;
   1326
   1327		ret = hi846_write_reg(hi846, HI846_REG_ISP,
   1328				      val | HI846_REG_ISP_TPG_EN);
   1329		if (ret)
   1330			return ret;
   1331	}
   1332
   1333	return hi846_write_reg(hi846, HI846_REG_TEST_PATTERN, pattern);
   1334}
   1335
   1336static int hi846_set_ctrl(struct v4l2_ctrl *ctrl)
   1337{
   1338	struct hi846 *hi846 = container_of(ctrl->handler,
   1339					     struct hi846, ctrl_handler);
   1340	struct i2c_client *client = v4l2_get_subdevdata(&hi846->sd);
   1341	s64 exposure_max;
   1342	int ret = 0;
   1343	u32 shutter, frame_len;
   1344
   1345	/* Propagate change of current control to all related controls */
   1346	if (ctrl->id == V4L2_CID_VBLANK) {
   1347		/* Update max exposure while meeting expected vblanking */
   1348		exposure_max = hi846->cur_mode->height + ctrl->val -
   1349			       HI846_EXPOSURE_MAX_MARGIN;
   1350		__v4l2_ctrl_modify_range(hi846->exposure,
   1351					 hi846->exposure->minimum,
   1352					 exposure_max, hi846->exposure->step,
   1353					 exposure_max);
   1354	}
   1355
   1356	if (!pm_runtime_get_if_in_use(&client->dev))
   1357		return 0;
   1358
   1359	switch (ctrl->id) {
   1360	case V4L2_CID_ANALOGUE_GAIN:
   1361		ret = hi846_write_reg(hi846, HI846_REG_ANALOG_GAIN, ctrl->val);
   1362		break;
   1363
   1364	case V4L2_CID_DIGITAL_GAIN:
   1365		ret = hi846_update_digital_gain(hi846, ctrl->val);
   1366		break;
   1367
   1368	case V4L2_CID_EXPOSURE:
   1369		shutter = ctrl->val;
   1370		frame_len = hi846->cur_mode->frame_len;
   1371
   1372		if (shutter > frame_len - 6) { /* margin */
   1373			frame_len = shutter + 6;
   1374			if (frame_len > 0xffff) { /* max frame len */
   1375				frame_len = 0xffff;
   1376			}
   1377		}
   1378
   1379		if (shutter < 6)
   1380			shutter = 6;
   1381		if (shutter > (0xffff - 6))
   1382			shutter = 0xffff - 6;
   1383
   1384		hi846_write_reg_16(hi846, HI846_REG_FLL, frame_len, &ret);
   1385		hi846_write_reg_16(hi846, HI846_REG_EXPOSURE, shutter, &ret);
   1386		break;
   1387
   1388	case V4L2_CID_VBLANK:
   1389		/* Update FLL that meets expected vertical blanking */
   1390		hi846_write_reg_16(hi846, HI846_REG_FLL,
   1391				   hi846->cur_mode->height + ctrl->val, &ret);
   1392		break;
   1393	case V4L2_CID_TEST_PATTERN:
   1394		ret = hi846_test_pattern(hi846, ctrl->val);
   1395		break;
   1396
   1397	default:
   1398		ret = -EINVAL;
   1399		break;
   1400	}
   1401
   1402	pm_runtime_put(&client->dev);
   1403
   1404	return ret;
   1405}
   1406
   1407static const struct v4l2_ctrl_ops hi846_ctrl_ops = {
   1408	.s_ctrl = hi846_set_ctrl,
   1409};
   1410
   1411static int hi846_init_controls(struct hi846 *hi846)
   1412{
   1413	struct v4l2_ctrl_handler *ctrl_hdlr;
   1414	s64 exposure_max, h_blank;
   1415	int ret;
   1416	struct i2c_client *client = v4l2_get_subdevdata(&hi846->sd);
   1417	struct v4l2_fwnode_device_properties props;
   1418
   1419	ctrl_hdlr = &hi846->ctrl_handler;
   1420	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
   1421	if (ret)
   1422		return ret;
   1423
   1424	ctrl_hdlr->lock = &hi846->mutex;
   1425
   1426	hi846->link_freq =
   1427		v4l2_ctrl_new_int_menu(ctrl_hdlr, &hi846_ctrl_ops,
   1428				       V4L2_CID_LINK_FREQ,
   1429				       ARRAY_SIZE(hi846_link_freqs) - 1,
   1430				       0, hi846_link_freqs);
   1431	if (hi846->link_freq)
   1432		hi846->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
   1433
   1434	hi846->pixel_rate =
   1435		v4l2_ctrl_new_std(ctrl_hdlr, &hi846_ctrl_ops,
   1436				  V4L2_CID_PIXEL_RATE, 0,
   1437				  hi846_calc_pixel_rate(hi846), 1,
   1438				  hi846_calc_pixel_rate(hi846));
   1439	hi846->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &hi846_ctrl_ops,
   1440					  V4L2_CID_VBLANK,
   1441					  hi846->cur_mode->frame_len -
   1442					  hi846->cur_mode->height,
   1443					  HI846_FLL_MAX -
   1444					  hi846->cur_mode->height, 1,
   1445					  hi846->cur_mode->frame_len -
   1446					  hi846->cur_mode->height);
   1447
   1448	h_blank = hi846->cur_mode->llp - hi846->cur_mode->width;
   1449
   1450	hi846->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &hi846_ctrl_ops,
   1451					  V4L2_CID_HBLANK, h_blank, h_blank, 1,
   1452					  h_blank);
   1453	if (hi846->hblank)
   1454		hi846->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
   1455
   1456	v4l2_ctrl_new_std(ctrl_hdlr, &hi846_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
   1457			  HI846_ANAL_GAIN_MIN, HI846_ANAL_GAIN_MAX,
   1458			  HI846_ANAL_GAIN_STEP, HI846_ANAL_GAIN_MIN);
   1459	v4l2_ctrl_new_std(ctrl_hdlr, &hi846_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
   1460			  HI846_DGTL_GAIN_MIN, HI846_DGTL_GAIN_MAX,
   1461			  HI846_DGTL_GAIN_STEP, HI846_DGTL_GAIN_DEFAULT);
   1462	exposure_max = hi846->cur_mode->frame_len - HI846_EXPOSURE_MAX_MARGIN;
   1463	hi846->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &hi846_ctrl_ops,
   1464					    V4L2_CID_EXPOSURE,
   1465					    HI846_EXPOSURE_MIN, exposure_max,
   1466					    HI846_EXPOSURE_STEP,
   1467					    exposure_max);
   1468	v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &hi846_ctrl_ops,
   1469				     V4L2_CID_TEST_PATTERN,
   1470				     ARRAY_SIZE(hi846_test_pattern_menu) - 1,
   1471				     0, 0, hi846_test_pattern_menu);
   1472	if (ctrl_hdlr->error) {
   1473		dev_err(&client->dev, "v4l ctrl handler error: %d\n",
   1474			ctrl_hdlr->error);
   1475		return ctrl_hdlr->error;
   1476	}
   1477
   1478	ret = v4l2_fwnode_device_parse(&client->dev, &props);
   1479	if (ret)
   1480		return ret;
   1481
   1482	ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &hi846_ctrl_ops,
   1483					      &props);
   1484	if (ret)
   1485		return ret;
   1486
   1487	hi846->sd.ctrl_handler = ctrl_hdlr;
   1488
   1489	return 0;
   1490}
   1491
   1492static int hi846_set_video_mode(struct hi846 *hi846, int fps)
   1493{
   1494	struct i2c_client *client = v4l2_get_subdevdata(&hi846->sd);
   1495	u64 frame_length;
   1496	int ret = 0;
   1497	int dummy_lines;
   1498	u64 link_freq = hi846_get_link_freq(hi846);
   1499
   1500	dev_dbg(&client->dev, "%s: link freq: %llu\n", __func__,
   1501		hi846_get_link_freq(hi846));
   1502
   1503	do_div(link_freq, fps);
   1504	frame_length = link_freq;
   1505	do_div(frame_length, HI846_LINE_LENGTH);
   1506
   1507	dummy_lines = (frame_length > hi846->cur_mode->frame_len) ?
   1508			(frame_length - hi846->cur_mode->frame_len) : 0;
   1509
   1510	frame_length = hi846->cur_mode->frame_len + dummy_lines;
   1511
   1512	dev_dbg(&client->dev, "%s: frame length calculated: %llu\n", __func__,
   1513		frame_length);
   1514
   1515	hi846_write_reg_16(hi846, HI846_REG_FLL, frame_length & 0xFFFF, &ret);
   1516	hi846_write_reg_16(hi846, HI846_REG_LLP,
   1517			   HI846_LINE_LENGTH & 0xFFFF, &ret);
   1518
   1519	return ret;
   1520}
   1521
   1522static int hi846_start_streaming(struct hi846 *hi846)
   1523{
   1524	struct i2c_client *client = v4l2_get_subdevdata(&hi846->sd);
   1525	int ret = 0;
   1526	u8 val;
   1527
   1528	if (hi846->nr_lanes == 2)
   1529		ret = hi846_write_reg_list(hi846, &hi846_init_regs_list_2lane);
   1530	else
   1531		ret = hi846_write_reg_list(hi846, &hi846_init_regs_list_4lane);
   1532	if (ret) {
   1533		dev_err(&client->dev, "failed to set plls: %d\n", ret);
   1534		return ret;
   1535	}
   1536
   1537	ret = hi846_write_reg_list(hi846, &hi846->cur_mode->reg_list_config);
   1538	if (ret) {
   1539		dev_err(&client->dev, "failed to set mode: %d\n", ret);
   1540		return ret;
   1541	}
   1542
   1543	if (hi846->nr_lanes == 2)
   1544		ret = hi846_write_reg_list(hi846,
   1545					   &hi846->cur_mode->reg_list_2lane);
   1546	else
   1547		ret = hi846_write_reg_list(hi846,
   1548					   &hi846->cur_mode->reg_list_4lane);
   1549	if (ret) {
   1550		dev_err(&client->dev, "failed to set mipi mode: %d\n", ret);
   1551		return ret;
   1552	}
   1553
   1554	hi846_set_video_mode(hi846, hi846->cur_mode->fps);
   1555
   1556	ret = __v4l2_ctrl_handler_setup(hi846->sd.ctrl_handler);
   1557	if (ret)
   1558		return ret;
   1559
   1560	/*
   1561	 * Reading 0x0034 is purely done for debugging reasons: It is not
   1562	 * documented in the DS but only mentioned once:
   1563	 * "If 0x0034[2] bit is disabled , Visible pixel width and height is 0."
   1564	 * So even though that sounds like we won't see anything, we don't
   1565	 * know more about this, so in that case only inform the user but do
   1566	 * nothing more.
   1567	 */
   1568	ret = hi846_read_reg(hi846, 0x0034, &val);
   1569	if (ret)
   1570		return ret;
   1571	if (!(val & BIT(2)))
   1572		dev_info(&client->dev, "visible pixel width and height is 0\n");
   1573
   1574	ret = hi846_write_reg(hi846, HI846_REG_MODE_SELECT,
   1575			      HI846_MODE_STREAMING);
   1576	if (ret) {
   1577		dev_err(&client->dev, "failed to start stream");
   1578		return ret;
   1579	}
   1580
   1581	hi846->streaming = 1;
   1582
   1583	dev_dbg(&client->dev, "%s: started streaming successfully\n", __func__);
   1584
   1585	return ret;
   1586}
   1587
   1588static void hi846_stop_streaming(struct hi846 *hi846)
   1589{
   1590	struct i2c_client *client = v4l2_get_subdevdata(&hi846->sd);
   1591
   1592	if (hi846_write_reg(hi846, HI846_REG_MODE_SELECT, HI846_MODE_STANDBY))
   1593		dev_err(&client->dev, "failed to stop stream");
   1594
   1595	hi846->streaming = 0;
   1596}
   1597
   1598static int hi846_set_stream(struct v4l2_subdev *sd, int enable)
   1599{
   1600	struct hi846 *hi846 = to_hi846(sd);
   1601	struct i2c_client *client = v4l2_get_subdevdata(sd);
   1602	int ret = 0;
   1603
   1604	if (hi846->streaming == enable)
   1605		return 0;
   1606
   1607	mutex_lock(&hi846->mutex);
   1608
   1609	if (enable) {
   1610		ret = pm_runtime_get_sync(&client->dev);
   1611		if (ret < 0) {
   1612			pm_runtime_put_noidle(&client->dev);
   1613			goto out;
   1614		}
   1615
   1616		ret = hi846_start_streaming(hi846);
   1617	}
   1618
   1619	if (!enable || ret) {
   1620		hi846_stop_streaming(hi846);
   1621		pm_runtime_put(&client->dev);
   1622	}
   1623
   1624out:
   1625	mutex_unlock(&hi846->mutex);
   1626
   1627	return ret;
   1628}
   1629
   1630static int hi846_power_on(struct hi846 *hi846)
   1631{
   1632	int ret;
   1633
   1634	ret = regulator_bulk_enable(HI846_NUM_SUPPLIES, hi846->supplies);
   1635	if (ret < 0)
   1636		return ret;
   1637
   1638	ret = clk_prepare_enable(hi846->clock);
   1639	if (ret < 0)
   1640		goto err_reg;
   1641
   1642	if (hi846->shutdown_gpio)
   1643		gpiod_set_value_cansleep(hi846->shutdown_gpio, 0);
   1644
   1645	/* 30us = 2400 cycles at 80Mhz */
   1646	usleep_range(30, 60);
   1647	if (hi846->rst_gpio)
   1648		gpiod_set_value_cansleep(hi846->rst_gpio, 0);
   1649	usleep_range(30, 60);
   1650
   1651	return 0;
   1652
   1653err_reg:
   1654	regulator_bulk_disable(HI846_NUM_SUPPLIES, hi846->supplies);
   1655
   1656	return ret;
   1657}
   1658
   1659static int hi846_power_off(struct hi846 *hi846)
   1660{
   1661	if (hi846->rst_gpio)
   1662		gpiod_set_value_cansleep(hi846->rst_gpio, 1);
   1663
   1664	if (hi846->shutdown_gpio)
   1665		gpiod_set_value_cansleep(hi846->shutdown_gpio, 1);
   1666
   1667	clk_disable_unprepare(hi846->clock);
   1668	return regulator_bulk_disable(HI846_NUM_SUPPLIES, hi846->supplies);
   1669}
   1670
   1671static int __maybe_unused hi846_suspend(struct device *dev)
   1672{
   1673	struct i2c_client *client = to_i2c_client(dev);
   1674	struct v4l2_subdev *sd = i2c_get_clientdata(client);
   1675	struct hi846 *hi846 = to_hi846(sd);
   1676
   1677	if (hi846->streaming)
   1678		hi846_stop_streaming(hi846);
   1679
   1680	return hi846_power_off(hi846);
   1681}
   1682
   1683static int __maybe_unused hi846_resume(struct device *dev)
   1684{
   1685	struct i2c_client *client = to_i2c_client(dev);
   1686	struct v4l2_subdev *sd = i2c_get_clientdata(client);
   1687	struct hi846 *hi846 = to_hi846(sd);
   1688	int ret;
   1689
   1690	ret = hi846_power_on(hi846);
   1691	if (ret)
   1692		return ret;
   1693
   1694	if (hi846->streaming) {
   1695		ret = hi846_start_streaming(hi846);
   1696		if (ret) {
   1697			dev_err(dev, "%s: start streaming failed: %d\n",
   1698				__func__, ret);
   1699			goto error;
   1700		}
   1701	}
   1702
   1703	return 0;
   1704
   1705error:
   1706	hi846_power_off(hi846);
   1707	return ret;
   1708}
   1709
   1710static int hi846_set_format(struct v4l2_subdev *sd,
   1711			    struct v4l2_subdev_state *sd_state,
   1712			    struct v4l2_subdev_format *format)
   1713{
   1714	struct hi846 *hi846 = to_hi846(sd);
   1715	struct v4l2_mbus_framefmt *mf = &format->format;
   1716	struct i2c_client *client = v4l2_get_subdevdata(sd);
   1717	const struct hi846_datafmt *fmt = hi846_find_datafmt(mf->code);
   1718	u32 tgt_fps;
   1719	s32 vblank_def, h_blank;
   1720
   1721	if (!fmt) {
   1722		mf->code = hi846_colour_fmts[0].code;
   1723		mf->colorspace = hi846_colour_fmts[0].colorspace;
   1724		fmt = &hi846_colour_fmts[0];
   1725	}
   1726
   1727	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
   1728		*v4l2_subdev_get_try_format(sd, sd_state, format->pad) = *mf;
   1729		return 0;
   1730	}
   1731
   1732	if (hi846->nr_lanes == 2) {
   1733		if (!hi846->cur_mode->reg_list_2lane.num_of_regs) {
   1734			dev_err(&client->dev,
   1735				"this mode is not supported for 2 lanes\n");
   1736			return -EINVAL;
   1737		}
   1738	} else {
   1739		if (!hi846->cur_mode->reg_list_4lane.num_of_regs) {
   1740			dev_err(&client->dev,
   1741				"this mode is not supported for 4 lanes\n");
   1742			return -EINVAL;
   1743		}
   1744	}
   1745
   1746	mutex_lock(&hi846->mutex);
   1747
   1748	if (hi846->streaming) {
   1749		mutex_unlock(&hi846->mutex);
   1750		return -EBUSY;
   1751	}
   1752
   1753	hi846->fmt = fmt;
   1754
   1755	hi846->cur_mode =
   1756		v4l2_find_nearest_size(supported_modes,
   1757				       ARRAY_SIZE(supported_modes),
   1758				       width, height, mf->width, mf->height);
   1759	dev_dbg(&client->dev, "%s: found mode: %dx%d\n", __func__,
   1760		hi846->cur_mode->width, hi846->cur_mode->height);
   1761
   1762	tgt_fps = hi846->cur_mode->fps;
   1763	dev_dbg(&client->dev, "%s: target fps: %d\n", __func__, tgt_fps);
   1764
   1765	mf->width = hi846->cur_mode->width;
   1766	mf->height = hi846->cur_mode->height;
   1767	mf->code = HI846_MEDIA_BUS_FORMAT;
   1768	mf->field = V4L2_FIELD_NONE;
   1769
   1770	__v4l2_ctrl_s_ctrl(hi846->link_freq, hi846_get_link_freq_index(hi846));
   1771	__v4l2_ctrl_s_ctrl_int64(hi846->pixel_rate,
   1772				 hi846_calc_pixel_rate(hi846));
   1773
   1774	/* Update limits and set FPS to default */
   1775	vblank_def = hi846->cur_mode->frame_len - hi846->cur_mode->height;
   1776	__v4l2_ctrl_modify_range(hi846->vblank,
   1777				 hi846->cur_mode->frame_len -
   1778					hi846->cur_mode->height,
   1779				 HI846_FLL_MAX - hi846->cur_mode->height, 1,
   1780				 vblank_def);
   1781	__v4l2_ctrl_s_ctrl(hi846->vblank, vblank_def);
   1782
   1783	h_blank = hi846->cur_mode->llp - hi846->cur_mode->width;
   1784
   1785	__v4l2_ctrl_modify_range(hi846->hblank, h_blank, h_blank, 1,
   1786				 h_blank);
   1787
   1788	dev_dbg(&client->dev, "Set fmt w=%d h=%d code=0x%x colorspace=0x%x\n",
   1789		mf->width, mf->height,
   1790		fmt->code, fmt->colorspace);
   1791
   1792	mutex_unlock(&hi846->mutex);
   1793
   1794	return 0;
   1795}
   1796
   1797static int hi846_get_format(struct v4l2_subdev *sd,
   1798			    struct v4l2_subdev_state *sd_state,
   1799			    struct v4l2_subdev_format *format)
   1800{
   1801	struct hi846 *hi846 = to_hi846(sd);
   1802	struct v4l2_mbus_framefmt *mf = &format->format;
   1803	struct i2c_client *client = v4l2_get_subdevdata(sd);
   1804
   1805	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
   1806		format->format = *v4l2_subdev_get_try_format(&hi846->sd,
   1807							sd_state,
   1808							format->pad);
   1809		return 0;
   1810	}
   1811
   1812	mutex_lock(&hi846->mutex);
   1813	mf->code        = HI846_MEDIA_BUS_FORMAT;
   1814	mf->colorspace  = V4L2_COLORSPACE_RAW;
   1815	mf->field       = V4L2_FIELD_NONE;
   1816	mf->width       = hi846->cur_mode->width;
   1817	mf->height      = hi846->cur_mode->height;
   1818	mutex_unlock(&hi846->mutex);
   1819	dev_dbg(&client->dev,
   1820		"Get format w=%d h=%d code=0x%x colorspace=0x%x\n",
   1821		mf->width, mf->height, mf->code, mf->colorspace);
   1822
   1823	return 0;
   1824}
   1825
   1826static int hi846_enum_mbus_code(struct v4l2_subdev *sd,
   1827				struct v4l2_subdev_state *sd_state,
   1828				struct v4l2_subdev_mbus_code_enum *code)
   1829{
   1830	if (code->pad || code->index > 0)
   1831		return -EINVAL;
   1832
   1833	code->code = HI846_MEDIA_BUS_FORMAT;
   1834
   1835	return 0;
   1836}
   1837
   1838static int hi846_enum_frame_size(struct v4l2_subdev *sd,
   1839				 struct v4l2_subdev_state *sd_state,
   1840				 struct v4l2_subdev_frame_size_enum *fse)
   1841{
   1842	struct i2c_client *client = v4l2_get_subdevdata(sd);
   1843
   1844	if (fse->pad || fse->index >= ARRAY_SIZE(supported_modes))
   1845		return -EINVAL;
   1846
   1847	if (fse->code != HI846_MEDIA_BUS_FORMAT) {
   1848		dev_err(&client->dev, "frame size enum not matching\n");
   1849		return -EINVAL;
   1850	}
   1851
   1852	fse->min_width = supported_modes[fse->index].width;
   1853	fse->max_width = supported_modes[fse->index].width;
   1854	fse->min_height = supported_modes[fse->index].height;
   1855	fse->max_height = supported_modes[fse->index].height;
   1856
   1857	dev_dbg(&client->dev, "%s: max width: %d max height: %d\n", __func__,
   1858		fse->max_width, fse->max_height);
   1859
   1860	return 0;
   1861}
   1862
   1863static int hi846_get_selection(struct v4l2_subdev *sd,
   1864			       struct v4l2_subdev_state *sd_state,
   1865			       struct v4l2_subdev_selection *sel)
   1866{
   1867	struct hi846 *hi846 = to_hi846(sd);
   1868
   1869	switch (sel->target) {
   1870	case V4L2_SEL_TGT_CROP:
   1871	case V4L2_SEL_TGT_CROP_DEFAULT:
   1872		mutex_lock(&hi846->mutex);
   1873		switch (sel->which) {
   1874		case V4L2_SUBDEV_FORMAT_TRY:
   1875			v4l2_subdev_get_try_crop(sd, sd_state, sel->pad);
   1876			break;
   1877		case V4L2_SUBDEV_FORMAT_ACTIVE:
   1878			sel->r = hi846->cur_mode->crop;
   1879			break;
   1880		}
   1881		mutex_unlock(&hi846->mutex);
   1882		return 0;
   1883	case V4L2_SEL_TGT_CROP_BOUNDS:
   1884	case V4L2_SEL_TGT_NATIVE_SIZE:
   1885		sel->r.top = 0;
   1886		sel->r.left = 0;
   1887		sel->r.width = 3264;
   1888		sel->r.height = 2448;
   1889		return 0;
   1890	default:
   1891		return -EINVAL;
   1892	}
   1893}
   1894
   1895static int hi846_init_cfg(struct v4l2_subdev *sd,
   1896			  struct v4l2_subdev_state *sd_state)
   1897{
   1898	struct hi846 *hi846 = to_hi846(sd);
   1899	struct v4l2_mbus_framefmt *mf;
   1900
   1901	mf = v4l2_subdev_get_try_format(sd, sd_state, 0);
   1902
   1903	mutex_lock(&hi846->mutex);
   1904	mf->code        = HI846_MEDIA_BUS_FORMAT;
   1905	mf->colorspace  = V4L2_COLORSPACE_RAW;
   1906	mf->field       = V4L2_FIELD_NONE;
   1907	mf->width       = hi846->cur_mode->width;
   1908	mf->height      = hi846->cur_mode->height;
   1909	mutex_unlock(&hi846->mutex);
   1910
   1911	return 0;
   1912}
   1913
   1914static const struct v4l2_subdev_video_ops hi846_video_ops = {
   1915	.s_stream = hi846_set_stream,
   1916};
   1917
   1918static const struct v4l2_subdev_pad_ops hi846_pad_ops = {
   1919	.init_cfg = hi846_init_cfg,
   1920	.enum_frame_size = hi846_enum_frame_size,
   1921	.enum_mbus_code = hi846_enum_mbus_code,
   1922	.set_fmt = hi846_set_format,
   1923	.get_fmt = hi846_get_format,
   1924	.get_selection = hi846_get_selection,
   1925};
   1926
   1927static const struct v4l2_subdev_ops hi846_subdev_ops = {
   1928	.video = &hi846_video_ops,
   1929	.pad = &hi846_pad_ops,
   1930};
   1931
   1932static const struct media_entity_operations hi846_subdev_entity_ops = {
   1933	.link_validate = v4l2_subdev_link_validate,
   1934};
   1935
   1936static int hi846_identify_module(struct hi846 *hi846)
   1937{
   1938	struct i2c_client *client = v4l2_get_subdevdata(&hi846->sd);
   1939	int ret;
   1940	u8 hi, lo;
   1941
   1942	ret = hi846_read_reg(hi846, HI846_REG_CHIP_ID_L, &lo);
   1943	if (ret)
   1944		return ret;
   1945
   1946	if (lo != HI846_CHIP_ID_L) {
   1947		dev_err(&client->dev, "wrong chip id low byte: %x", lo);
   1948		return -ENXIO;
   1949	}
   1950
   1951	ret = hi846_read_reg(hi846, HI846_REG_CHIP_ID_H, &hi);
   1952	if (ret)
   1953		return ret;
   1954
   1955	if (hi != HI846_CHIP_ID_H) {
   1956		dev_err(&client->dev, "wrong chip id high byte: %x", hi);
   1957		return -ENXIO;
   1958	}
   1959
   1960	dev_info(&client->dev, "chip id %02X %02X using %d mipi lanes\n",
   1961		 hi, lo, hi846->nr_lanes);
   1962
   1963	return 0;
   1964}
   1965
   1966static s64 hi846_check_link_freqs(struct hi846 *hi846,
   1967				  struct v4l2_fwnode_endpoint *ep)
   1968{
   1969	const s64 *freqs = hi846_link_freqs;
   1970	int freqs_count = ARRAY_SIZE(hi846_link_freqs);
   1971	int i, j;
   1972
   1973	for (i = 0; i < freqs_count; i++) {
   1974		for (j = 0; j < ep->nr_of_link_frequencies; j++)
   1975			if (freqs[i] == ep->link_frequencies[j])
   1976				break;
   1977		if (j == ep->nr_of_link_frequencies)
   1978			return freqs[i];
   1979	}
   1980
   1981	return 0;
   1982}
   1983
   1984static int hi846_parse_dt(struct hi846 *hi846, struct device *dev)
   1985{
   1986	struct fwnode_handle *ep;
   1987	struct fwnode_handle *fwnode = dev_fwnode(dev);
   1988	struct v4l2_fwnode_endpoint bus_cfg = {
   1989		.bus_type = V4L2_MBUS_CSI2_DPHY
   1990	};
   1991	int ret;
   1992	s64 fq;
   1993
   1994	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
   1995	if (!ep) {
   1996		dev_err(dev, "unable to find endpoint node\n");
   1997		return -ENXIO;
   1998	}
   1999
   2000	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
   2001	fwnode_handle_put(ep);
   2002	if (ret) {
   2003		dev_err(dev, "failed to parse endpoint node: %d\n", ret);
   2004		return ret;
   2005	}
   2006
   2007	if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2 &&
   2008	    bus_cfg.bus.mipi_csi2.num_data_lanes != 4) {
   2009		dev_err(dev, "number of CSI2 data lanes %d is not supported",
   2010			bus_cfg.bus.mipi_csi2.num_data_lanes);
   2011		v4l2_fwnode_endpoint_free(&bus_cfg);
   2012		return -EINVAL;
   2013	}
   2014
   2015	hi846->nr_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
   2016
   2017	if (!bus_cfg.nr_of_link_frequencies) {
   2018		dev_err(dev, "link-frequency property not found in DT\n");
   2019		return -EINVAL;
   2020	}
   2021
   2022	/* Check that link frequences for all the modes are in device tree */
   2023	fq = hi846_check_link_freqs(hi846, &bus_cfg);
   2024	if (fq) {
   2025		dev_err(dev, "Link frequency of %lld is not supported\n", fq);
   2026		return -EINVAL;
   2027	}
   2028
   2029	v4l2_fwnode_endpoint_free(&bus_cfg);
   2030
   2031	hi846->rst_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
   2032	if (IS_ERR(hi846->rst_gpio)) {
   2033		dev_err(dev, "failed to get reset gpio: %pe\n",
   2034			hi846->rst_gpio);
   2035		return PTR_ERR(hi846->rst_gpio);
   2036	}
   2037
   2038	hi846->shutdown_gpio = devm_gpiod_get_optional(dev, "shutdown",
   2039						       GPIOD_OUT_LOW);
   2040	if (IS_ERR(hi846->shutdown_gpio)) {
   2041		dev_err(dev, "failed to get shutdown gpio: %pe\n",
   2042			hi846->shutdown_gpio);
   2043		return PTR_ERR(hi846->shutdown_gpio);
   2044	}
   2045
   2046	return 0;
   2047}
   2048
   2049static int hi846_probe(struct i2c_client *client)
   2050{
   2051	struct hi846 *hi846;
   2052	int ret;
   2053	int i;
   2054	u32 mclk_freq;
   2055
   2056	hi846 = devm_kzalloc(&client->dev, sizeof(*hi846), GFP_KERNEL);
   2057	if (!hi846)
   2058		return -ENOMEM;
   2059
   2060	ret = hi846_parse_dt(hi846, &client->dev);
   2061	if (ret) {
   2062		dev_err(&client->dev, "failed to check HW configuration: %d",
   2063			ret);
   2064		return ret;
   2065	}
   2066
   2067	hi846->clock = devm_clk_get(&client->dev, NULL);
   2068	if (IS_ERR(hi846->clock)) {
   2069		dev_err(&client->dev, "failed to get clock: %pe\n",
   2070			hi846->clock);
   2071		return PTR_ERR(hi846->clock);
   2072	}
   2073
   2074	mclk_freq = clk_get_rate(hi846->clock);
   2075	if (mclk_freq != 25000000)
   2076		dev_warn(&client->dev,
   2077			 "External clock freq should be 25000000, not %u.\n",
   2078			 mclk_freq);
   2079
   2080	for (i = 0; i < HI846_NUM_SUPPLIES; i++)
   2081		hi846->supplies[i].supply = hi846_supply_names[i];
   2082
   2083	ret = devm_regulator_bulk_get(&client->dev, HI846_NUM_SUPPLIES,
   2084				      hi846->supplies);
   2085	if (ret < 0)
   2086		return ret;
   2087
   2088	v4l2_i2c_subdev_init(&hi846->sd, client, &hi846_subdev_ops);
   2089
   2090	mutex_init(&hi846->mutex);
   2091
   2092	ret = hi846_power_on(hi846);
   2093	if (ret)
   2094		goto err_mutex;
   2095
   2096	ret = hi846_identify_module(hi846);
   2097	if (ret)
   2098		goto err_power_off;
   2099
   2100	hi846->cur_mode = &supported_modes[0];
   2101
   2102	ret = hi846_init_controls(hi846);
   2103	if (ret) {
   2104		dev_err(&client->dev, "failed to init controls: %d", ret);
   2105		goto err_power_off;
   2106	}
   2107
   2108	hi846->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
   2109	hi846->sd.entity.ops = &hi846_subdev_entity_ops;
   2110	hi846->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
   2111	hi846->pad.flags = MEDIA_PAD_FL_SOURCE;
   2112	ret = media_entity_pads_init(&hi846->sd.entity, 1, &hi846->pad);
   2113	if (ret) {
   2114		dev_err(&client->dev, "failed to init entity pads: %d", ret);
   2115		goto err_v4l2_ctrl_handler_free;
   2116	}
   2117
   2118	ret = v4l2_async_register_subdev_sensor(&hi846->sd);
   2119	if (ret < 0) {
   2120		dev_err(&client->dev, "failed to register V4L2 subdev: %d",
   2121			ret);
   2122		goto err_media_entity_cleanup;
   2123	}
   2124
   2125	pm_runtime_set_active(&client->dev);
   2126	pm_runtime_enable(&client->dev);
   2127	pm_runtime_idle(&client->dev);
   2128
   2129	return 0;
   2130
   2131err_media_entity_cleanup:
   2132	media_entity_cleanup(&hi846->sd.entity);
   2133
   2134err_v4l2_ctrl_handler_free:
   2135	v4l2_ctrl_handler_free(hi846->sd.ctrl_handler);
   2136
   2137err_power_off:
   2138	hi846_power_off(hi846);
   2139
   2140err_mutex:
   2141	mutex_destroy(&hi846->mutex);
   2142
   2143	return ret;
   2144}
   2145
   2146static int hi846_remove(struct i2c_client *client)
   2147{
   2148	struct v4l2_subdev *sd = i2c_get_clientdata(client);
   2149	struct hi846 *hi846 = to_hi846(sd);
   2150
   2151	v4l2_async_unregister_subdev(sd);
   2152	media_entity_cleanup(&sd->entity);
   2153	v4l2_ctrl_handler_free(sd->ctrl_handler);
   2154
   2155	pm_runtime_disable(&client->dev);
   2156	if (!pm_runtime_status_suspended(&client->dev))
   2157		hi846_suspend(&client->dev);
   2158	pm_runtime_set_suspended(&client->dev);
   2159
   2160	mutex_destroy(&hi846->mutex);
   2161
   2162	return 0;
   2163}
   2164
   2165static const struct dev_pm_ops hi846_pm_ops = {
   2166	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
   2167				pm_runtime_force_resume)
   2168	SET_RUNTIME_PM_OPS(hi846_suspend, hi846_resume, NULL)
   2169};
   2170
   2171static const struct of_device_id hi846_of_match[] = {
   2172	{ .compatible = "hynix,hi846", },
   2173	{},
   2174};
   2175MODULE_DEVICE_TABLE(of, hi846_of_match);
   2176
   2177static struct i2c_driver hi846_i2c_driver = {
   2178	.driver = {
   2179		.name = "hi846",
   2180		.pm = &hi846_pm_ops,
   2181		.of_match_table = hi846_of_match,
   2182	},
   2183	.probe_new = hi846_probe,
   2184	.remove = hi846_remove,
   2185};
   2186
   2187module_i2c_driver(hi846_i2c_driver);
   2188
   2189MODULE_AUTHOR("Angus Ainslie <angus@akkea.ca>");
   2190MODULE_AUTHOR("Martin Kepplinger <martin.kepplinger@puri.sm>");
   2191MODULE_DESCRIPTION("Hynix HI846 sensor driver");
   2192MODULE_LICENSE("GPL v2");