xref: /openbmc/linux/drivers/media/i2c/isl7998x.c (revision 51ef2be5)
1*51ef2be5SMarek Vasut // SPDX-License-Identifier: GPL-2.0
2*51ef2be5SMarek Vasut /*
3*51ef2be5SMarek Vasut  * Intersil ISL7998x analog to MIPI CSI-2 or BT.656 decoder driver.
4*51ef2be5SMarek Vasut  *
5*51ef2be5SMarek Vasut  * Copyright (C) 2018-2019 Marek Vasut <marex@denx.de>
6*51ef2be5SMarek Vasut  * Copyright (C) 2021 Michael Tretter <kernel@pengutronix.de>
7*51ef2be5SMarek Vasut  */
8*51ef2be5SMarek Vasut 
9*51ef2be5SMarek Vasut #include <linux/bitfield.h>
10*51ef2be5SMarek Vasut #include <linux/delay.h>
11*51ef2be5SMarek Vasut #include <linux/gpio.h>
12*51ef2be5SMarek Vasut #include <linux/i2c.h>
13*51ef2be5SMarek Vasut #include <linux/module.h>
14*51ef2be5SMarek Vasut #include <linux/of_graph.h>
15*51ef2be5SMarek Vasut #include <linux/pm_runtime.h>
16*51ef2be5SMarek Vasut #include <linux/regmap.h>
17*51ef2be5SMarek Vasut #include <linux/slab.h>
18*51ef2be5SMarek Vasut #include <linux/v4l2-mediabus.h>
19*51ef2be5SMarek Vasut #include <linux/videodev2.h>
20*51ef2be5SMarek Vasut 
21*51ef2be5SMarek Vasut #include <media/v4l2-async.h>
22*51ef2be5SMarek Vasut #include <media/v4l2-common.h>
23*51ef2be5SMarek Vasut #include <media/v4l2-ctrls.h>
24*51ef2be5SMarek Vasut #include <media/v4l2-device.h>
25*51ef2be5SMarek Vasut #include <media/v4l2-fwnode.h>
26*51ef2be5SMarek Vasut #include <media/v4l2-ioctl.h>
27*51ef2be5SMarek Vasut 
28*51ef2be5SMarek Vasut /*
29*51ef2be5SMarek Vasut  * This control allows to activate and deactivate the test pattern on
30*51ef2be5SMarek Vasut  * selected output channels.
31*51ef2be5SMarek Vasut  * This value is ISL7998x specific.
32*51ef2be5SMarek Vasut  */
33*51ef2be5SMarek Vasut #define V4L2_CID_TEST_PATTERN_CHANNELS	(V4L2_CID_USER_ISL7998X_BASE + 0)
34*51ef2be5SMarek Vasut 
35*51ef2be5SMarek Vasut /*
36*51ef2be5SMarek Vasut  * This control allows to specify the color of the test pattern.
37*51ef2be5SMarek Vasut  * This value is ISL7998x specific.
38*51ef2be5SMarek Vasut  */
39*51ef2be5SMarek Vasut #define V4L2_CID_TEST_PATTERN_COLOR	(V4L2_CID_USER_ISL7998X_BASE + 1)
40*51ef2be5SMarek Vasut 
41*51ef2be5SMarek Vasut /*
42*51ef2be5SMarek Vasut  * This control allows to specify the bar pattern in the test pattern.
43*51ef2be5SMarek Vasut  * This value is ISL7998x specific.
44*51ef2be5SMarek Vasut  */
45*51ef2be5SMarek Vasut #define V4L2_CID_TEST_PATTERN_BARS	(V4L2_CID_USER_ISL7998X_BASE + 2)
46*51ef2be5SMarek Vasut 
47*51ef2be5SMarek Vasut #define ISL7998X_INPUTS			4
48*51ef2be5SMarek Vasut 
49*51ef2be5SMarek Vasut #define ISL7998X_REG(page, reg)		(((page) << 8) | (reg))
50*51ef2be5SMarek Vasut 
51*51ef2be5SMarek Vasut #define ISL7998X_REG_PN_SIZE			256
52*51ef2be5SMarek Vasut #define ISL7998X_REG_PN_BASE(n)			((n) * ISL7998X_REG_PN_SIZE)
53*51ef2be5SMarek Vasut 
54*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_PAGE(page)		ISL7998X_REG((page), 0xff)
55*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_PAGE_MASK		0xf
56*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_PRODUCT_ID_CODE		ISL7998X_REG(0, 0x00)
57*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_PRODUCT_REV_CODE	ISL7998X_REG(0, 0x01)
58*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_SW_RESET_CTL		ISL7998X_REG(0, 0x02)
59*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_IO_BUFFER_CTL		ISL7998X_REG(0, 0x03)
60*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_IO_BUFFER_CTL_1_1	ISL7998X_REG(0, 0x04)
61*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_IO_PAD_PULL_EN_CTL	ISL7998X_REG(0, 0x05)
62*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_IO_BUFFER_CTL_1_2	ISL7998X_REG(0, 0x06)
63*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_VIDEO_IN_CHAN_CTL	ISL7998X_REG(0, 0x07)
64*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CLK_CTL_1		ISL7998X_REG(0, 0x08)
65*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CLK_CTL_2		ISL7998X_REG(0, 0x09)
66*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CLK_CTL_3		ISL7998X_REG(0, 0x0a)
67*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CLK_CTL_4		ISL7998X_REG(0, 0x0b)
68*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_MPP1_SYNC_CTL		ISL7998X_REG(0, 0x0c)
69*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_MPP2_SYNC_CTL		ISL7998X_REG(0, 0x0d)
70*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_IRQ_SYNC_CTL		ISL7998X_REG(0, 0x0e)
71*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_INTERRUPT_STATUS	ISL7998X_REG(0, 0x10)
72*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_1_IRQ		ISL7998X_REG(0, 0x11)
73*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_2_IRQ		ISL7998X_REG(0, 0x12)
74*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_3_IRQ		ISL7998X_REG(0, 0x13)
75*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_4_IRQ		ISL7998X_REG(0, 0x14)
76*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_SHORT_DIAG_IRQ		ISL7998X_REG(0, 0x15)
77*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_1_IRQ_EN		ISL7998X_REG(0, 0x16)
78*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_2_IRQ_EN		ISL7998X_REG(0, 0x17)
79*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_3_IRQ_EN		ISL7998X_REG(0, 0x18)
80*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_4_IRQ_EN		ISL7998X_REG(0, 0x19)
81*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN	ISL7998X_REG(0, 0x1a)
82*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_1_STATUS		ISL7998X_REG(0, 0x1b)
83*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_2_STATUS		ISL7998X_REG(0, 0x1c)
84*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_3_STATUS		ISL7998X_REG(0, 0x1d)
85*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CHAN_4_STATUS		ISL7998X_REG(0, 0x1e)
86*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_SHORT_DIAG_STATUS	ISL7998X_REG(0, 0x1f)
87*51ef2be5SMarek Vasut #define ISL7998X_REG_P0_CLOCK_DELAY		ISL7998X_REG(0, 0x20)
88*51ef2be5SMarek Vasut 
89*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_INPUT_FMT(pg)	ISL7998X_REG((pg), 0x02)
90*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_STATUS_1(pg)	ISL7998X_REG((pg), 0x03)
91*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_STATUS_1_VDLOSS	BIT(7)
92*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_STATUS_1_HLOCK	BIT(6)
93*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_STATUS_1_VLOCK	BIT(3)
94*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_HS_DELAY_CTL(pg)	ISL7998X_REG((pg), 0x04)
95*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_ANCTL(pg)		ISL7998X_REG((pg), 0x06)
96*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CROP_HI(pg)		ISL7998X_REG((pg), 0x07)
97*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_VDELAY_LO(pg)	ISL7998X_REG((pg), 0x08)
98*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_VACTIVE_LO(pg)	ISL7998X_REG((pg), 0x09)
99*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_HDELAY_LO(pg)	ISL7998X_REG((pg), 0x0a)
100*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_HACTIVE_LO(pg)	ISL7998X_REG((pg), 0x0b)
101*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CNTRL1(pg)		ISL7998X_REG((pg), 0x0c)
102*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CSC_CTL(pg)		ISL7998X_REG((pg), 0x0d)
103*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_BRIGHT(pg)		ISL7998X_REG((pg), 0x10)
104*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CONTRAST(pg)	ISL7998X_REG((pg), 0x11)
105*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SHARPNESS(pg)	ISL7998X_REG((pg), 0x12)
106*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SAT_U(pg)		ISL7998X_REG((pg), 0x13)
107*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SAT_V(pg)		ISL7998X_REG((pg), 0x14)
108*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_HUE(pg)		ISL7998X_REG((pg), 0x15)
109*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_VERT_PEAK(pg)	ISL7998X_REG((pg), 0x17)
110*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CORING(pg)		ISL7998X_REG((pg), 0x18)
111*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT(pg)		ISL7998X_REG((pg), 0x1c)
112*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_DET		BIT(7)
113*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_NOW		GENMASK(6, 4)
114*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD	GENMASK(2, 0)
115*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_M		0
116*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL		1
117*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_SECAM		2
118*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_443	3
119*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_M		4
120*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_CN		5
121*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_60		6
122*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN	7
123*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDTR(pg)		ISL7998X_REG((pg), 0x1d)
124*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SDTR_ATSTART	BIT(7)
125*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CLMPG(pg)		ISL7998X_REG((pg), 0x20)
126*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_IAGC(pg)		ISL7998X_REG((pg), 0x21)
127*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_AGCGAIN(pg)		ISL7998X_REG((pg), 0x22)
128*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_PEAKWT(pg)		ISL7998X_REG((pg), 0x23)
129*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CLMPL(pg)		ISL7998X_REG((pg), 0x24)
130*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SYNCT(pg)		ISL7998X_REG((pg), 0x25)
131*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_MISSCNT(pg)		ISL7998X_REG((pg), 0x26)
132*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_PCLAMP(pg)		ISL7998X_REG((pg), 0x27)
133*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_VERT_CTL_1(pg)	ISL7998X_REG((pg), 0x28)
134*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_VERT_CTL_2(pg)	ISL7998X_REG((pg), 0x29)
135*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CLR_KILL_LVL(pg)	ISL7998X_REG((pg), 0x2a)
136*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_COMB_FILTER_CTL(pg)	ISL7998X_REG((pg), 0x2b)
137*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_LUMA_DELAY(pg)	ISL7998X_REG((pg), 0x2c)
138*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_MISC1(pg)		ISL7998X_REG((pg), 0x2d)
139*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_MISC2(pg)		ISL7998X_REG((pg), 0x2e)
140*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_MISC3(pg)		ISL7998X_REG((pg), 0x2f)
141*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_MVSN(pg)		ISL7998X_REG((pg), 0x30)
142*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CSTATUS2(pg)	ISL7998X_REG((pg), 0x31)
143*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_HFREF(pg)		ISL7998X_REG((pg), 0x32)
144*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CLMD(pg)		ISL7998X_REG((pg), 0x33)
145*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_ID_DET_CTL(pg)	ISL7998X_REG((pg), 0x34)
146*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_CLCNTL(pg)		ISL7998X_REG((pg), 0x35)
147*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_1(pg)	ISL7998X_REG((pg), 0x36)
148*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_2(pg)	ISL7998X_REG((pg), 0x37)
149*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_3(pg)	ISL7998X_REG((pg), 0x38)
150*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_DIFF_CLMP_CTL_4(pg)	ISL7998X_REG((pg), 0x39)
151*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SHORT_DET_CTL(pg)	ISL7998X_REG((pg), 0x3a)
152*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(pg)	ISL7998X_REG((pg), 0x3b)
153*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_AFE_TST_MUX_CTL(pg)	ISL7998X_REG((pg), 0x3c)
154*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_DATA_CONV(pg)	ISL7998X_REG((pg), 0x3d)
155*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_INTERNAL_TEST(pg)	ISL7998X_REG((pg), 0x3f)
156*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_H_DELAY_CTL(pg)	ISL7998X_REG((pg), 0x43)
157*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_H_DELAY_II_HI(pg)	ISL7998X_REG((pg), 0x44)
158*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(pg)	ISL7998X_REG((pg), 0x45)
159*51ef2be5SMarek Vasut 
160*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_CTL_1(pg)		ISL7998X_REG((pg), 0x80)
161*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_GAIN_CTL(pg)	ISL7998X_REG((pg), 0x81)
162*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_AVG_HI_LIMIT(pg)	ISL7998X_REG((pg), 0x82)
163*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_AVG_LO_LIMIT(pg)	ISL7998X_REG((pg), 0x83)
164*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_DET_THRESHOLD(pg)	ISL7998X_REG((pg), 0x84)
165*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_BLACK_LVL(pg)	ISL7998X_REG((pg), 0x85)
166*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_CENTER_LVL(pg)	ISL7998X_REG((pg), 0x86)
167*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_WHITE_LVL(pg)	ISL7998X_REG((pg), 0x87)
168*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_MEAN_OFF_LIMIT(pg)	ISL7998X_REG((pg), 0x88)
169*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_MEAN_OFF_UPGAIN(pg)	ISL7998X_REG((pg), 0x89)
170*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_MEAN_OFF_SLOPE(pg)	ISL7998X_REG((pg), 0x8a)
171*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_MEAN_OFF_DNGAIN(pg)	ISL7998X_REG((pg), 0x8b)
172*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_DELTA_CO_THRES(pg)	ISL7998X_REG((pg), 0x8c)
173*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_DELTA_SLOPE(pg)	ISL7998X_REG((pg), 0x8d)
174*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_HI_AVG_THRES(pg)	ISL7998X_REG((pg), 0x8e)
175*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_MAX_LVL_CTL(pg)	ISL7998X_REG((pg), 0x8f)
176*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HI_MAX_LVL_CTL(pg)	ISL7998X_REG((pg), 0x90)
177*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_UPGAIN_CTL(pg)	ISL7998X_REG((pg), 0x91)
178*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_DNGAIN_CTL(pg)	ISL7998X_REG((pg), 0x92)
179*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HI_UPGAIN_CTL(pg)	ISL7998X_REG((pg), 0x93)
180*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HI_DNGAIN_CTL(pg)	ISL7998X_REG((pg), 0x94)
181*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LOPASS_FLT_COEF(pg)	ISL7998X_REG((pg), 0x95)
182*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_PDF_INDEX(pg)	ISL7998X_REG((pg), 0x96)
183*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_H_STT(pg)	ISL7998X_REG((pg), 0x97)
184*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_H_SZ1(pg)	ISL7998X_REG((pg), 0x98)
185*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_H_SZ2(pg)	ISL7998X_REG((pg), 0x99)
186*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_V_STT(pg)	ISL7998X_REG((pg), 0x9a)
187*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ1(pg)	ISL7998X_REG((pg), 0x9b)
188*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2(pg)	ISL7998X_REG((pg), 0x9c)
189*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_AVG(pg)		ISL7998X_REG((pg), 0xa0)
190*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_AVG_LIM(pg)	ISL7998X_REG((pg), 0xa1)
191*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_AVG(pg)		ISL7998X_REG((pg), 0xa2)
192*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HI_AVG(pg)		ISL7998X_REG((pg), 0xa3)
193*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_MAX(pg)		ISL7998X_REG((pg), 0xa4)
194*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_MIN(pg)		ISL7998X_REG((pg), 0xa5)
195*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_MOFFSET(pg)		ISL7998X_REG((pg), 0xa6)
196*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LO_GAIN(pg)		ISL7998X_REG((pg), 0xa7)
197*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HI_GAIN(pg)		ISL7998X_REG((pg), 0xa8)
198*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LL_SLOPE(pg)	ISL7998X_REG((pg), 0xa9)
199*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_LH_SLOPE(pg)	ISL7998X_REG((pg), 0xaa)
200*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HL_SLOPE(pg)	ISL7998X_REG((pg), 0xab)
201*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HH_SLOPE(pg)	ISL7998X_REG((pg), 0xac)
202*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_X_LOW(pg)		ISL7998X_REG((pg), 0xad)
203*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_X_MEAN(pg)		ISL7998X_REG((pg), 0xae)
204*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_X_HIGH(pg)		ISL7998X_REG((pg), 0xaf)
205*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_LOW(pg)		ISL7998X_REG((pg), 0xb0)
206*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_MEAN(pg)		ISL7998X_REG((pg), 0xb1)
207*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_Y_HIGH(pg)		ISL7998X_REG((pg), 0xb2)
208*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_CTL_2(pg)		ISL7998X_REG((pg), 0xb3)
209*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_CTL_3(pg)		ISL7998X_REG((pg), 0xb4)
210*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_CTL_4(pg)		ISL7998X_REG((pg), 0xb5)
211*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_HIST(pg)	ISL7998X_REG((pg), 0xc0)
212*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TL_H(pg)	ISL7998X_REG((pg), 0xc1)
213*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TL_L(pg)	ISL7998X_REG((pg), 0xc2)
214*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TL_H(pg)	ISL7998X_REG((pg), 0xc3)
215*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TL_L(pg)	ISL7998X_REG((pg), 0xc4)
216*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TR_H(pg)	ISL7998X_REG((pg), 0xc5)
217*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TR_L(pg)	ISL7998X_REG((pg), 0xc6)
218*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TR_H(pg)	ISL7998X_REG((pg), 0xc7)
219*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TR_L(pg)	ISL7998X_REG((pg), 0xc8)
220*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BL_H(pg)	ISL7998X_REG((pg), 0xc9)
221*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BL_L(pg)	ISL7998X_REG((pg), 0xca)
222*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BL_H(pg)	ISL7998X_REG((pg), 0xcb)
223*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BL_L(pg)	ISL7998X_REG((pg), 0xcc)
224*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BR_H(pg)	ISL7998X_REG((pg), 0xcd)
225*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BR_L(pg)	ISL7998X_REG((pg), 0xce)
226*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BR_H(pg)	ISL7998X_REG((pg), 0xcf)
227*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BR_L(pg)	ISL7998X_REG((pg), 0xd0)
228*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_LM_H(pg)	ISL7998X_REG((pg), 0xd1)
229*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_LM_L(pg)	ISL7998X_REG((pg), 0xd2)
230*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_LM_H(pg)	ISL7998X_REG((pg), 0xd3)
231*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_LM_L(pg)	ISL7998X_REG((pg), 0xd4)
232*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TM_H(pg)	ISL7998X_REG((pg), 0xd5)
233*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_TM_L(pg)	ISL7998X_REG((pg), 0xd6)
234*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TM_H(pg)	ISL7998X_REG((pg), 0xd7)
235*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_TM_L(pg)	ISL7998X_REG((pg), 0xd8)
236*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BM_H(pg)	ISL7998X_REG((pg), 0xd9)
237*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_BM_L(pg)	ISL7998X_REG((pg), 0xda)
238*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BM_H(pg)	ISL7998X_REG((pg), 0xdb)
239*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_BM_L(pg)	ISL7998X_REG((pg), 0xdc)
240*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_RM_H(pg)	ISL7998X_REG((pg), 0xdd)
241*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_X_RM_L(pg)	ISL7998X_REG((pg), 0xde)
242*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_RM_H(pg)	ISL7998X_REG((pg), 0xdf)
243*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_RM_L(pg)	ISL7998X_REG((pg), 0xe0)
244*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_DATA_LO(pg)	ISL7998X_REG((pg), 0xe1)
245*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_DATA_MID(pg)	ISL7998X_REG((pg), 0xe2)
246*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_HIST_DATA_HI(pg)	ISL7998X_REG((pg), 0xe3)
247*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_Y_CLR(pg)	ISL7998X_REG((pg), 0xe4)
248*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_CB_CLR(pg)	ISL7998X_REG((pg), 0xe5)
249*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_FLEX_WIN_CR_CLR(pg)	ISL7998X_REG((pg), 0xe6)
250*51ef2be5SMarek Vasut #define ISL7998X_REG_PX_ACA_XFER_HIST_HOST(pg)	ISL7998X_REG((pg), 0xe7)
251*51ef2be5SMarek Vasut 
252*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_CTL		ISL7998X_REG(5, 0x00)
253*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_LINE_CTL	ISL7998X_REG(5, 0x01)
254*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH	ISL7998X_REG(5, 0x02)
255*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL	ISL7998X_REG(5, 0x03)
256*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_VC_ASSIGNMENT	ISL7998X_REG(5, 0x04)
257*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL	ISL7998X_REG(5, 0x05)
258*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL	ISL7998X_REG(5, 0x06)
259*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_READ_START_CTL	ISL7998X_REG(5, 0x07)
260*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_PSEUDO_FRM_FIELD_CTL	ISL7998X_REG(5, 0x08)
261*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_ONE_FIELD_MODE_CTL	ISL7998X_REG(5, 0x09)
262*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_INT_HW_TST_CTR	ISL7998X_REG(5, 0x0a)
263*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_TP_GEN_BAR_PATTERN	ISL7998X_REG(5, 0x0b)
264*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_PCNT_PSFRM		ISL7998X_REG(5, 0x0c)
265*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL	ISL7998X_REG(5, 0x0d)
266*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_VBLANK_PSFRM	ISL7998X_REG(5, 0x0e)
267*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_LI_ENGINE_CTL_2		ISL7998X_REG(5, 0x0f)
268*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_WCNT_1		ISL7998X_REG(5, 0x10)
269*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_WCNT_2		ISL7998X_REG(5, 0x11)
270*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_1	ISL7998X_REG(5, 0x12)
271*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_2	ISL7998X_REG(5, 0x13)
272*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_3	ISL7998X_REG(5, 0x14)
273*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_4	ISL7998X_REG(5, 0x15)
274*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_5	ISL7998X_REG(5, 0x16)
275*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_6	ISL7998X_REG(5, 0x17)
276*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_PARAMS_1	ISL7998X_REG(5, 0x18)
277*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_SOT_PERIOD	ISL7998X_REG(5, 0x19)
278*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_EOT_PERIOD	ISL7998X_REG(5, 0x1a)
279*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_PARAMS_2	ISL7998X_REG(5, 0x1b)
280*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_7	ISL7998X_REG(5, 0x1c)
281*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_8	ISL7998X_REG(5, 0x1d)
282*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_9	ISL7998X_REG(5, 0x1e)
283*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_10	ISL7998X_REG(5, 0x1f)
284*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_TP_GEN_MIPI		ISL7998X_REG(5, 0x20)
285*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_ESC_MODE_TIME_CTL	ISL7998X_REG(5, 0x21)
286*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_AUTO_TEST_ERR_DET	ISL7998X_REG(5, 0x22)
287*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_TIMING		ISL7998X_REG(5, 0x23)
288*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_PIC_HEIGHT_HIGH		ISL7998X_REG(5, 0x24)
289*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_PIC_HEIGHT_LOW		ISL7998X_REG(5, 0x25)
290*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL	ISL7998X_REG(5, 0x26)
291*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_FIFO_THRSH_CNT_1	ISL7998X_REG(5, 0x28)
292*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_FIFO_THRSH_CNT_2	ISL7998X_REG(5, 0x29)
293*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1	ISL7998X_REG(5, 0x2a)
294*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2	ISL7998X_REG(5, 0x2b)
295*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_1	ISL7998X_REG(5, 0x2c)
296*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_2	ISL7998X_REG(5, 0x2d)
297*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_3	ISL7998X_REG(5, 0x2e)
298*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_PSF_FIELD_END_CTL_4	ISL7998X_REG(5, 0x2f)
299*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_1	ISL7998X_REG(5, 0x30)
300*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_2	ISL7998X_REG(5, 0x31)
301*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_ANA_CLK_CTL	ISL7998X_REG(5, 0x32)
302*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_PLL_ANA_STATUS		ISL7998X_REG(5, 0x33)
303*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_PLL_ANA_MISC_CTL	ISL7998X_REG(5, 0x34)
304*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_MIPI_ANA		ISL7998X_REG(5, 0x35)
305*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_PLL_ANA			ISL7998X_REG(5, 0x36)
306*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1	ISL7998X_REG(5, 0x38)
307*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_2	ISL7998X_REG(5, 0x39)
308*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_H_LINE_CNT_1		ISL7998X_REG(5, 0x3a)
309*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_H_LINE_CNT_2		ISL7998X_REG(5, 0x3b)
310*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_HIST_LINE_CNT_1		ISL7998X_REG(5, 0x3c)
311*51ef2be5SMarek Vasut #define ISL7998X_REG_P5_HIST_LINE_CNT_2		ISL7998X_REG(5, 0x3d)
312*51ef2be5SMarek Vasut 
313*51ef2be5SMarek Vasut static const struct reg_sequence isl7998x_init_seq_1[] = {
314*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN, 0xff },
315*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SDT(0x1), 0x00 },
316*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x1), 0x03 },
317*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SDT(0x2), 0x00 },
318*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x2), 0x03 },
319*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SDT(0x3), 0x00 },
320*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x3), 0x03 },
321*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SDT(0x4), 0x00 },
322*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_SHORT_DET_CTL_1(0x4), 0x03 },
323*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_CTL, 0x00 },
324*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_SW_RESET_CTL, 0x1f, 10 },
325*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_IO_BUFFER_CTL, 0x00 },
326*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_MPP2_SYNC_CTL, 0xc9 },
327*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_IRQ_SYNC_CTL, 0xc9 },
328*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CHAN_1_IRQ, 0x03 },
329*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CHAN_2_IRQ, 0x00 },
330*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CHAN_3_IRQ, 0x00 },
331*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CHAN_4_IRQ, 0x00 },
332*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_CTL, 0x02 },
333*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_LINE_CTL, 0x85 },
334*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH, 0xa0 },
335*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL, 0x18 },
336*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL, 0x40 },
337*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL, 0x40 },
338*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_WCNT_1, 0x05 },
339*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_WCNT_2, 0xa0 },
340*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_MIPI, 0x00 },
341*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_ESC_MODE_TIME_CTL, 0x0c },
342*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL, 0x00 },
343*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1, 0x00 },
344*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2, 0x19 },
345*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_1, 0x18 },
346*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_2, 0xf1 },
347*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_3, 0x00 },
348*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PSF_FIELD_END_CTL_4, 0xf1 },
349*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_1, 0x00 },
350*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_ANA_DATA_CTL_2, 0x00 },
351*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_ANA_CLK_CTL, 0x00 },
352*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PLL_ANA_STATUS, 0xc0 },
353*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PLL_ANA_MISC_CTL, 0x18 },
354*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PLL_ANA, 0x00 },
355*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_SW_RESET_CTL, 0x10, 10 },
356*51ef2be5SMarek Vasut 	/* Page 0xf means write to all of pages 1,2,3,4 */
357*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_VDELAY_LO(0xf), 0x14 },
358*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_MISC3(0xf), 0xe6 },
359*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_CLMD(0xf), 0x85 },
360*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(0xf), 0x11 },
361*51ef2be5SMarek Vasut 	{ ISL7998X_REG_PX_ACA_XFER_HIST_HOST(0xf), 0x00 },
362*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CLK_CTL_1, 0x1f },
363*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CLK_CTL_2, 0x43 },
364*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_CLK_CTL_3, 0x4f },
365*51ef2be5SMarek Vasut };
366*51ef2be5SMarek Vasut 
367*51ef2be5SMarek Vasut static const struct reg_sequence isl7998x_init_seq_2[] = {
368*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_SYNC_CTL, 0x10 },
369*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_VC_ASSIGNMENT, 0xe4 },
370*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_TYPE_CTL, 0x00 },
371*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL, 0x60 },
372*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_READ_START_CTL, 0x2b },
373*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_PSEUDO_FRM_FIELD_CTL, 0x02 },
374*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_ONE_FIELD_MODE_CTL, 0x00 },
375*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_INT_HW_TST_CTR, 0x62 },
376*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_BAR_PATTERN, 0x02 },
377*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_PCNT_PSFRM, 0x36 },
378*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL, 0x00 },
379*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_VBLANK_PSFRM, 0x6c },
380*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_CTL_2, 0x00 },
381*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_WCNT_1, 0x05 },
382*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_WCNT_2, 0xa0 },
383*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_1, 0x77 },
384*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_2, 0x17 },
385*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_3, 0x08 },
386*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_4, 0x38 },
387*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_5, 0x14 },
388*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_6, 0xf6 },
389*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_PARAMS_1, 0x00 },
390*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_SOT_PERIOD, 0x17 },
391*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_EOT_PERIOD, 0x0a },
392*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_PARAMS_2, 0x71 },
393*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_7, 0x7a },
394*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_8, 0x0f },
395*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_DPHY_TIMING_CTL_9, 0x8c },
396*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL, 0x08 },
397*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_FIFO_THRSH_CNT_1, 0x01 },
398*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_FIFO_THRSH_CNT_2, 0x0e },
399*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_1, 0x00 },
400*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TP_GEN_RND_SYNC_CTL_2, 0x00 },
401*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1, 0x03 },
402*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_2, 0xc0 },
403*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_H_LINE_CNT_1, 0x06 },
404*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_H_LINE_CNT_2, 0xb3 },
405*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_HIST_LINE_CNT_1, 0x00 },
406*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_HIST_LINE_CNT_2, 0xf1 },
407*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_LI_ENGINE_FIFO_CTL, 0x00 },
408*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P5_MIPI_ANA, 0x00 },
409*51ef2be5SMarek Vasut 	/*
410*51ef2be5SMarek Vasut 	 * Wait a bit after reset so that the chip can capture a frame
411*51ef2be5SMarek Vasut 	 * and update internal line counters.
412*51ef2be5SMarek Vasut 	 */
413*51ef2be5SMarek Vasut 	{ ISL7998X_REG_P0_SW_RESET_CTL, 0x00, 50 },
414*51ef2be5SMarek Vasut };
415*51ef2be5SMarek Vasut 
416*51ef2be5SMarek Vasut enum isl7998x_pads {
417*51ef2be5SMarek Vasut 	ISL7998X_PAD_OUT,
418*51ef2be5SMarek Vasut 	ISL7998X_PAD_VIN1,
419*51ef2be5SMarek Vasut 	ISL7998X_PAD_VIN2,
420*51ef2be5SMarek Vasut 	ISL7998X_PAD_VIN3,
421*51ef2be5SMarek Vasut 	ISL7998X_PAD_VIN4,
422*51ef2be5SMarek Vasut 	ISL7998X_NUM_PADS
423*51ef2be5SMarek Vasut };
424*51ef2be5SMarek Vasut 
425*51ef2be5SMarek Vasut struct isl7998x_datafmt {
426*51ef2be5SMarek Vasut 	u32			code;
427*51ef2be5SMarek Vasut 	enum v4l2_colorspace	colorspace;
428*51ef2be5SMarek Vasut };
429*51ef2be5SMarek Vasut 
430*51ef2be5SMarek Vasut static const struct isl7998x_datafmt isl7998x_colour_fmts[] = {
431*51ef2be5SMarek Vasut 	{ MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB },
432*51ef2be5SMarek Vasut };
433*51ef2be5SMarek Vasut 
434*51ef2be5SMarek Vasut /* Menu items for LINK_FREQ V4L2 control */
435*51ef2be5SMarek Vasut static const s64 link_freq_menu_items[] = {
436*51ef2be5SMarek Vasut 	/* 1 channel, 1 lane or 2 channels, 2 lanes */
437*51ef2be5SMarek Vasut 	108000000,
438*51ef2be5SMarek Vasut 	/* 2 channels, 1 lane or 4 channels, 2 lanes */
439*51ef2be5SMarek Vasut 	216000000,
440*51ef2be5SMarek Vasut 	/* 4 channels, 1 lane */
441*51ef2be5SMarek Vasut 	432000000,
442*51ef2be5SMarek Vasut };
443*51ef2be5SMarek Vasut 
444*51ef2be5SMarek Vasut /* Menu items for TEST_PATTERN V4L2 control */
445*51ef2be5SMarek Vasut static const char * const isl7998x_test_pattern_menu[] = {
446*51ef2be5SMarek Vasut 	"Disabled",
447*51ef2be5SMarek Vasut 	"Enabled",
448*51ef2be5SMarek Vasut };
449*51ef2be5SMarek Vasut 
450*51ef2be5SMarek Vasut static const char * const isl7998x_test_pattern_bars[] = {
451*51ef2be5SMarek Vasut 	"bbbbwb", "bbbwwb", "bbwbwb", "bbwwwb",
452*51ef2be5SMarek Vasut };
453*51ef2be5SMarek Vasut 
454*51ef2be5SMarek Vasut static const char * const isl7998x_test_pattern_colors[] = {
455*51ef2be5SMarek Vasut 	"Yellow", "Blue", "Green", "Pink",
456*51ef2be5SMarek Vasut };
457*51ef2be5SMarek Vasut 
458*51ef2be5SMarek Vasut struct isl7998x_mode {
459*51ef2be5SMarek Vasut 	unsigned int width;
460*51ef2be5SMarek Vasut 	unsigned int height;
461*51ef2be5SMarek Vasut 	enum v4l2_field field;
462*51ef2be5SMarek Vasut };
463*51ef2be5SMarek Vasut 
464*51ef2be5SMarek Vasut static const struct isl7998x_mode supported_modes[] = {
465*51ef2be5SMarek Vasut 	{
466*51ef2be5SMarek Vasut 		.width = 720,
467*51ef2be5SMarek Vasut 		.height = 576,
468*51ef2be5SMarek Vasut 		.field = V4L2_FIELD_SEQ_TB,
469*51ef2be5SMarek Vasut 	},
470*51ef2be5SMarek Vasut 	{
471*51ef2be5SMarek Vasut 		.width = 720,
472*51ef2be5SMarek Vasut 		.height = 480,
473*51ef2be5SMarek Vasut 		.field = V4L2_FIELD_SEQ_BT,
474*51ef2be5SMarek Vasut 	},
475*51ef2be5SMarek Vasut };
476*51ef2be5SMarek Vasut 
477*51ef2be5SMarek Vasut static const struct isl7998x_video_std {
478*51ef2be5SMarek Vasut 	const v4l2_std_id norm;
479*51ef2be5SMarek Vasut 	unsigned int id;
480*51ef2be5SMarek Vasut 	const struct isl7998x_mode *mode;
481*51ef2be5SMarek Vasut } isl7998x_std_res[] = {
482*51ef2be5SMarek Vasut 	{ V4L2_STD_NTSC_443,
483*51ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_443,
484*51ef2be5SMarek Vasut 	  &supported_modes[1] },
485*51ef2be5SMarek Vasut 	{ V4L2_STD_PAL_M,
486*51ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_M,
487*51ef2be5SMarek Vasut 	  &supported_modes[1] },
488*51ef2be5SMarek Vasut 	{ V4L2_STD_PAL_Nc,
489*51ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_CN,
490*51ef2be5SMarek Vasut 	  &supported_modes[0] },
491*51ef2be5SMarek Vasut 	{ V4L2_STD_PAL_N,
492*51ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL,
493*51ef2be5SMarek Vasut 	  &supported_modes[0] },
494*51ef2be5SMarek Vasut 	{ V4L2_STD_PAL_60,
495*51ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_60,
496*51ef2be5SMarek Vasut 	  &supported_modes[1] },
497*51ef2be5SMarek Vasut 	{ V4L2_STD_NTSC,
498*51ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_M,
499*51ef2be5SMarek Vasut 	  &supported_modes[1] },
500*51ef2be5SMarek Vasut 	{ V4L2_STD_PAL,
501*51ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL,
502*51ef2be5SMarek Vasut 	  &supported_modes[0] },
503*51ef2be5SMarek Vasut 	{ V4L2_STD_SECAM,
504*51ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_SECAM,
505*51ef2be5SMarek Vasut 	  &supported_modes[0] },
506*51ef2be5SMarek Vasut 	{ V4L2_STD_UNKNOWN,
507*51ef2be5SMarek Vasut 	  ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN,
508*51ef2be5SMarek Vasut 	  &supported_modes[1] },
509*51ef2be5SMarek Vasut };
510*51ef2be5SMarek Vasut 
511*51ef2be5SMarek Vasut struct isl7998x {
512*51ef2be5SMarek Vasut 	struct v4l2_subdev		subdev;
513*51ef2be5SMarek Vasut 	struct regmap			*regmap;
514*51ef2be5SMarek Vasut 	struct gpio_desc		*pd_gpio;
515*51ef2be5SMarek Vasut 	struct gpio_desc		*rstb_gpio;
516*51ef2be5SMarek Vasut 	unsigned int			nr_mipi_lanes;
517*51ef2be5SMarek Vasut 	u32				nr_inputs;
518*51ef2be5SMarek Vasut 
519*51ef2be5SMarek Vasut 	const struct isl7998x_datafmt	*fmt;
520*51ef2be5SMarek Vasut 	v4l2_std_id			norm;
521*51ef2be5SMarek Vasut 	struct media_pad		pads[ISL7998X_NUM_PADS];
522*51ef2be5SMarek Vasut 
523*51ef2be5SMarek Vasut 	int				enabled;
524*51ef2be5SMarek Vasut 
525*51ef2be5SMarek Vasut 	/* protect fmt, norm, enabled */
526*51ef2be5SMarek Vasut 	struct mutex			lock;
527*51ef2be5SMarek Vasut 
528*51ef2be5SMarek Vasut 	struct v4l2_ctrl_handler	ctrl_handler;
529*51ef2be5SMarek Vasut 	/* protect ctrl_handler */
530*51ef2be5SMarek Vasut 	struct mutex			ctrl_mutex;
531*51ef2be5SMarek Vasut 
532*51ef2be5SMarek Vasut 	/* V4L2 Controls */
533*51ef2be5SMarek Vasut 	struct v4l2_ctrl		*link_freq;
534*51ef2be5SMarek Vasut 	u8				test_pattern;
535*51ef2be5SMarek Vasut 	u8				test_pattern_bars;
536*51ef2be5SMarek Vasut 	u8				test_pattern_chans;
537*51ef2be5SMarek Vasut 	u8				test_pattern_color;
538*51ef2be5SMarek Vasut };
539*51ef2be5SMarek Vasut 
540*51ef2be5SMarek Vasut static struct isl7998x *sd_to_isl7998x(struct v4l2_subdev *sd)
541*51ef2be5SMarek Vasut {
542*51ef2be5SMarek Vasut 	return container_of(sd, struct isl7998x, subdev);
543*51ef2be5SMarek Vasut }
544*51ef2be5SMarek Vasut 
545*51ef2be5SMarek Vasut static struct isl7998x *i2c_to_isl7998x(const struct i2c_client *client)
546*51ef2be5SMarek Vasut {
547*51ef2be5SMarek Vasut 	return sd_to_isl7998x(i2c_get_clientdata(client));
548*51ef2be5SMarek Vasut }
549*51ef2be5SMarek Vasut 
550*51ef2be5SMarek Vasut static unsigned int isl7998x_norm_to_val(v4l2_std_id norm)
551*51ef2be5SMarek Vasut {
552*51ef2be5SMarek Vasut 	unsigned int i;
553*51ef2be5SMarek Vasut 
554*51ef2be5SMarek Vasut 	for (i = 0; i < ARRAY_SIZE(isl7998x_std_res); i++)
555*51ef2be5SMarek Vasut 		if (isl7998x_std_res[i].norm & norm)
556*51ef2be5SMarek Vasut 			break;
557*51ef2be5SMarek Vasut 	if (i == ARRAY_SIZE(isl7998x_std_res))
558*51ef2be5SMarek Vasut 		return ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN;
559*51ef2be5SMarek Vasut 
560*51ef2be5SMarek Vasut 	return isl7998x_std_res[i].id;
561*51ef2be5SMarek Vasut }
562*51ef2be5SMarek Vasut 
563*51ef2be5SMarek Vasut static const struct isl7998x_mode *isl7998x_norm_to_mode(v4l2_std_id norm)
564*51ef2be5SMarek Vasut {
565*51ef2be5SMarek Vasut 	unsigned int i;
566*51ef2be5SMarek Vasut 
567*51ef2be5SMarek Vasut 	for (i = 0; i < ARRAY_SIZE(isl7998x_std_res); i++)
568*51ef2be5SMarek Vasut 		if (isl7998x_std_res[i].norm & norm)
569*51ef2be5SMarek Vasut 			break;
570*51ef2be5SMarek Vasut 	/* Use NTSC default resolution during standard detection */
571*51ef2be5SMarek Vasut 	if (i == ARRAY_SIZE(isl7998x_std_res))
572*51ef2be5SMarek Vasut 		return &supported_modes[1];
573*51ef2be5SMarek Vasut 
574*51ef2be5SMarek Vasut 	return isl7998x_std_res[i].mode;
575*51ef2be5SMarek Vasut }
576*51ef2be5SMarek Vasut 
577*51ef2be5SMarek Vasut static int isl7998x_get_nr_inputs(struct device_node *of_node)
578*51ef2be5SMarek Vasut {
579*51ef2be5SMarek Vasut 	struct device_node *port;
580*51ef2be5SMarek Vasut 	unsigned int inputs = 0;
581*51ef2be5SMarek Vasut 	unsigned int i;
582*51ef2be5SMarek Vasut 
583*51ef2be5SMarek Vasut 	if (of_graph_get_endpoint_count(of_node) > ISL7998X_NUM_PADS)
584*51ef2be5SMarek Vasut 		return -EINVAL;
585*51ef2be5SMarek Vasut 
586*51ef2be5SMarek Vasut 	/*
587*51ef2be5SMarek Vasut 	 * The driver does not provide means to remap the input ports. It
588*51ef2be5SMarek Vasut 	 * always configures input ports to start from VID1. Ensure that the
589*51ef2be5SMarek Vasut 	 * device tree is correct.
590*51ef2be5SMarek Vasut 	 */
591*51ef2be5SMarek Vasut 	for (i = ISL7998X_PAD_VIN1; i <= ISL7998X_PAD_VIN4; i++) {
592*51ef2be5SMarek Vasut 		port = of_graph_get_port_by_id(of_node, i);
593*51ef2be5SMarek Vasut 		if (!port)
594*51ef2be5SMarek Vasut 			continue;
595*51ef2be5SMarek Vasut 
596*51ef2be5SMarek Vasut 		inputs |= BIT(i);
597*51ef2be5SMarek Vasut 		of_node_put(port);
598*51ef2be5SMarek Vasut 	}
599*51ef2be5SMarek Vasut 
600*51ef2be5SMarek Vasut 	switch (inputs) {
601*51ef2be5SMarek Vasut 	case BIT(ISL7998X_PAD_VIN1):
602*51ef2be5SMarek Vasut 		return 1;
603*51ef2be5SMarek Vasut 	case BIT(ISL7998X_PAD_VIN1) | BIT(ISL7998X_PAD_VIN2):
604*51ef2be5SMarek Vasut 		return 2;
605*51ef2be5SMarek Vasut 	case BIT(ISL7998X_PAD_VIN1) | BIT(ISL7998X_PAD_VIN2) |
606*51ef2be5SMarek Vasut 	     BIT(ISL7998X_PAD_VIN3) | BIT(ISL7998X_PAD_VIN4):
607*51ef2be5SMarek Vasut 		return 4;
608*51ef2be5SMarek Vasut 	default:
609*51ef2be5SMarek Vasut 		return -EINVAL;
610*51ef2be5SMarek Vasut 	}
611*51ef2be5SMarek Vasut }
612*51ef2be5SMarek Vasut 
613*51ef2be5SMarek Vasut static int isl7998x_wait_power_on(struct isl7998x *isl7998x)
614*51ef2be5SMarek Vasut {
615*51ef2be5SMarek Vasut 	struct device *dev = isl7998x->subdev.dev;
616*51ef2be5SMarek Vasut 	u32 chip_id;
617*51ef2be5SMarek Vasut 	int ret;
618*51ef2be5SMarek Vasut 	int err;
619*51ef2be5SMarek Vasut 
620*51ef2be5SMarek Vasut 	ret = read_poll_timeout(regmap_read, err, !err, 2000, 20000, false,
621*51ef2be5SMarek Vasut 				isl7998x->regmap,
622*51ef2be5SMarek Vasut 				ISL7998X_REG_P0_PRODUCT_ID_CODE, &chip_id);
623*51ef2be5SMarek Vasut 	if (ret) {
624*51ef2be5SMarek Vasut 		dev_err(dev, "timeout while waiting for ISL7998X\n");
625*51ef2be5SMarek Vasut 		return ret;
626*51ef2be5SMarek Vasut 	}
627*51ef2be5SMarek Vasut 
628*51ef2be5SMarek Vasut 	dev_dbg(dev, "Found ISL799%x\n", chip_id);
629*51ef2be5SMarek Vasut 
630*51ef2be5SMarek Vasut 	return ret;
631*51ef2be5SMarek Vasut }
632*51ef2be5SMarek Vasut 
633*51ef2be5SMarek Vasut static int isl7998x_set_standard(struct isl7998x *isl7998x, v4l2_std_id norm)
634*51ef2be5SMarek Vasut {
635*51ef2be5SMarek Vasut 	const struct isl7998x_mode *mode = isl7998x_norm_to_mode(norm);
636*51ef2be5SMarek Vasut 	unsigned int val = isl7998x_norm_to_val(norm);
637*51ef2be5SMarek Vasut 	unsigned int width = mode->width;
638*51ef2be5SMarek Vasut 	unsigned int i;
639*51ef2be5SMarek Vasut 	int ret;
640*51ef2be5SMarek Vasut 
641*51ef2be5SMarek Vasut 	for (i = 0; i < ISL7998X_INPUTS; i++) {
642*51ef2be5SMarek Vasut 		ret = regmap_write_bits(isl7998x->regmap,
643*51ef2be5SMarek Vasut 					ISL7998X_REG_PX_DEC_SDT(i + 1),
644*51ef2be5SMarek Vasut 					ISL7998X_REG_PX_DEC_SDT_STANDARD,
645*51ef2be5SMarek Vasut 					val);
646*51ef2be5SMarek Vasut 		if (ret)
647*51ef2be5SMarek Vasut 			return ret;
648*51ef2be5SMarek Vasut 	}
649*51ef2be5SMarek Vasut 
650*51ef2be5SMarek Vasut 	ret = regmap_write(isl7998x->regmap,
651*51ef2be5SMarek Vasut 			   ISL7998X_REG_P5_LI_ENGINE_LINE_CTL,
652*51ef2be5SMarek Vasut 			   0x20 | ((width >> 7) & 0x1f));
653*51ef2be5SMarek Vasut 	if (ret)
654*51ef2be5SMarek Vasut 		return ret;
655*51ef2be5SMarek Vasut 
656*51ef2be5SMarek Vasut 	ret = regmap_write(isl7998x->regmap,
657*51ef2be5SMarek Vasut 			   ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH,
658*51ef2be5SMarek Vasut 			   (width << 1) & 0xff);
659*51ef2be5SMarek Vasut 	if (ret)
660*51ef2be5SMarek Vasut 		return ret;
661*51ef2be5SMarek Vasut 
662*51ef2be5SMarek Vasut 	return 0;
663*51ef2be5SMarek Vasut }
664*51ef2be5SMarek Vasut 
665*51ef2be5SMarek Vasut static int isl7998x_init(struct isl7998x *isl7998x)
666*51ef2be5SMarek Vasut {
667*51ef2be5SMarek Vasut 	const unsigned int lanes = isl7998x->nr_mipi_lanes;
668*51ef2be5SMarek Vasut 	const u32 isl7998x_video_in_chan_map[] = { 0x00, 0x11, 0x02, 0x02 };
669*51ef2be5SMarek Vasut 	const struct reg_sequence isl7998x_init_seq_custom[] = {
670*51ef2be5SMarek Vasut 		{ ISL7998X_REG_P0_VIDEO_IN_CHAN_CTL,
671*51ef2be5SMarek Vasut 		  isl7998x_video_in_chan_map[isl7998x->nr_inputs - 1] },
672*51ef2be5SMarek Vasut 		{ ISL7998X_REG_P0_CLK_CTL_4,
673*51ef2be5SMarek Vasut 		  (lanes == 1) ? 0x40 : 0x41 },
674*51ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_LI_ENGINE_CTL,
675*51ef2be5SMarek Vasut 		  (lanes == 1) ? 0x01 : 0x02 },
676*51ef2be5SMarek Vasut 	};
677*51ef2be5SMarek Vasut 	struct device *dev = isl7998x->subdev.dev;
678*51ef2be5SMarek Vasut 	struct regmap *regmap = isl7998x->regmap;
679*51ef2be5SMarek Vasut 	int ret;
680*51ef2be5SMarek Vasut 
681*51ef2be5SMarek Vasut 	dev_dbg(dev, "configuring %d lanes for %d inputs (norm %s)\n",
682*51ef2be5SMarek Vasut 		isl7998x->nr_mipi_lanes, isl7998x->nr_inputs,
683*51ef2be5SMarek Vasut 		v4l2_norm_to_name(isl7998x->norm));
684*51ef2be5SMarek Vasut 
685*51ef2be5SMarek Vasut 	ret = regmap_register_patch(regmap, isl7998x_init_seq_1,
686*51ef2be5SMarek Vasut 				    ARRAY_SIZE(isl7998x_init_seq_1));
687*51ef2be5SMarek Vasut 	if (ret)
688*51ef2be5SMarek Vasut 		return ret;
689*51ef2be5SMarek Vasut 
690*51ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
691*51ef2be5SMarek Vasut 	ret = isl7998x_set_standard(isl7998x, isl7998x->norm);
692*51ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
693*51ef2be5SMarek Vasut 	if (ret)
694*51ef2be5SMarek Vasut 		return ret;
695*51ef2be5SMarek Vasut 
696*51ef2be5SMarek Vasut 	ret = regmap_register_patch(regmap, isl7998x_init_seq_custom,
697*51ef2be5SMarek Vasut 				    ARRAY_SIZE(isl7998x_init_seq_custom));
698*51ef2be5SMarek Vasut 	if (ret)
699*51ef2be5SMarek Vasut 		return ret;
700*51ef2be5SMarek Vasut 
701*51ef2be5SMarek Vasut 	return regmap_register_patch(regmap, isl7998x_init_seq_2,
702*51ef2be5SMarek Vasut 				     ARRAY_SIZE(isl7998x_init_seq_2));
703*51ef2be5SMarek Vasut }
704*51ef2be5SMarek Vasut 
705*51ef2be5SMarek Vasut static int isl7998x_set_test_pattern(struct isl7998x *isl7998x)
706*51ef2be5SMarek Vasut {
707*51ef2be5SMarek Vasut 	const struct reg_sequence isl7998x_init_seq_tpg_off[] = {
708*51ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL, 0 },
709*51ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_LI_ENGINE_CTL_2, 0 }
710*51ef2be5SMarek Vasut 	};
711*51ef2be5SMarek Vasut 	const struct reg_sequence isl7998x_init_seq_tpg_on[] = {
712*51ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_TP_GEN_BAR_PATTERN,
713*51ef2be5SMarek Vasut 		  isl7998x->test_pattern_bars << 6 },
714*51ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_LI_ENGINE_CTL_2,
715*51ef2be5SMarek Vasut 		  isl7998x->norm & V4L2_STD_PAL ? BIT(2) : 0 },
716*51ef2be5SMarek Vasut 		{ ISL7998X_REG_P5_LI_ENGINE_TP_GEN_CTL,
717*51ef2be5SMarek Vasut 		  (isl7998x->test_pattern_chans << 4) |
718*51ef2be5SMarek Vasut 		  (isl7998x->test_pattern_color << 2) }
719*51ef2be5SMarek Vasut 	};
720*51ef2be5SMarek Vasut 	struct device *dev = isl7998x->subdev.dev;
721*51ef2be5SMarek Vasut 	struct regmap *regmap = isl7998x->regmap;
722*51ef2be5SMarek Vasut 	int ret;
723*51ef2be5SMarek Vasut 
724*51ef2be5SMarek Vasut 	if (pm_runtime_get_if_in_use(dev) <= 0)
725*51ef2be5SMarek Vasut 		return 0;
726*51ef2be5SMarek Vasut 
727*51ef2be5SMarek Vasut 	if (isl7998x->test_pattern != 0) {
728*51ef2be5SMarek Vasut 		dev_dbg(dev, "enabling test pattern: channels 0x%x, %s, %s\n",
729*51ef2be5SMarek Vasut 			isl7998x->test_pattern_chans,
730*51ef2be5SMarek Vasut 			isl7998x_test_pattern_bars[isl7998x->test_pattern_bars],
731*51ef2be5SMarek Vasut 			isl7998x_test_pattern_colors[isl7998x->test_pattern_color]);
732*51ef2be5SMarek Vasut 		ret = regmap_register_patch(regmap, isl7998x_init_seq_tpg_on,
733*51ef2be5SMarek Vasut 					    ARRAY_SIZE(isl7998x_init_seq_tpg_on));
734*51ef2be5SMarek Vasut 	} else {
735*51ef2be5SMarek Vasut 		ret = regmap_register_patch(regmap, isl7998x_init_seq_tpg_off,
736*51ef2be5SMarek Vasut 					    ARRAY_SIZE(isl7998x_init_seq_tpg_off));
737*51ef2be5SMarek Vasut 	}
738*51ef2be5SMarek Vasut 
739*51ef2be5SMarek Vasut 	pm_runtime_put(dev);
740*51ef2be5SMarek Vasut 
741*51ef2be5SMarek Vasut 	return ret;
742*51ef2be5SMarek Vasut }
743*51ef2be5SMarek Vasut 
744*51ef2be5SMarek Vasut #ifdef CONFIG_VIDEO_ADV_DEBUG
745*51ef2be5SMarek Vasut static int isl7998x_g_register(struct v4l2_subdev *sd,
746*51ef2be5SMarek Vasut 			       struct v4l2_dbg_register *reg)
747*51ef2be5SMarek Vasut {
748*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
749*51ef2be5SMarek Vasut 	int ret;
750*51ef2be5SMarek Vasut 	u32 val;
751*51ef2be5SMarek Vasut 
752*51ef2be5SMarek Vasut 	ret = regmap_read(isl7998x->regmap, reg->reg, &val);
753*51ef2be5SMarek Vasut 	if (ret)
754*51ef2be5SMarek Vasut 		return ret;
755*51ef2be5SMarek Vasut 
756*51ef2be5SMarek Vasut 	reg->size = 1;
757*51ef2be5SMarek Vasut 	reg->val = val;
758*51ef2be5SMarek Vasut 
759*51ef2be5SMarek Vasut 	return 0;
760*51ef2be5SMarek Vasut }
761*51ef2be5SMarek Vasut 
762*51ef2be5SMarek Vasut static int isl7998x_s_register(struct v4l2_subdev *sd,
763*51ef2be5SMarek Vasut 			       const struct v4l2_dbg_register *reg)
764*51ef2be5SMarek Vasut {
765*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
766*51ef2be5SMarek Vasut 
767*51ef2be5SMarek Vasut 	return regmap_write(isl7998x->regmap, reg->reg, reg->val);
768*51ef2be5SMarek Vasut }
769*51ef2be5SMarek Vasut #endif
770*51ef2be5SMarek Vasut 
771*51ef2be5SMarek Vasut static int isl7998x_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
772*51ef2be5SMarek Vasut {
773*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
774*51ef2be5SMarek Vasut 
775*51ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
776*51ef2be5SMarek Vasut 	*norm = isl7998x->norm;
777*51ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
778*51ef2be5SMarek Vasut 
779*51ef2be5SMarek Vasut 	return 0;
780*51ef2be5SMarek Vasut }
781*51ef2be5SMarek Vasut 
782*51ef2be5SMarek Vasut static int isl7998x_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
783*51ef2be5SMarek Vasut {
784*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
785*51ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
786*51ef2be5SMarek Vasut 	struct device *dev = &client->dev;
787*51ef2be5SMarek Vasut 	int ret = 0;
788*51ef2be5SMarek Vasut 
789*51ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
790*51ef2be5SMarek Vasut 	if (isl7998x->enabled) {
791*51ef2be5SMarek Vasut 		ret = -EBUSY;
792*51ef2be5SMarek Vasut 		mutex_unlock(&isl7998x->lock);
793*51ef2be5SMarek Vasut 		return ret;
794*51ef2be5SMarek Vasut 	}
795*51ef2be5SMarek Vasut 	isl7998x->norm = norm;
796*51ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
797*51ef2be5SMarek Vasut 
798*51ef2be5SMarek Vasut 	if (pm_runtime_get_if_in_use(dev) <= 0)
799*51ef2be5SMarek Vasut 		return ret;
800*51ef2be5SMarek Vasut 
801*51ef2be5SMarek Vasut 	ret = isl7998x_set_standard(isl7998x, norm);
802*51ef2be5SMarek Vasut 
803*51ef2be5SMarek Vasut 	pm_runtime_put(dev);
804*51ef2be5SMarek Vasut 
805*51ef2be5SMarek Vasut 	return ret;
806*51ef2be5SMarek Vasut }
807*51ef2be5SMarek Vasut 
808*51ef2be5SMarek Vasut static int isl7998x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
809*51ef2be5SMarek Vasut {
810*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
811*51ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
812*51ef2be5SMarek Vasut 	struct device *dev = &client->dev;
813*51ef2be5SMarek Vasut 	unsigned int std_id[ISL7998X_INPUTS];
814*51ef2be5SMarek Vasut 	unsigned int i;
815*51ef2be5SMarek Vasut 	int ret;
816*51ef2be5SMarek Vasut 	u32 reg;
817*51ef2be5SMarek Vasut 
818*51ef2be5SMarek Vasut 	ret = pm_runtime_resume_and_get(dev);
819*51ef2be5SMarek Vasut 	if (ret)
820*51ef2be5SMarek Vasut 		return ret;
821*51ef2be5SMarek Vasut 
822*51ef2be5SMarek Vasut 	dev_dbg(dev, "starting video standard detection\n");
823*51ef2be5SMarek Vasut 
824*51ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
825*51ef2be5SMarek Vasut 	if (isl7998x->enabled) {
826*51ef2be5SMarek Vasut 		ret = -EBUSY;
827*51ef2be5SMarek Vasut 		goto out_unlock;
828*51ef2be5SMarek Vasut 	}
829*51ef2be5SMarek Vasut 
830*51ef2be5SMarek Vasut 	ret = isl7998x_set_standard(isl7998x, V4L2_STD_UNKNOWN);
831*51ef2be5SMarek Vasut 	if (ret)
832*51ef2be5SMarek Vasut 		goto out_unlock;
833*51ef2be5SMarek Vasut 
834*51ef2be5SMarek Vasut 	for (i = 0; i < ISL7998X_INPUTS; i++) {
835*51ef2be5SMarek Vasut 		ret = regmap_write(isl7998x->regmap,
836*51ef2be5SMarek Vasut 				   ISL7998X_REG_PX_DEC_SDTR(i + 1),
837*51ef2be5SMarek Vasut 				   ISL7998X_REG_PX_DEC_SDTR_ATSTART);
838*51ef2be5SMarek Vasut 		if (ret)
839*51ef2be5SMarek Vasut 			goto out_reset_std;
840*51ef2be5SMarek Vasut 	}
841*51ef2be5SMarek Vasut 
842*51ef2be5SMarek Vasut 	for (i = 0; i < ISL7998X_INPUTS; i++) {
843*51ef2be5SMarek Vasut 		ret = regmap_read_poll_timeout(isl7998x->regmap,
844*51ef2be5SMarek Vasut 					       ISL7998X_REG_PX_DEC_SDT(i + 1),
845*51ef2be5SMarek Vasut 					       reg,
846*51ef2be5SMarek Vasut 					       !(reg & ISL7998X_REG_PX_DEC_SDT_DET),
847*51ef2be5SMarek Vasut 					       2000, 500 * USEC_PER_MSEC);
848*51ef2be5SMarek Vasut 		if (ret)
849*51ef2be5SMarek Vasut 			goto out_reset_std;
850*51ef2be5SMarek Vasut 		std_id[i] = FIELD_GET(ISL7998X_REG_PX_DEC_SDT_NOW, reg);
851*51ef2be5SMarek Vasut 	}
852*51ef2be5SMarek Vasut 
853*51ef2be5SMarek Vasut 	/*
854*51ef2be5SMarek Vasut 	 * According to Renesas FAE, all input cameras must have the
855*51ef2be5SMarek Vasut 	 * same standard on this chip.
856*51ef2be5SMarek Vasut 	 */
857*51ef2be5SMarek Vasut 	for (i = 0; i < isl7998x->nr_inputs; i++) {
858*51ef2be5SMarek Vasut 		dev_dbg(dev, "input %d: detected %s\n",
859*51ef2be5SMarek Vasut 			i, v4l2_norm_to_name(isl7998x_std_res[std_id[i]].norm));
860*51ef2be5SMarek Vasut 		if (std_id[0] != std_id[i])
861*51ef2be5SMarek Vasut 			dev_warn(dev,
862*51ef2be5SMarek Vasut 				 "incompatible standards: %s on input %d (expected %s)\n",
863*51ef2be5SMarek Vasut 				 v4l2_norm_to_name(isl7998x_std_res[std_id[i]].norm), i,
864*51ef2be5SMarek Vasut 				 v4l2_norm_to_name(isl7998x_std_res[std_id[0]].norm));
865*51ef2be5SMarek Vasut 	}
866*51ef2be5SMarek Vasut 
867*51ef2be5SMarek Vasut 	*std = isl7998x_std_res[std_id[0]].norm;
868*51ef2be5SMarek Vasut 
869*51ef2be5SMarek Vasut out_reset_std:
870*51ef2be5SMarek Vasut 	isl7998x_set_standard(isl7998x, isl7998x->norm);
871*51ef2be5SMarek Vasut out_unlock:
872*51ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
873*51ef2be5SMarek Vasut 	pm_runtime_put(dev);
874*51ef2be5SMarek Vasut 
875*51ef2be5SMarek Vasut 	return ret;
876*51ef2be5SMarek Vasut }
877*51ef2be5SMarek Vasut 
878*51ef2be5SMarek Vasut static int isl7998x_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *std)
879*51ef2be5SMarek Vasut {
880*51ef2be5SMarek Vasut 	*std = V4L2_STD_ALL;
881*51ef2be5SMarek Vasut 
882*51ef2be5SMarek Vasut 	return 0;
883*51ef2be5SMarek Vasut }
884*51ef2be5SMarek Vasut 
885*51ef2be5SMarek Vasut static int isl7998x_g_input_status(struct v4l2_subdev *sd, u32 *status)
886*51ef2be5SMarek Vasut {
887*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
888*51ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
889*51ef2be5SMarek Vasut 	struct device *dev = &client->dev;
890*51ef2be5SMarek Vasut 	unsigned int i;
891*51ef2be5SMarek Vasut 	int ret = 0;
892*51ef2be5SMarek Vasut 	u32 reg;
893*51ef2be5SMarek Vasut 
894*51ef2be5SMarek Vasut 	if (!pm_runtime_active(dev)) {
895*51ef2be5SMarek Vasut 		*status |= V4L2_IN_ST_NO_POWER;
896*51ef2be5SMarek Vasut 		return 0;
897*51ef2be5SMarek Vasut 	}
898*51ef2be5SMarek Vasut 
899*51ef2be5SMarek Vasut 	for (i = 0; i < isl7998x->nr_inputs; i++) {
900*51ef2be5SMarek Vasut 		ret = regmap_read(isl7998x->regmap,
901*51ef2be5SMarek Vasut 				  ISL7998X_REG_PX_DEC_STATUS_1(i + 1), &reg);
902*51ef2be5SMarek Vasut 		if (!ret) {
903*51ef2be5SMarek Vasut 			if (reg & ISL7998X_REG_PX_DEC_STATUS_1_VDLOSS)
904*51ef2be5SMarek Vasut 				*status |= V4L2_IN_ST_NO_SIGNAL;
905*51ef2be5SMarek Vasut 			if (!(reg & ISL7998X_REG_PX_DEC_STATUS_1_HLOCK))
906*51ef2be5SMarek Vasut 				*status |= V4L2_IN_ST_NO_H_LOCK;
907*51ef2be5SMarek Vasut 			if (!(reg & ISL7998X_REG_PX_DEC_STATUS_1_VLOCK))
908*51ef2be5SMarek Vasut 				*status |= V4L2_IN_ST_NO_V_LOCK;
909*51ef2be5SMarek Vasut 		}
910*51ef2be5SMarek Vasut 	}
911*51ef2be5SMarek Vasut 
912*51ef2be5SMarek Vasut 	return ret;
913*51ef2be5SMarek Vasut }
914*51ef2be5SMarek Vasut 
915*51ef2be5SMarek Vasut static int isl7998x_s_stream(struct v4l2_subdev *sd, int enable)
916*51ef2be5SMarek Vasut {
917*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
918*51ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
919*51ef2be5SMarek Vasut 	struct device *dev = &client->dev;
920*51ef2be5SMarek Vasut 	int ret = 0;
921*51ef2be5SMarek Vasut 	u32 reg;
922*51ef2be5SMarek Vasut 
923*51ef2be5SMarek Vasut 	dev_dbg(dev, "stream %s\n", enable ? "ON" : "OFF");
924*51ef2be5SMarek Vasut 
925*51ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
926*51ef2be5SMarek Vasut 	if (isl7998x->enabled == enable)
927*51ef2be5SMarek Vasut 		goto out;
928*51ef2be5SMarek Vasut 	isl7998x->enabled = enable;
929*51ef2be5SMarek Vasut 
930*51ef2be5SMarek Vasut 	if (enable) {
931*51ef2be5SMarek Vasut 		ret = isl7998x_set_test_pattern(isl7998x);
932*51ef2be5SMarek Vasut 		if (ret)
933*51ef2be5SMarek Vasut 			goto out;
934*51ef2be5SMarek Vasut 	}
935*51ef2be5SMarek Vasut 
936*51ef2be5SMarek Vasut 	regmap_read(isl7998x->regmap,
937*51ef2be5SMarek Vasut 		    ISL7998X_REG_P5_LI_ENGINE_CTL, &reg);
938*51ef2be5SMarek Vasut 	if (enable)
939*51ef2be5SMarek Vasut 		reg &= ~BIT(7);
940*51ef2be5SMarek Vasut 	else
941*51ef2be5SMarek Vasut 		reg |= BIT(7);
942*51ef2be5SMarek Vasut 	ret = regmap_write(isl7998x->regmap,
943*51ef2be5SMarek Vasut 			   ISL7998X_REG_P5_LI_ENGINE_CTL, reg);
944*51ef2be5SMarek Vasut 
945*51ef2be5SMarek Vasut out:
946*51ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
947*51ef2be5SMarek Vasut 
948*51ef2be5SMarek Vasut 	return ret;
949*51ef2be5SMarek Vasut }
950*51ef2be5SMarek Vasut 
951*51ef2be5SMarek Vasut static int isl7998x_pre_streamon(struct v4l2_subdev *sd, u32 flags)
952*51ef2be5SMarek Vasut {
953*51ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
954*51ef2be5SMarek Vasut 	struct device *dev = &client->dev;
955*51ef2be5SMarek Vasut 
956*51ef2be5SMarek Vasut 	return pm_runtime_resume_and_get(dev);
957*51ef2be5SMarek Vasut }
958*51ef2be5SMarek Vasut 
959*51ef2be5SMarek Vasut static int isl7998x_post_streamoff(struct v4l2_subdev *sd)
960*51ef2be5SMarek Vasut {
961*51ef2be5SMarek Vasut 	struct i2c_client *client = v4l2_get_subdevdata(sd);
962*51ef2be5SMarek Vasut 	struct device *dev = &client->dev;
963*51ef2be5SMarek Vasut 
964*51ef2be5SMarek Vasut 	pm_runtime_put(dev);
965*51ef2be5SMarek Vasut 
966*51ef2be5SMarek Vasut 	return 0;
967*51ef2be5SMarek Vasut }
968*51ef2be5SMarek Vasut 
969*51ef2be5SMarek Vasut static int isl7998x_enum_mbus_code(struct v4l2_subdev *sd,
970*51ef2be5SMarek Vasut 				   struct v4l2_subdev_state *sd_state,
971*51ef2be5SMarek Vasut 				   struct v4l2_subdev_mbus_code_enum *code)
972*51ef2be5SMarek Vasut {
973*51ef2be5SMarek Vasut 	if (code->index >= ARRAY_SIZE(isl7998x_colour_fmts))
974*51ef2be5SMarek Vasut 		return -EINVAL;
975*51ef2be5SMarek Vasut 
976*51ef2be5SMarek Vasut 	code->code = isl7998x_colour_fmts[code->index].code;
977*51ef2be5SMarek Vasut 
978*51ef2be5SMarek Vasut 	return 0;
979*51ef2be5SMarek Vasut }
980*51ef2be5SMarek Vasut 
981*51ef2be5SMarek Vasut static int isl7998x_enum_frame_size(struct v4l2_subdev *sd,
982*51ef2be5SMarek Vasut 				    struct v4l2_subdev_state *sd_state,
983*51ef2be5SMarek Vasut 				    struct v4l2_subdev_frame_size_enum *fse)
984*51ef2be5SMarek Vasut {
985*51ef2be5SMarek Vasut 	if (fse->index >= ARRAY_SIZE(supported_modes))
986*51ef2be5SMarek Vasut 		return -EINVAL;
987*51ef2be5SMarek Vasut 
988*51ef2be5SMarek Vasut 	if (fse->code != isl7998x_colour_fmts[0].code)
989*51ef2be5SMarek Vasut 		return -EINVAL;
990*51ef2be5SMarek Vasut 
991*51ef2be5SMarek Vasut 	fse->min_width = supported_modes[fse->index].width;
992*51ef2be5SMarek Vasut 	fse->max_width = fse->min_width;
993*51ef2be5SMarek Vasut 	fse->min_height = supported_modes[fse->index].height;
994*51ef2be5SMarek Vasut 	fse->max_height = fse->min_height;
995*51ef2be5SMarek Vasut 
996*51ef2be5SMarek Vasut 	return 0;
997*51ef2be5SMarek Vasut }
998*51ef2be5SMarek Vasut 
999*51ef2be5SMarek Vasut static int isl7998x_get_fmt(struct v4l2_subdev *sd,
1000*51ef2be5SMarek Vasut 			    struct v4l2_subdev_state *sd_state,
1001*51ef2be5SMarek Vasut 			    struct v4l2_subdev_format *format)
1002*51ef2be5SMarek Vasut {
1003*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
1004*51ef2be5SMarek Vasut 	struct v4l2_mbus_framefmt *mf = &format->format;
1005*51ef2be5SMarek Vasut 	const struct isl7998x_mode *mode;
1006*51ef2be5SMarek Vasut 
1007*51ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
1008*51ef2be5SMarek Vasut 
1009*51ef2be5SMarek Vasut 	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
1010*51ef2be5SMarek Vasut 		format->format = *v4l2_subdev_get_try_format(sd, sd_state,
1011*51ef2be5SMarek Vasut 							     format->pad);
1012*51ef2be5SMarek Vasut 		goto out;
1013*51ef2be5SMarek Vasut 	}
1014*51ef2be5SMarek Vasut 
1015*51ef2be5SMarek Vasut 	mode = isl7998x_norm_to_mode(isl7998x->norm);
1016*51ef2be5SMarek Vasut 
1017*51ef2be5SMarek Vasut 	mf->width	= mode->width;
1018*51ef2be5SMarek Vasut 	mf->height	= mode->height;
1019*51ef2be5SMarek Vasut 	mf->code	= isl7998x->fmt->code;
1020*51ef2be5SMarek Vasut 	mf->field	= mode->field;
1021*51ef2be5SMarek Vasut 	mf->colorspace	= 0;
1022*51ef2be5SMarek Vasut 
1023*51ef2be5SMarek Vasut out:
1024*51ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
1025*51ef2be5SMarek Vasut 
1026*51ef2be5SMarek Vasut 	return 0;
1027*51ef2be5SMarek Vasut }
1028*51ef2be5SMarek Vasut 
1029*51ef2be5SMarek Vasut static int isl7998x_set_fmt(struct v4l2_subdev *sd,
1030*51ef2be5SMarek Vasut 			    struct v4l2_subdev_state *sd_state,
1031*51ef2be5SMarek Vasut 			    struct v4l2_subdev_format *format)
1032*51ef2be5SMarek Vasut {
1033*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
1034*51ef2be5SMarek Vasut 	struct v4l2_mbus_framefmt *mf = &format->format;
1035*51ef2be5SMarek Vasut 	const struct isl7998x_mode *mode;
1036*51ef2be5SMarek Vasut 
1037*51ef2be5SMarek Vasut 	mutex_lock(&isl7998x->lock);
1038*51ef2be5SMarek Vasut 
1039*51ef2be5SMarek Vasut 	mode = isl7998x_norm_to_mode(isl7998x->norm);
1040*51ef2be5SMarek Vasut 
1041*51ef2be5SMarek Vasut 	mf->width = mode->width;
1042*51ef2be5SMarek Vasut 	mf->height = mode->height;
1043*51ef2be5SMarek Vasut 	mf->code = isl7998x->fmt->code;
1044*51ef2be5SMarek Vasut 	mf->field = mode->field;
1045*51ef2be5SMarek Vasut 
1046*51ef2be5SMarek Vasut 	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
1047*51ef2be5SMarek Vasut 		*v4l2_subdev_get_try_format(sd, sd_state, format->pad) = format->format;
1048*51ef2be5SMarek Vasut 
1049*51ef2be5SMarek Vasut 	mutex_unlock(&isl7998x->lock);
1050*51ef2be5SMarek Vasut 
1051*51ef2be5SMarek Vasut 	return 0;
1052*51ef2be5SMarek Vasut }
1053*51ef2be5SMarek Vasut 
1054*51ef2be5SMarek Vasut static int isl7998x_set_ctrl(struct v4l2_ctrl *ctrl)
1055*51ef2be5SMarek Vasut {
1056*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = container_of(ctrl->handler,
1057*51ef2be5SMarek Vasut 						 struct isl7998x, ctrl_handler);
1058*51ef2be5SMarek Vasut 	int ret = 0;
1059*51ef2be5SMarek Vasut 
1060*51ef2be5SMarek Vasut 	switch (ctrl->id) {
1061*51ef2be5SMarek Vasut 	case V4L2_CID_TEST_PATTERN_BARS:
1062*51ef2be5SMarek Vasut 		mutex_lock(&isl7998x->lock);
1063*51ef2be5SMarek Vasut 		isl7998x->test_pattern_bars = ctrl->val & 0x3;
1064*51ef2be5SMarek Vasut 		ret = isl7998x_set_test_pattern(isl7998x);
1065*51ef2be5SMarek Vasut 		mutex_unlock(&isl7998x->lock);
1066*51ef2be5SMarek Vasut 		break;
1067*51ef2be5SMarek Vasut 	case V4L2_CID_TEST_PATTERN_CHANNELS:
1068*51ef2be5SMarek Vasut 		mutex_lock(&isl7998x->lock);
1069*51ef2be5SMarek Vasut 		isl7998x->test_pattern_chans = ctrl->val & 0xf;
1070*51ef2be5SMarek Vasut 		ret = isl7998x_set_test_pattern(isl7998x);
1071*51ef2be5SMarek Vasut 		mutex_unlock(&isl7998x->lock);
1072*51ef2be5SMarek Vasut 		break;
1073*51ef2be5SMarek Vasut 	case V4L2_CID_TEST_PATTERN_COLOR:
1074*51ef2be5SMarek Vasut 		mutex_lock(&isl7998x->lock);
1075*51ef2be5SMarek Vasut 		isl7998x->test_pattern_color = ctrl->val & 0x3;
1076*51ef2be5SMarek Vasut 		ret = isl7998x_set_test_pattern(isl7998x);
1077*51ef2be5SMarek Vasut 		mutex_unlock(&isl7998x->lock);
1078*51ef2be5SMarek Vasut 		break;
1079*51ef2be5SMarek Vasut 	case V4L2_CID_TEST_PATTERN:
1080*51ef2be5SMarek Vasut 		mutex_lock(&isl7998x->lock);
1081*51ef2be5SMarek Vasut 		isl7998x->test_pattern = ctrl->val;
1082*51ef2be5SMarek Vasut 		ret = isl7998x_set_test_pattern(isl7998x);
1083*51ef2be5SMarek Vasut 		mutex_unlock(&isl7998x->lock);
1084*51ef2be5SMarek Vasut 		break;
1085*51ef2be5SMarek Vasut 	}
1086*51ef2be5SMarek Vasut 
1087*51ef2be5SMarek Vasut 	return ret;
1088*51ef2be5SMarek Vasut }
1089*51ef2be5SMarek Vasut 
1090*51ef2be5SMarek Vasut static const struct v4l2_subdev_core_ops isl7998x_subdev_core_ops = {
1091*51ef2be5SMarek Vasut #ifdef CONFIG_VIDEO_ADV_DEBUG
1092*51ef2be5SMarek Vasut 	.g_register	= isl7998x_g_register,
1093*51ef2be5SMarek Vasut 	.s_register	= isl7998x_s_register,
1094*51ef2be5SMarek Vasut #endif
1095*51ef2be5SMarek Vasut };
1096*51ef2be5SMarek Vasut 
1097*51ef2be5SMarek Vasut static const struct v4l2_subdev_video_ops isl7998x_subdev_video_ops = {
1098*51ef2be5SMarek Vasut 	.g_std		= isl7998x_g_std,
1099*51ef2be5SMarek Vasut 	.s_std		= isl7998x_s_std,
1100*51ef2be5SMarek Vasut 	.querystd	= isl7998x_querystd,
1101*51ef2be5SMarek Vasut 	.g_tvnorms	= isl7998x_g_tvnorms,
1102*51ef2be5SMarek Vasut 	.g_input_status	= isl7998x_g_input_status,
1103*51ef2be5SMarek Vasut 	.s_stream	= isl7998x_s_stream,
1104*51ef2be5SMarek Vasut 	.pre_streamon	= isl7998x_pre_streamon,
1105*51ef2be5SMarek Vasut 	.post_streamoff	= isl7998x_post_streamoff,
1106*51ef2be5SMarek Vasut };
1107*51ef2be5SMarek Vasut 
1108*51ef2be5SMarek Vasut static const struct v4l2_subdev_pad_ops isl7998x_subdev_pad_ops = {
1109*51ef2be5SMarek Vasut 	.enum_mbus_code		= isl7998x_enum_mbus_code,
1110*51ef2be5SMarek Vasut 	.enum_frame_size	= isl7998x_enum_frame_size,
1111*51ef2be5SMarek Vasut 	.get_fmt		= isl7998x_get_fmt,
1112*51ef2be5SMarek Vasut 	.set_fmt		= isl7998x_set_fmt,
1113*51ef2be5SMarek Vasut };
1114*51ef2be5SMarek Vasut 
1115*51ef2be5SMarek Vasut static const struct v4l2_subdev_ops isl7998x_subdev_ops = {
1116*51ef2be5SMarek Vasut 	.core		= &isl7998x_subdev_core_ops,
1117*51ef2be5SMarek Vasut 	.video		= &isl7998x_subdev_video_ops,
1118*51ef2be5SMarek Vasut 	.pad		= &isl7998x_subdev_pad_ops,
1119*51ef2be5SMarek Vasut };
1120*51ef2be5SMarek Vasut 
1121*51ef2be5SMarek Vasut static const struct media_entity_operations isl7998x_entity_ops = {
1122*51ef2be5SMarek Vasut 	.link_validate = v4l2_subdev_link_validate,
1123*51ef2be5SMarek Vasut };
1124*51ef2be5SMarek Vasut 
1125*51ef2be5SMarek Vasut static const struct v4l2_ctrl_ops isl7998x_ctrl_ops = {
1126*51ef2be5SMarek Vasut 	.s_ctrl			= isl7998x_set_ctrl,
1127*51ef2be5SMarek Vasut };
1128*51ef2be5SMarek Vasut 
1129*51ef2be5SMarek Vasut static const struct v4l2_ctrl_config isl7998x_ctrls[] = {
1130*51ef2be5SMarek Vasut 	{
1131*51ef2be5SMarek Vasut 		.ops		= &isl7998x_ctrl_ops,
1132*51ef2be5SMarek Vasut 		.id		= V4L2_CID_TEST_PATTERN_BARS,
1133*51ef2be5SMarek Vasut 		.type		= V4L2_CTRL_TYPE_MENU,
1134*51ef2be5SMarek Vasut 		.name		= "Test Pattern Bars",
1135*51ef2be5SMarek Vasut 		.max		= ARRAY_SIZE(isl7998x_test_pattern_bars) - 1,
1136*51ef2be5SMarek Vasut 		.def		= 0,
1137*51ef2be5SMarek Vasut 		.qmenu		= isl7998x_test_pattern_bars,
1138*51ef2be5SMarek Vasut 	}, {
1139*51ef2be5SMarek Vasut 		.ops		= &isl7998x_ctrl_ops,
1140*51ef2be5SMarek Vasut 		.id		= V4L2_CID_TEST_PATTERN_CHANNELS,
1141*51ef2be5SMarek Vasut 		.type		= V4L2_CTRL_TYPE_INTEGER,
1142*51ef2be5SMarek Vasut 		.name		= "Test Pattern Channels",
1143*51ef2be5SMarek Vasut 		.min		= 0,
1144*51ef2be5SMarek Vasut 		.max		= 0xf,
1145*51ef2be5SMarek Vasut 		.step		= 1,
1146*51ef2be5SMarek Vasut 		.def		= 0xf,
1147*51ef2be5SMarek Vasut 		.flags		= 0,
1148*51ef2be5SMarek Vasut 	}, {
1149*51ef2be5SMarek Vasut 		.ops		= &isl7998x_ctrl_ops,
1150*51ef2be5SMarek Vasut 		.id		= V4L2_CID_TEST_PATTERN_COLOR,
1151*51ef2be5SMarek Vasut 		.type		= V4L2_CTRL_TYPE_MENU,
1152*51ef2be5SMarek Vasut 		.name		= "Test Pattern Color",
1153*51ef2be5SMarek Vasut 		.max		= ARRAY_SIZE(isl7998x_test_pattern_colors) - 1,
1154*51ef2be5SMarek Vasut 		.def		= 0,
1155*51ef2be5SMarek Vasut 		.qmenu		= isl7998x_test_pattern_colors,
1156*51ef2be5SMarek Vasut 	},
1157*51ef2be5SMarek Vasut };
1158*51ef2be5SMarek Vasut 
1159*51ef2be5SMarek Vasut #define ISL7998X_REG_DECODER_ACA_READABLE_RANGE(page)			\
1160*51ef2be5SMarek Vasut 	/* Decoder range */						\
1161*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_INPUT_FMT(page),		\
1162*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_HS_DELAY_CTL(page)),	\
1163*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_ANCTL(page),		\
1164*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_CSC_CTL(page)),		\
1165*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_BRIGHT(page),		\
1166*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_HUE(page)),		\
1167*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_VERT_PEAK(page),		\
1168*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_CORING(page)),		\
1169*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_SDT(page),			\
1170*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_SDTR(page)),		\
1171*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_CLMPG(page),		\
1172*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_DATA_CONV(page)),		\
1173*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_INTERNAL_TEST(page),	\
1174*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_INTERNAL_TEST(page)),	\
1175*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_H_DELAY_CTL(page),		\
1176*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(page)),	\
1177*51ef2be5SMarek Vasut 	/* ACA range */							\
1178*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_CTL_1(page),		\
1179*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2(page)),	\
1180*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_Y_AVG(page),		\
1181*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_CTL_4(page)),		\
1182*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_FLEX_WIN_HIST(page),	\
1183*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_XFER_HIST_HOST(page)),	\
1184*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(page),		\
1185*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(page))
1186*51ef2be5SMarek Vasut 
1187*51ef2be5SMarek Vasut #define ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(page)			\
1188*51ef2be5SMarek Vasut 	/* Decoder range */						\
1189*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_INPUT_FMT(page),		\
1190*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_INPUT_FMT(page)),		\
1191*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_HS_DELAY_CTL(page),	\
1192*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_HS_DELAY_CTL(page)),	\
1193*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_ANCTL(page),		\
1194*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_CSC_CTL(page)),		\
1195*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_BRIGHT(page),		\
1196*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_HUE(page)),		\
1197*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_VERT_PEAK(page),		\
1198*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_CORING(page)),		\
1199*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_SDT(page),			\
1200*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_SDTR(page)),		\
1201*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_CLMPG(page),		\
1202*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_MISC3(page)),		\
1203*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_CLMD(page),		\
1204*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_DATA_CONV(page)),		\
1205*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_INTERNAL_TEST(page),	\
1206*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_INTERNAL_TEST(page)),	\
1207*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_H_DELAY_CTL(page),		\
1208*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_H_DELAY_II_LOW(page)),	\
1209*51ef2be5SMarek Vasut 	/* ACA range */							\
1210*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_CTL_1(page),		\
1211*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_HIST_WIN_V_SZ2(page)),	\
1212*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_CTL_2(page),		\
1213*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_CTL_4(page)),		\
1214*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_FLEX_WIN_HIST(page),	\
1215*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_HIST_DATA_LO(page)),	\
1216*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_XFER_HIST_HOST(page),	\
1217*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_XFER_HIST_HOST(page)),	\
1218*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(page),		\
1219*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(page))
1220*51ef2be5SMarek Vasut 
1221*51ef2be5SMarek Vasut #define ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(page)			\
1222*51ef2be5SMarek Vasut 	/* Decoder range */						\
1223*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_STATUS_1(page),		\
1224*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_STATUS_1(page)),		\
1225*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_SDT(page),			\
1226*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_SDT(page)),		\
1227*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_MVSN(page),		\
1228*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_HFREF(page)),		\
1229*51ef2be5SMarek Vasut 	/* ACA range */							\
1230*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_Y_AVG(page),		\
1231*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_Y_HIGH(page)),		\
1232*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_ACA_HIST_DATA_LO(page),	\
1233*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_ACA_FLEX_WIN_CR_CLR(page))
1234*51ef2be5SMarek Vasut 
1235*51ef2be5SMarek Vasut static const struct regmap_range isl7998x_readable_ranges[] = {
1236*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_PRODUCT_ID_CODE,
1237*51ef2be5SMarek Vasut 			 ISL7998X_REG_P0_IRQ_SYNC_CTL),
1238*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_INTERRUPT_STATUS,
1239*51ef2be5SMarek Vasut 			 ISL7998X_REG_P0_CLOCK_DELAY),
1240*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(0),
1241*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(0)),
1242*51ef2be5SMarek Vasut 
1243*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_READABLE_RANGE(1),
1244*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_READABLE_RANGE(2),
1245*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_READABLE_RANGE(3),
1246*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_READABLE_RANGE(4),
1247*51ef2be5SMarek Vasut 
1248*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_LI_ENGINE_CTL,
1249*51ef2be5SMarek Vasut 			 ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL),
1250*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_FIFO_THRSH_CNT_1,
1251*51ef2be5SMarek Vasut 			 ISL7998X_REG_P5_PLL_ANA),
1252*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1,
1253*51ef2be5SMarek Vasut 			 ISL7998X_REG_P5_HIST_LINE_CNT_2),
1254*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(5),
1255*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(5)),
1256*51ef2be5SMarek Vasut };
1257*51ef2be5SMarek Vasut 
1258*51ef2be5SMarek Vasut static const struct regmap_range isl7998x_writeable_ranges[] = {
1259*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_SW_RESET_CTL,
1260*51ef2be5SMarek Vasut 			 ISL7998X_REG_P0_IRQ_SYNC_CTL),
1261*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_CHAN_1_IRQ,
1262*51ef2be5SMarek Vasut 			 ISL7998X_REG_P0_SHORT_DIAG_IRQ_EN),
1263*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_CLOCK_DELAY,
1264*51ef2be5SMarek Vasut 			 ISL7998X_REG_P0_CLOCK_DELAY),
1265*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(0),
1266*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(0)),
1267*51ef2be5SMarek Vasut 
1268*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(1),
1269*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(2),
1270*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(3),
1271*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(4),
1272*51ef2be5SMarek Vasut 
1273*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_LI_ENGINE_CTL,
1274*51ef2be5SMarek Vasut 			 ISL7998X_REG_P5_ESC_MODE_TIME_CTL),
1275*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_MIPI_SP_HS_TRL_CTL,
1276*51ef2be5SMarek Vasut 			 ISL7998X_REG_P5_PLL_ANA),
1277*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_TOTAL_PF_LINE_CNT_1,
1278*51ef2be5SMarek Vasut 			 ISL7998X_REG_P5_HIST_LINE_CNT_2),
1279*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_PX_DEC_PAGE(5),
1280*51ef2be5SMarek Vasut 			 ISL7998X_REG_PX_DEC_PAGE(5)),
1281*51ef2be5SMarek Vasut 
1282*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(0xf),
1283*51ef2be5SMarek Vasut };
1284*51ef2be5SMarek Vasut 
1285*51ef2be5SMarek Vasut static const struct regmap_range isl7998x_volatile_ranges[] = {
1286*51ef2be5SMarek Vasut 	/* Product id code register is used to check availability */
1287*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_PRODUCT_ID_CODE,
1288*51ef2be5SMarek Vasut 			 ISL7998X_REG_P0_PRODUCT_ID_CODE),
1289*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_MPP1_SYNC_CTL,
1290*51ef2be5SMarek Vasut 			 ISL7998X_REG_P0_IRQ_SYNC_CTL),
1291*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_INTERRUPT_STATUS,
1292*51ef2be5SMarek Vasut 			 ISL7998X_REG_P0_INTERRUPT_STATUS),
1293*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P0_CHAN_1_STATUS,
1294*51ef2be5SMarek Vasut 			 ISL7998X_REG_P0_SHORT_DIAG_STATUS),
1295*51ef2be5SMarek Vasut 
1296*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(1),
1297*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(2),
1298*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(3),
1299*51ef2be5SMarek Vasut 	ISL7998X_REG_DECODER_ACA_VOLATILE_RANGE(4),
1300*51ef2be5SMarek Vasut 
1301*51ef2be5SMarek Vasut 	regmap_reg_range(ISL7998X_REG_P5_AUTO_TEST_ERR_DET,
1302*51ef2be5SMarek Vasut 			 ISL7998X_REG_P5_PIC_HEIGHT_LOW),
1303*51ef2be5SMarek Vasut };
1304*51ef2be5SMarek Vasut 
1305*51ef2be5SMarek Vasut static const struct regmap_access_table isl7998x_readable_table = {
1306*51ef2be5SMarek Vasut 	.yes_ranges = isl7998x_readable_ranges,
1307*51ef2be5SMarek Vasut 	.n_yes_ranges = ARRAY_SIZE(isl7998x_readable_ranges),
1308*51ef2be5SMarek Vasut };
1309*51ef2be5SMarek Vasut 
1310*51ef2be5SMarek Vasut static const struct regmap_access_table isl7998x_writeable_table = {
1311*51ef2be5SMarek Vasut 	.yes_ranges = isl7998x_writeable_ranges,
1312*51ef2be5SMarek Vasut 	.n_yes_ranges = ARRAY_SIZE(isl7998x_writeable_ranges),
1313*51ef2be5SMarek Vasut };
1314*51ef2be5SMarek Vasut 
1315*51ef2be5SMarek Vasut static const struct regmap_access_table isl7998x_volatile_table = {
1316*51ef2be5SMarek Vasut 	.yes_ranges = isl7998x_volatile_ranges,
1317*51ef2be5SMarek Vasut 	.n_yes_ranges = ARRAY_SIZE(isl7998x_volatile_ranges),
1318*51ef2be5SMarek Vasut };
1319*51ef2be5SMarek Vasut 
1320*51ef2be5SMarek Vasut static const struct regmap_range_cfg isl7998x_ranges[] = {
1321*51ef2be5SMarek Vasut 	{
1322*51ef2be5SMarek Vasut 		.range_min	= ISL7998X_REG_PN_BASE(0),
1323*51ef2be5SMarek Vasut 		.range_max	= ISL7998X_REG_PX_ACA_XFER_HIST_HOST(0xf),
1324*51ef2be5SMarek Vasut 		.selector_reg	= ISL7998X_REG_PX_DEC_PAGE(0),
1325*51ef2be5SMarek Vasut 		.selector_mask	= ISL7998X_REG_PX_DEC_PAGE_MASK,
1326*51ef2be5SMarek Vasut 		.window_start	= 0,
1327*51ef2be5SMarek Vasut 		.window_len	= 256,
1328*51ef2be5SMarek Vasut 	}
1329*51ef2be5SMarek Vasut };
1330*51ef2be5SMarek Vasut 
1331*51ef2be5SMarek Vasut static const struct regmap_config isl7998x_regmap = {
1332*51ef2be5SMarek Vasut 	.reg_bits	= 8,
1333*51ef2be5SMarek Vasut 	.val_bits	= 8,
1334*51ef2be5SMarek Vasut 	.max_register	= ISL7998X_REG_PX_ACA_XFER_HIST_HOST(0xf),
1335*51ef2be5SMarek Vasut 	.ranges		= isl7998x_ranges,
1336*51ef2be5SMarek Vasut 	.num_ranges	= ARRAY_SIZE(isl7998x_ranges),
1337*51ef2be5SMarek Vasut 	.rd_table	= &isl7998x_readable_table,
1338*51ef2be5SMarek Vasut 	.wr_table	= &isl7998x_writeable_table,
1339*51ef2be5SMarek Vasut 	.volatile_table	= &isl7998x_volatile_table,
1340*51ef2be5SMarek Vasut 	.cache_type	= REGCACHE_RBTREE,
1341*51ef2be5SMarek Vasut };
1342*51ef2be5SMarek Vasut 
1343*51ef2be5SMarek Vasut static int isl7998x_mc_init(struct isl7998x *isl7998x)
1344*51ef2be5SMarek Vasut {
1345*51ef2be5SMarek Vasut 	unsigned int i;
1346*51ef2be5SMarek Vasut 
1347*51ef2be5SMarek Vasut 	isl7998x->subdev.entity.ops = &isl7998x_entity_ops;
1348*51ef2be5SMarek Vasut 	isl7998x->subdev.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
1349*51ef2be5SMarek Vasut 
1350*51ef2be5SMarek Vasut 	isl7998x->pads[ISL7998X_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE;
1351*51ef2be5SMarek Vasut 	for (i = ISL7998X_PAD_VIN1; i < ISL7998X_NUM_PADS; i++)
1352*51ef2be5SMarek Vasut 		isl7998x->pads[i].flags = MEDIA_PAD_FL_SINK;
1353*51ef2be5SMarek Vasut 
1354*51ef2be5SMarek Vasut 	return media_entity_pads_init(&isl7998x->subdev.entity,
1355*51ef2be5SMarek Vasut 				      ISL7998X_NUM_PADS,
1356*51ef2be5SMarek Vasut 				      isl7998x->pads);
1357*51ef2be5SMarek Vasut }
1358*51ef2be5SMarek Vasut 
1359*51ef2be5SMarek Vasut static int get_link_freq_menu_index(unsigned int lanes,
1360*51ef2be5SMarek Vasut 				    unsigned int inputs)
1361*51ef2be5SMarek Vasut {
1362*51ef2be5SMarek Vasut 	int ret = -EINVAL;
1363*51ef2be5SMarek Vasut 
1364*51ef2be5SMarek Vasut 	switch (lanes) {
1365*51ef2be5SMarek Vasut 	case 1:
1366*51ef2be5SMarek Vasut 		if (inputs == 1)
1367*51ef2be5SMarek Vasut 			ret = 0;
1368*51ef2be5SMarek Vasut 		if (inputs == 2)
1369*51ef2be5SMarek Vasut 			ret = 1;
1370*51ef2be5SMarek Vasut 		if (inputs == 4)
1371*51ef2be5SMarek Vasut 			ret = 2;
1372*51ef2be5SMarek Vasut 		break;
1373*51ef2be5SMarek Vasut 	case 2:
1374*51ef2be5SMarek Vasut 		if (inputs == 2)
1375*51ef2be5SMarek Vasut 			ret = 0;
1376*51ef2be5SMarek Vasut 		if (inputs == 4)
1377*51ef2be5SMarek Vasut 			ret = 1;
1378*51ef2be5SMarek Vasut 		break;
1379*51ef2be5SMarek Vasut 	default:
1380*51ef2be5SMarek Vasut 		break;
1381*51ef2be5SMarek Vasut 	}
1382*51ef2be5SMarek Vasut 
1383*51ef2be5SMarek Vasut 	return ret;
1384*51ef2be5SMarek Vasut }
1385*51ef2be5SMarek Vasut 
1386*51ef2be5SMarek Vasut static void isl7998x_remove_controls(struct isl7998x *isl7998x)
1387*51ef2be5SMarek Vasut {
1388*51ef2be5SMarek Vasut 	v4l2_ctrl_handler_free(&isl7998x->ctrl_handler);
1389*51ef2be5SMarek Vasut 	mutex_destroy(&isl7998x->ctrl_mutex);
1390*51ef2be5SMarek Vasut }
1391*51ef2be5SMarek Vasut 
1392*51ef2be5SMarek Vasut static int isl7998x_init_controls(struct isl7998x *isl7998x)
1393*51ef2be5SMarek Vasut {
1394*51ef2be5SMarek Vasut 	struct v4l2_subdev *sd = &isl7998x->subdev;
1395*51ef2be5SMarek Vasut 	int link_freq_index;
1396*51ef2be5SMarek Vasut 	unsigned int i;
1397*51ef2be5SMarek Vasut 	int ret;
1398*51ef2be5SMarek Vasut 
1399*51ef2be5SMarek Vasut 	ret = v4l2_ctrl_handler_init(&isl7998x->ctrl_handler,
1400*51ef2be5SMarek Vasut 				     2 + ARRAY_SIZE(isl7998x_ctrls));
1401*51ef2be5SMarek Vasut 	if (ret)
1402*51ef2be5SMarek Vasut 		return ret;
1403*51ef2be5SMarek Vasut 
1404*51ef2be5SMarek Vasut 	mutex_init(&isl7998x->ctrl_mutex);
1405*51ef2be5SMarek Vasut 	isl7998x->ctrl_handler.lock = &isl7998x->ctrl_mutex;
1406*51ef2be5SMarek Vasut 	link_freq_index = get_link_freq_menu_index(isl7998x->nr_mipi_lanes,
1407*51ef2be5SMarek Vasut 						   isl7998x->nr_inputs);
1408*51ef2be5SMarek Vasut 	if (link_freq_index < 0 ||
1409*51ef2be5SMarek Vasut 	    link_freq_index >= ARRAY_SIZE(link_freq_menu_items)) {
1410*51ef2be5SMarek Vasut 		dev_err(sd->dev,
1411*51ef2be5SMarek Vasut 			"failed to find MIPI link freq: %d lanes, %d inputs\n",
1412*51ef2be5SMarek Vasut 			isl7998x->nr_mipi_lanes, isl7998x->nr_inputs);
1413*51ef2be5SMarek Vasut 		ret = -EINVAL;
1414*51ef2be5SMarek Vasut 		goto err;
1415*51ef2be5SMarek Vasut 	}
1416*51ef2be5SMarek Vasut 
1417*51ef2be5SMarek Vasut 	isl7998x->link_freq = v4l2_ctrl_new_int_menu(&isl7998x->ctrl_handler,
1418*51ef2be5SMarek Vasut 						     &isl7998x_ctrl_ops,
1419*51ef2be5SMarek Vasut 						     V4L2_CID_LINK_FREQ,
1420*51ef2be5SMarek Vasut 						     ARRAY_SIZE(link_freq_menu_items) - 1,
1421*51ef2be5SMarek Vasut 						     link_freq_index,
1422*51ef2be5SMarek Vasut 						     link_freq_menu_items);
1423*51ef2be5SMarek Vasut 	if (isl7998x->link_freq)
1424*51ef2be5SMarek Vasut 		isl7998x->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1425*51ef2be5SMarek Vasut 
1426*51ef2be5SMarek Vasut 	for (i = 0; i < ARRAY_SIZE(isl7998x_ctrls); i++)
1427*51ef2be5SMarek Vasut 		v4l2_ctrl_new_custom(&isl7998x->ctrl_handler,
1428*51ef2be5SMarek Vasut 				     &isl7998x_ctrls[i], NULL);
1429*51ef2be5SMarek Vasut 
1430*51ef2be5SMarek Vasut 	v4l2_ctrl_new_std_menu_items(&isl7998x->ctrl_handler,
1431*51ef2be5SMarek Vasut 				     &isl7998x_ctrl_ops,
1432*51ef2be5SMarek Vasut 				     V4L2_CID_TEST_PATTERN,
1433*51ef2be5SMarek Vasut 				     ARRAY_SIZE(isl7998x_test_pattern_menu) - 1,
1434*51ef2be5SMarek Vasut 				     0, 0, isl7998x_test_pattern_menu);
1435*51ef2be5SMarek Vasut 
1436*51ef2be5SMarek Vasut 	ret = isl7998x->ctrl_handler.error;
1437*51ef2be5SMarek Vasut 	if (ret)
1438*51ef2be5SMarek Vasut 		goto err;
1439*51ef2be5SMarek Vasut 
1440*51ef2be5SMarek Vasut 	isl7998x->subdev.ctrl_handler = &isl7998x->ctrl_handler;
1441*51ef2be5SMarek Vasut 	v4l2_ctrl_handler_setup(&isl7998x->ctrl_handler);
1442*51ef2be5SMarek Vasut 
1443*51ef2be5SMarek Vasut 	return 0;
1444*51ef2be5SMarek Vasut 
1445*51ef2be5SMarek Vasut err:
1446*51ef2be5SMarek Vasut 	isl7998x_remove_controls(isl7998x);
1447*51ef2be5SMarek Vasut 
1448*51ef2be5SMarek Vasut 	return ret;
1449*51ef2be5SMarek Vasut }
1450*51ef2be5SMarek Vasut 
1451*51ef2be5SMarek Vasut static int isl7998x_probe(struct i2c_client *client)
1452*51ef2be5SMarek Vasut {
1453*51ef2be5SMarek Vasut 	struct device *dev = &client->dev;
1454*51ef2be5SMarek Vasut 	struct v4l2_fwnode_endpoint endpoint = {
1455*51ef2be5SMarek Vasut 		.bus_type = V4L2_MBUS_CSI2_DPHY,
1456*51ef2be5SMarek Vasut 	};
1457*51ef2be5SMarek Vasut 	struct fwnode_handle *ep;
1458*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x;
1459*51ef2be5SMarek Vasut 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
1460*51ef2be5SMarek Vasut 	int nr_inputs;
1461*51ef2be5SMarek Vasut 	int ret;
1462*51ef2be5SMarek Vasut 
1463*51ef2be5SMarek Vasut 	ret = i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA);
1464*51ef2be5SMarek Vasut 	if (!ret) {
1465*51ef2be5SMarek Vasut 		dev_warn(&adapter->dev,
1466*51ef2be5SMarek Vasut 			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
1467*51ef2be5SMarek Vasut 		return -EIO;
1468*51ef2be5SMarek Vasut 	}
1469*51ef2be5SMarek Vasut 
1470*51ef2be5SMarek Vasut 	isl7998x = devm_kzalloc(dev, sizeof(*isl7998x), GFP_KERNEL);
1471*51ef2be5SMarek Vasut 	if (!isl7998x)
1472*51ef2be5SMarek Vasut 		return -ENOMEM;
1473*51ef2be5SMarek Vasut 
1474*51ef2be5SMarek Vasut 	isl7998x->pd_gpio = devm_gpiod_get_optional(dev, "powerdown",
1475*51ef2be5SMarek Vasut 						    GPIOD_OUT_HIGH);
1476*51ef2be5SMarek Vasut 	if (IS_ERR(isl7998x->pd_gpio))
1477*51ef2be5SMarek Vasut 		return dev_err_probe(dev, PTR_ERR(isl7998x->pd_gpio),
1478*51ef2be5SMarek Vasut 				     "Failed to retrieve/request PD GPIO\n");
1479*51ef2be5SMarek Vasut 
1480*51ef2be5SMarek Vasut 	isl7998x->rstb_gpio = devm_gpiod_get_optional(dev, "reset",
1481*51ef2be5SMarek Vasut 						      GPIOD_OUT_HIGH);
1482*51ef2be5SMarek Vasut 	if (IS_ERR(isl7998x->rstb_gpio))
1483*51ef2be5SMarek Vasut 		return dev_err_probe(dev, PTR_ERR(isl7998x->rstb_gpio),
1484*51ef2be5SMarek Vasut 				     "Failed to retrieve/request RSTB GPIO\n");
1485*51ef2be5SMarek Vasut 
1486*51ef2be5SMarek Vasut 	isl7998x->regmap = devm_regmap_init_i2c(client, &isl7998x_regmap);
1487*51ef2be5SMarek Vasut 	if (IS_ERR(isl7998x->regmap))
1488*51ef2be5SMarek Vasut 		return dev_err_probe(dev, PTR_ERR(isl7998x->regmap),
1489*51ef2be5SMarek Vasut 				     "Failed to allocate register map\n");
1490*51ef2be5SMarek Vasut 
1491*51ef2be5SMarek Vasut 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
1492*51ef2be5SMarek Vasut 					     ISL7998X_PAD_OUT, 0, 0);
1493*51ef2be5SMarek Vasut 	if (!ep)
1494*51ef2be5SMarek Vasut 		return dev_err_probe(dev, -EINVAL, "Missing endpoint node\n");
1495*51ef2be5SMarek Vasut 
1496*51ef2be5SMarek Vasut 	ret = v4l2_fwnode_endpoint_parse(ep, &endpoint);
1497*51ef2be5SMarek Vasut 	fwnode_handle_put(ep);
1498*51ef2be5SMarek Vasut 	if (ret)
1499*51ef2be5SMarek Vasut 		return dev_err_probe(dev, ret, "Failed to parse endpoint\n");
1500*51ef2be5SMarek Vasut 
1501*51ef2be5SMarek Vasut 	if (endpoint.bus.mipi_csi2.num_data_lanes == 0 ||
1502*51ef2be5SMarek Vasut 	    endpoint.bus.mipi_csi2.num_data_lanes > 2)
1503*51ef2be5SMarek Vasut 		return dev_err_probe(dev, -EINVAL,
1504*51ef2be5SMarek Vasut 				     "Invalid number of MIPI lanes\n");
1505*51ef2be5SMarek Vasut 
1506*51ef2be5SMarek Vasut 	isl7998x->nr_mipi_lanes = endpoint.bus.mipi_csi2.num_data_lanes;
1507*51ef2be5SMarek Vasut 
1508*51ef2be5SMarek Vasut 	nr_inputs = isl7998x_get_nr_inputs(dev->of_node);
1509*51ef2be5SMarek Vasut 	if (nr_inputs < 0)
1510*51ef2be5SMarek Vasut 		return dev_err_probe(dev, nr_inputs,
1511*51ef2be5SMarek Vasut 				     "Invalid number of input ports\n");
1512*51ef2be5SMarek Vasut 	isl7998x->nr_inputs = nr_inputs;
1513*51ef2be5SMarek Vasut 
1514*51ef2be5SMarek Vasut 	v4l2_i2c_subdev_init(&isl7998x->subdev, client, &isl7998x_subdev_ops);
1515*51ef2be5SMarek Vasut 	isl7998x->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1516*51ef2be5SMarek Vasut 
1517*51ef2be5SMarek Vasut 	ret = isl7998x_mc_init(isl7998x);
1518*51ef2be5SMarek Vasut 	if (ret < 0)
1519*51ef2be5SMarek Vasut 		return ret;
1520*51ef2be5SMarek Vasut 
1521*51ef2be5SMarek Vasut 	isl7998x->fmt = &isl7998x_colour_fmts[0];
1522*51ef2be5SMarek Vasut 	isl7998x->norm = V4L2_STD_NTSC;
1523*51ef2be5SMarek Vasut 	isl7998x->enabled = 0;
1524*51ef2be5SMarek Vasut 
1525*51ef2be5SMarek Vasut 	mutex_init(&isl7998x->lock);
1526*51ef2be5SMarek Vasut 
1527*51ef2be5SMarek Vasut 	ret = isl7998x_init_controls(isl7998x);
1528*51ef2be5SMarek Vasut 	if (ret)
1529*51ef2be5SMarek Vasut 		goto err_entity_cleanup;
1530*51ef2be5SMarek Vasut 
1531*51ef2be5SMarek Vasut 	ret = v4l2_async_register_subdev(&isl7998x->subdev);
1532*51ef2be5SMarek Vasut 	if (ret < 0)
1533*51ef2be5SMarek Vasut 		goto err_controls_cleanup;
1534*51ef2be5SMarek Vasut 
1535*51ef2be5SMarek Vasut 	pm_runtime_enable(dev);
1536*51ef2be5SMarek Vasut 
1537*51ef2be5SMarek Vasut 	return 0;
1538*51ef2be5SMarek Vasut 
1539*51ef2be5SMarek Vasut err_controls_cleanup:
1540*51ef2be5SMarek Vasut 	isl7998x_remove_controls(isl7998x);
1541*51ef2be5SMarek Vasut err_entity_cleanup:
1542*51ef2be5SMarek Vasut 	media_entity_cleanup(&isl7998x->subdev.entity);
1543*51ef2be5SMarek Vasut 
1544*51ef2be5SMarek Vasut 	return ret;
1545*51ef2be5SMarek Vasut }
1546*51ef2be5SMarek Vasut 
1547*51ef2be5SMarek Vasut static int isl7998x_remove(struct i2c_client *client)
1548*51ef2be5SMarek Vasut {
1549*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = i2c_to_isl7998x(client);
1550*51ef2be5SMarek Vasut 
1551*51ef2be5SMarek Vasut 	pm_runtime_disable(&client->dev);
1552*51ef2be5SMarek Vasut 	v4l2_async_unregister_subdev(&isl7998x->subdev);
1553*51ef2be5SMarek Vasut 	isl7998x_remove_controls(isl7998x);
1554*51ef2be5SMarek Vasut 	media_entity_cleanup(&isl7998x->subdev.entity);
1555*51ef2be5SMarek Vasut 
1556*51ef2be5SMarek Vasut 	return 0;
1557*51ef2be5SMarek Vasut }
1558*51ef2be5SMarek Vasut 
1559*51ef2be5SMarek Vasut static const struct of_device_id isl7998x_of_match[] = {
1560*51ef2be5SMarek Vasut 	{ .compatible = "isil,isl79987", },
1561*51ef2be5SMarek Vasut 	{ /* sentinel */ },
1562*51ef2be5SMarek Vasut };
1563*51ef2be5SMarek Vasut MODULE_DEVICE_TABLE(of, isl7998x_of_match);
1564*51ef2be5SMarek Vasut 
1565*51ef2be5SMarek Vasut static const struct i2c_device_id isl7998x_id[] = {
1566*51ef2be5SMarek Vasut 	{ "isl79987", 0 },
1567*51ef2be5SMarek Vasut 	{ /* sentinel */ },
1568*51ef2be5SMarek Vasut };
1569*51ef2be5SMarek Vasut MODULE_DEVICE_TABLE(i2c, isl7998x_id);
1570*51ef2be5SMarek Vasut 
1571*51ef2be5SMarek Vasut static int __maybe_unused isl7998x_runtime_resume(struct device *dev)
1572*51ef2be5SMarek Vasut {
1573*51ef2be5SMarek Vasut 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
1574*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
1575*51ef2be5SMarek Vasut 	int ret;
1576*51ef2be5SMarek Vasut 
1577*51ef2be5SMarek Vasut 	gpiod_set_value(isl7998x->rstb_gpio, 1);
1578*51ef2be5SMarek Vasut 	gpiod_set_value(isl7998x->pd_gpio, 0);
1579*51ef2be5SMarek Vasut 	gpiod_set_value(isl7998x->rstb_gpio, 0);
1580*51ef2be5SMarek Vasut 
1581*51ef2be5SMarek Vasut 	ret = isl7998x_wait_power_on(isl7998x);
1582*51ef2be5SMarek Vasut 	if (ret)
1583*51ef2be5SMarek Vasut 		goto err;
1584*51ef2be5SMarek Vasut 
1585*51ef2be5SMarek Vasut 	ret = isl7998x_init(isl7998x);
1586*51ef2be5SMarek Vasut 	if (ret)
1587*51ef2be5SMarek Vasut 		goto err;
1588*51ef2be5SMarek Vasut 
1589*51ef2be5SMarek Vasut 	return 0;
1590*51ef2be5SMarek Vasut 
1591*51ef2be5SMarek Vasut err:
1592*51ef2be5SMarek Vasut 	gpiod_set_value(isl7998x->pd_gpio, 1);
1593*51ef2be5SMarek Vasut 
1594*51ef2be5SMarek Vasut 	return ret;
1595*51ef2be5SMarek Vasut }
1596*51ef2be5SMarek Vasut 
1597*51ef2be5SMarek Vasut static int __maybe_unused isl7998x_runtime_suspend(struct device *dev)
1598*51ef2be5SMarek Vasut {
1599*51ef2be5SMarek Vasut 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
1600*51ef2be5SMarek Vasut 	struct isl7998x *isl7998x = sd_to_isl7998x(sd);
1601*51ef2be5SMarek Vasut 
1602*51ef2be5SMarek Vasut 	gpiod_set_value(isl7998x->pd_gpio, 1);
1603*51ef2be5SMarek Vasut 
1604*51ef2be5SMarek Vasut 	return 0;
1605*51ef2be5SMarek Vasut }
1606*51ef2be5SMarek Vasut 
1607*51ef2be5SMarek Vasut static const struct dev_pm_ops isl7998x_pm_ops = {
1608*51ef2be5SMarek Vasut 	SET_RUNTIME_PM_OPS(isl7998x_runtime_suspend,
1609*51ef2be5SMarek Vasut 			   isl7998x_runtime_resume,
1610*51ef2be5SMarek Vasut 			   NULL)
1611*51ef2be5SMarek Vasut };
1612*51ef2be5SMarek Vasut 
1613*51ef2be5SMarek Vasut static struct i2c_driver isl7998x_i2c_driver = {
1614*51ef2be5SMarek Vasut 	.driver = {
1615*51ef2be5SMarek Vasut 		.name = "isl7998x",
1616*51ef2be5SMarek Vasut 		.of_match_table = of_match_ptr(isl7998x_of_match),
1617*51ef2be5SMarek Vasut 		.pm = &isl7998x_pm_ops,
1618*51ef2be5SMarek Vasut 	},
1619*51ef2be5SMarek Vasut 	.probe_new	= isl7998x_probe,
1620*51ef2be5SMarek Vasut 	.remove		= isl7998x_remove,
1621*51ef2be5SMarek Vasut 	.id_table	= isl7998x_id,
1622*51ef2be5SMarek Vasut };
1623*51ef2be5SMarek Vasut 
1624*51ef2be5SMarek Vasut module_i2c_driver(isl7998x_i2c_driver);
1625*51ef2be5SMarek Vasut 
1626*51ef2be5SMarek Vasut MODULE_DESCRIPTION("Intersil ISL7998x Analog to MIPI CSI-2/BT656 decoder");
1627*51ef2be5SMarek Vasut MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
1628*51ef2be5SMarek Vasut MODULE_LICENSE("GPL v2");
1629