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