1 // SPDX-License-Identifier: GPL-2.0
3 * Intersil ISL7998x analog to MIPI CSI-2 or BT.656 decoder driver.
5 * Copyright (C) 2018-2019 Marek Vasut <marex@denx.de>
6 * Copyright (C) 2021 Michael Tretter <kernel@pengutronix.de>
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>
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>
29 * This control allows to activate and deactivate the test pattern on
30 * selected output channels.
31 * This value is ISL7998x specific.
33 #define V4L2_CID_TEST_PATTERN_CHANNELS (V4L2_CID_USER_ISL7998X_BASE + 0)
36 * This control allows to specify the color of the test pattern.
37 * This value is ISL7998x specific.
39 #define V4L2_CID_TEST_PATTERN_COLOR (V4L2_CID_USER_ISL7998X_BASE + 1)
42 * This control allows to specify the bar pattern in the test pattern.
43 * This value is ISL7998x specific.
45 #define V4L2_CID_TEST_PATTERN_BARS (V4L2_CID_USER_ISL7998X_BASE + 2)
47 #define ISL7998X_INPUTS 4
49 #define ISL7998X_REG(page, reg) (((page) << 8) | (reg))
51 #define ISL7998X_REG_PN_SIZE 256
52 #define ISL7998X_REG_PN_BASE(n) ((n) * ISL7998X_REG_PN_SIZE)
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)
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)
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)
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)
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 },
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 },
410 * Wait a bit after reset so that the chip can capture a frame
411 * and update internal line counters.
413 { ISL7998X_REG_P0_SW_RESET_CTL
, 0x00, 50 },
425 struct isl7998x_datafmt
{
427 enum v4l2_colorspace colorspace
;
430 static const struct isl7998x_datafmt isl7998x_colour_fmts
[] = {
431 { MEDIA_BUS_FMT_UYVY8_2X8
, V4L2_COLORSPACE_SRGB
},
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 */
438 /* 2 channels, 1 lane or 4 channels, 2 lanes */
440 /* 4 channels, 1 lane */
444 /* Menu items for TEST_PATTERN V4L2 control */
445 static const char * const isl7998x_test_pattern_menu
[] = {
450 static const char * const isl7998x_test_pattern_bars
[] = {
451 "bbbbwb", "bbbwwb", "bbwbwb", "bbwwwb",
454 static const char * const isl7998x_test_pattern_colors
[] = {
455 "Yellow", "Blue", "Green", "Pink",
458 struct isl7998x_mode
{
461 enum v4l2_field field
;
464 static const struct isl7998x_mode supported_modes
[] = {
468 .field
= V4L2_FIELD_SEQ_TB
,
473 .field
= V4L2_FIELD_SEQ_BT
,
477 static const struct isl7998x_video_std
{
478 const v4l2_std_id norm
;
480 const struct isl7998x_mode
*mode
;
481 } isl7998x_std_res
[] = {
483 ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_443
,
484 &supported_modes
[1] },
486 ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_M
,
487 &supported_modes
[1] },
489 ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_CN
,
490 &supported_modes
[0] },
492 ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL
,
493 &supported_modes
[0] },
495 ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL_60
,
496 &supported_modes
[1] },
498 ISL7998X_REG_PX_DEC_SDT_STANDARD_NTSC_M
,
499 &supported_modes
[1] },
501 ISL7998X_REG_PX_DEC_SDT_STANDARD_PAL
,
502 &supported_modes
[0] },
504 ISL7998X_REG_PX_DEC_SDT_STANDARD_SECAM
,
505 &supported_modes
[0] },
507 ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN
,
508 &supported_modes
[1] },
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
;
519 const struct isl7998x_datafmt
*fmt
;
521 struct media_pad pads
[ISL7998X_NUM_PADS
];
525 /* protect fmt, norm, enabled */
528 struct v4l2_ctrl_handler ctrl_handler
;
529 /* protect ctrl_handler */
530 struct mutex ctrl_mutex
;
533 struct v4l2_ctrl
*link_freq
;
535 u8 test_pattern_bars
;
536 u8 test_pattern_chans
;
537 u8 test_pattern_color
;
540 static struct isl7998x
*sd_to_isl7998x(struct v4l2_subdev
*sd
)
542 return container_of(sd
, struct isl7998x
, subdev
);
545 static struct isl7998x
*i2c_to_isl7998x(const struct i2c_client
*client
)
547 return sd_to_isl7998x(i2c_get_clientdata(client
));
550 static unsigned int isl7998x_norm_to_val(v4l2_std_id norm
)
554 for (i
= 0; i
< ARRAY_SIZE(isl7998x_std_res
); i
++)
555 if (isl7998x_std_res
[i
].norm
& norm
)
557 if (i
== ARRAY_SIZE(isl7998x_std_res
))
558 return ISL7998X_REG_PX_DEC_SDT_STANDARD_UNKNOWN
;
560 return isl7998x_std_res
[i
].id
;
563 static const struct isl7998x_mode
*isl7998x_norm_to_mode(v4l2_std_id norm
)
567 for (i
= 0; i
< ARRAY_SIZE(isl7998x_std_res
); i
++)
568 if (isl7998x_std_res
[i
].norm
& norm
)
570 /* Use NTSC default resolution during standard detection */
571 if (i
== ARRAY_SIZE(isl7998x_std_res
))
572 return &supported_modes
[1];
574 return isl7998x_std_res
[i
].mode
;
577 static int isl7998x_get_nr_inputs(struct device_node
*of_node
)
579 struct device_node
*port
;
580 unsigned int inputs
= 0;
583 if (of_graph_get_endpoint_count(of_node
) > ISL7998X_NUM_PADS
)
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.
591 for (i
= ISL7998X_PAD_VIN1
; i
<= ISL7998X_PAD_VIN4
; i
++) {
592 port
= of_graph_get_port_by_id(of_node
, i
);
601 case BIT(ISL7998X_PAD_VIN1
):
603 case BIT(ISL7998X_PAD_VIN1
) | BIT(ISL7998X_PAD_VIN2
):
605 case BIT(ISL7998X_PAD_VIN1
) | BIT(ISL7998X_PAD_VIN2
) |
606 BIT(ISL7998X_PAD_VIN3
) | BIT(ISL7998X_PAD_VIN4
):
613 static int isl7998x_wait_power_on(struct isl7998x
*isl7998x
)
615 struct device
*dev
= isl7998x
->subdev
.dev
;
620 ret
= read_poll_timeout(regmap_read
, err
, !err
, 2000, 20000, false,
622 ISL7998X_REG_P0_PRODUCT_ID_CODE
, &chip_id
);
624 dev_err(dev
, "timeout while waiting for ISL7998X\n");
628 dev_dbg(dev
, "Found ISL799%x\n", chip_id
);
633 static int isl7998x_set_standard(struct isl7998x
*isl7998x
, v4l2_std_id norm
)
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
;
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
,
650 ret
= regmap_write(isl7998x
->regmap
,
651 ISL7998X_REG_P5_LI_ENGINE_LINE_CTL
,
652 0x20 | ((width
>> 7) & 0x1f));
656 ret
= regmap_write(isl7998x
->regmap
,
657 ISL7998X_REG_P5_LI_ENGINE_PIC_WIDTH
,
658 (width
<< 1) & 0xff);
665 static int isl7998x_init(struct isl7998x
*isl7998x
)
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 },
677 struct device
*dev
= isl7998x
->subdev
.dev
;
678 struct regmap
*regmap
= isl7998x
->regmap
;
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
));
685 ret
= regmap_register_patch(regmap
, isl7998x_init_seq_1
,
686 ARRAY_SIZE(isl7998x_init_seq_1
));
690 mutex_lock(&isl7998x
->lock
);
691 ret
= isl7998x_set_standard(isl7998x
, isl7998x
->norm
);
692 mutex_unlock(&isl7998x
->lock
);
696 ret
= regmap_register_patch(regmap
, isl7998x_init_seq_custom
,
697 ARRAY_SIZE(isl7998x_init_seq_custom
));
701 return regmap_register_patch(regmap
, isl7998x_init_seq_2
,
702 ARRAY_SIZE(isl7998x_init_seq_2
));
705 static int isl7998x_set_test_pattern(struct isl7998x
*isl7998x
)
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 }
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) }
720 struct device
*dev
= isl7998x
->subdev
.dev
;
721 struct regmap
*regmap
= isl7998x
->regmap
;
724 if (pm_runtime_get_if_in_use(dev
) <= 0)
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
));
735 ret
= regmap_register_patch(regmap
, isl7998x_init_seq_tpg_off
,
736 ARRAY_SIZE(isl7998x_init_seq_tpg_off
));
744 #ifdef CONFIG_VIDEO_ADV_DEBUG
745 static int isl7998x_g_register(struct v4l2_subdev
*sd
,
746 struct v4l2_dbg_register
*reg
)
748 struct isl7998x
*isl7998x
= sd_to_isl7998x(sd
);
752 ret
= regmap_read(isl7998x
->regmap
, reg
->reg
, &val
);
762 static int isl7998x_s_register(struct v4l2_subdev
*sd
,
763 const struct v4l2_dbg_register
*reg
)
765 struct isl7998x
*isl7998x
= sd_to_isl7998x(sd
);
767 return regmap_write(isl7998x
->regmap
, reg
->reg
, reg
->val
);
771 static int isl7998x_g_std(struct v4l2_subdev
*sd
, v4l2_std_id
*norm
)
773 struct isl7998x
*isl7998x
= sd_to_isl7998x(sd
);
775 mutex_lock(&isl7998x
->lock
);
776 *norm
= isl7998x
->norm
;
777 mutex_unlock(&isl7998x
->lock
);
782 static int isl7998x_s_std(struct v4l2_subdev
*sd
, v4l2_std_id norm
)
784 struct isl7998x
*isl7998x
= sd_to_isl7998x(sd
);
785 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
786 struct device
*dev
= &client
->dev
;
789 mutex_lock(&isl7998x
->lock
);
790 if (isl7998x
->enabled
) {
792 mutex_unlock(&isl7998x
->lock
);
795 isl7998x
->norm
= norm
;
796 mutex_unlock(&isl7998x
->lock
);
798 if (pm_runtime_get_if_in_use(dev
) <= 0)
801 ret
= isl7998x_set_standard(isl7998x
, norm
);
808 static int isl7998x_querystd(struct v4l2_subdev
*sd
, v4l2_std_id
*std
)
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
];
818 ret
= pm_runtime_resume_and_get(dev
);
822 dev_dbg(dev
, "starting video standard detection\n");
824 mutex_lock(&isl7998x
->lock
);
825 if (isl7998x
->enabled
) {
830 ret
= isl7998x_set_standard(isl7998x
, V4L2_STD_UNKNOWN
);
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
);
842 for (i
= 0; i
< ISL7998X_INPUTS
; i
++) {
843 ret
= regmap_read_poll_timeout(isl7998x
->regmap
,
844 ISL7998X_REG_PX_DEC_SDT(i
+ 1),
846 !(reg
& ISL7998X_REG_PX_DEC_SDT_DET
),
847 2000, 500 * USEC_PER_MSEC
);
850 std_id
[i
] = FIELD_GET(ISL7998X_REG_PX_DEC_SDT_NOW
, reg
);
854 * According to Renesas FAE, all input cameras must have the
855 * same standard on this chip.
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
])
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
));
867 *std
= isl7998x_std_res
[std_id
[0]].norm
;
870 isl7998x_set_standard(isl7998x
, isl7998x
->norm
);
872 mutex_unlock(&isl7998x
->lock
);
878 static int isl7998x_g_tvnorms(struct v4l2_subdev
*sd
, v4l2_std_id
*std
)
885 static int isl7998x_g_input_status(struct v4l2_subdev
*sd
, u32
*status
)
887 struct isl7998x
*isl7998x
= sd_to_isl7998x(sd
);
888 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
889 struct device
*dev
= &client
->dev
;
894 if (!pm_runtime_active(dev
)) {
895 *status
|= V4L2_IN_ST_NO_POWER
;
899 for (i
= 0; i
< isl7998x
->nr_inputs
; i
++) {
900 ret
= regmap_read(isl7998x
->regmap
,
901 ISL7998X_REG_PX_DEC_STATUS_1(i
+ 1), ®
);
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
;
915 static int isl7998x_s_stream(struct v4l2_subdev
*sd
, int enable
)
917 struct isl7998x
*isl7998x
= sd_to_isl7998x(sd
);
918 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
919 struct device
*dev
= &client
->dev
;
923 dev_dbg(dev
, "stream %s\n", enable
? "ON" : "OFF");
925 mutex_lock(&isl7998x
->lock
);
926 if (isl7998x
->enabled
== enable
)
928 isl7998x
->enabled
= enable
;
931 ret
= isl7998x_set_test_pattern(isl7998x
);
936 regmap_read(isl7998x
->regmap
,
937 ISL7998X_REG_P5_LI_ENGINE_CTL
, ®
);
942 ret
= regmap_write(isl7998x
->regmap
,
943 ISL7998X_REG_P5_LI_ENGINE_CTL
, reg
);
946 mutex_unlock(&isl7998x
->lock
);
951 static int isl7998x_pre_streamon(struct v4l2_subdev
*sd
, u32 flags
)
953 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
954 struct device
*dev
= &client
->dev
;
956 return pm_runtime_resume_and_get(dev
);
959 static int isl7998x_post_streamoff(struct v4l2_subdev
*sd
)
961 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
962 struct device
*dev
= &client
->dev
;
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
)
973 if (code
->index
>= ARRAY_SIZE(isl7998x_colour_fmts
))
976 code
->code
= isl7998x_colour_fmts
[code
->index
].code
;
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
)
985 if (fse
->index
>= ARRAY_SIZE(supported_modes
))
988 if (fse
->code
!= isl7998x_colour_fmts
[0].code
)
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
;
999 static int isl7998x_get_fmt(struct v4l2_subdev
*sd
,
1000 struct v4l2_subdev_state
*sd_state
,
1001 struct v4l2_subdev_format
*format
)
1003 struct isl7998x
*isl7998x
= sd_to_isl7998x(sd
);
1004 struct v4l2_mbus_framefmt
*mf
= &format
->format
;
1005 const struct isl7998x_mode
*mode
;
1007 mutex_lock(&isl7998x
->lock
);
1009 if (format
->which
== V4L2_SUBDEV_FORMAT_TRY
) {
1010 format
->format
= *v4l2_subdev_state_get_format(sd_state
,
1015 mode
= isl7998x_norm_to_mode(isl7998x
->norm
);
1017 mf
->width
= mode
->width
;
1018 mf
->height
= mode
->height
;
1019 mf
->code
= isl7998x
->fmt
->code
;
1020 mf
->field
= mode
->field
;
1024 mutex_unlock(&isl7998x
->lock
);
1029 static int isl7998x_set_fmt(struct v4l2_subdev
*sd
,
1030 struct v4l2_subdev_state
*sd_state
,
1031 struct v4l2_subdev_format
*format
)
1033 struct isl7998x
*isl7998x
= sd_to_isl7998x(sd
);
1034 struct v4l2_mbus_framefmt
*mf
= &format
->format
;
1035 const struct isl7998x_mode
*mode
;
1037 mutex_lock(&isl7998x
->lock
);
1039 mode
= isl7998x_norm_to_mode(isl7998x
->norm
);
1041 mf
->width
= mode
->width
;
1042 mf
->height
= mode
->height
;
1043 mf
->code
= isl7998x
->fmt
->code
;
1044 mf
->field
= mode
->field
;
1046 if (format
->which
== V4L2_SUBDEV_FORMAT_TRY
)
1047 *v4l2_subdev_state_get_format(sd_state
, format
->pad
) = format
->format
;
1049 mutex_unlock(&isl7998x
->lock
);
1054 static int isl7998x_set_ctrl(struct v4l2_ctrl
*ctrl
)
1056 struct isl7998x
*isl7998x
= container_of(ctrl
->handler
,
1057 struct isl7998x
, ctrl_handler
);
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
);
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
);
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
);
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
);
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
,
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
,
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
,
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
,
1121 static const struct media_entity_operations isl7998x_entity_ops
= {
1122 .link_validate
= v4l2_subdev_link_validate
,
1125 static const struct v4l2_ctrl_ops isl7998x_ctrl_ops
= {
1126 .s_ctrl
= isl7998x_set_ctrl
,
1129 static const struct v4l2_ctrl_config isl7998x_ctrls
[] = {
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,
1137 .qmenu
= isl7998x_test_pattern_bars
,
1139 .ops
= &isl7998x_ctrl_ops
,
1140 .id
= V4L2_CID_TEST_PATTERN_CHANNELS
,
1141 .type
= V4L2_CTRL_TYPE_INTEGER
,
1142 .name
= "Test Pattern Channels",
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,
1155 .qmenu
= isl7998x_test_pattern_colors
,
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)), \
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))
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)), \
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))
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)), \
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))
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)),
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),
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)),
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)),
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),
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)),
1282 ISL7998X_REG_DECODER_ACA_WRITEABLE_RANGE(0xf),
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
),
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),
1301 regmap_reg_range(ISL7998X_REG_P5_AUTO_TEST_ERR_DET
,
1302 ISL7998X_REG_P5_PIC_HEIGHT_LOW
),
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
),
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
),
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
),
1320 static const struct regmap_range_cfg isl7998x_ranges
[] = {
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
,
1331 static const struct regmap_config isl7998x_regmap
= {
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_MAPLE
,
1343 static int isl7998x_mc_init(struct isl7998x
*isl7998x
)
1347 isl7998x
->subdev
.entity
.ops
= &isl7998x_entity_ops
;
1348 isl7998x
->subdev
.entity
.function
= MEDIA_ENT_F_VID_IF_BRIDGE
;
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
;
1354 return media_entity_pads_init(&isl7998x
->subdev
.entity
,
1359 static int get_link_freq_menu_index(unsigned int lanes
,
1360 unsigned int inputs
)
1386 static void isl7998x_remove_controls(struct isl7998x
*isl7998x
)
1388 v4l2_ctrl_handler_free(&isl7998x
->ctrl_handler
);
1389 mutex_destroy(&isl7998x
->ctrl_mutex
);
1392 static int isl7998x_init_controls(struct isl7998x
*isl7998x
)
1394 struct v4l2_subdev
*sd
= &isl7998x
->subdev
;
1395 int link_freq_index
;
1399 ret
= v4l2_ctrl_handler_init(&isl7998x
->ctrl_handler
,
1400 2 + ARRAY_SIZE(isl7998x_ctrls
));
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
)) {
1411 "failed to find MIPI link freq: %d lanes, %d inputs\n",
1412 isl7998x
->nr_mipi_lanes
, isl7998x
->nr_inputs
);
1417 isl7998x
->link_freq
= v4l2_ctrl_new_int_menu(&isl7998x
->ctrl_handler
,
1420 ARRAY_SIZE(link_freq_menu_items
) - 1,
1422 link_freq_menu_items
);
1423 if (isl7998x
->link_freq
)
1424 isl7998x
->link_freq
->flags
|= V4L2_CTRL_FLAG_READ_ONLY
;
1426 for (i
= 0; i
< ARRAY_SIZE(isl7998x_ctrls
); i
++)
1427 v4l2_ctrl_new_custom(&isl7998x
->ctrl_handler
,
1428 &isl7998x_ctrls
[i
], NULL
);
1430 v4l2_ctrl_new_std_menu_items(&isl7998x
->ctrl_handler
,
1432 V4L2_CID_TEST_PATTERN
,
1433 ARRAY_SIZE(isl7998x_test_pattern_menu
) - 1,
1434 0, 0, isl7998x_test_pattern_menu
);
1436 ret
= isl7998x
->ctrl_handler
.error
;
1440 isl7998x
->subdev
.ctrl_handler
= &isl7998x
->ctrl_handler
;
1441 v4l2_ctrl_handler_setup(&isl7998x
->ctrl_handler
);
1446 isl7998x_remove_controls(isl7998x
);
1451 static int isl7998x_probe(struct i2c_client
*client
)
1453 struct device
*dev
= &client
->dev
;
1454 struct v4l2_fwnode_endpoint endpoint
= {
1455 .bus_type
= V4L2_MBUS_CSI2_DPHY
,
1457 struct fwnode_handle
*ep
;
1458 struct isl7998x
*isl7998x
;
1459 struct i2c_adapter
*adapter
= to_i2c_adapter(client
->dev
.parent
);
1463 ret
= i2c_check_functionality(adapter
, I2C_FUNC_SMBUS_WORD_DATA
);
1465 dev_warn(&adapter
->dev
,
1466 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
1470 isl7998x
= devm_kzalloc(dev
, sizeof(*isl7998x
), GFP_KERNEL
);
1474 isl7998x
->pd_gpio
= devm_gpiod_get_optional(dev
, "powerdown",
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");
1480 isl7998x
->rstb_gpio
= devm_gpiod_get_optional(dev
, "reset",
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");
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");
1491 ep
= fwnode_graph_get_endpoint_by_id(dev_fwnode(dev
),
1492 ISL7998X_PAD_OUT
, 0, 0);
1494 return dev_err_probe(dev
, -EINVAL
, "Missing endpoint node\n");
1496 ret
= v4l2_fwnode_endpoint_parse(ep
, &endpoint
);
1497 fwnode_handle_put(ep
);
1499 return dev_err_probe(dev
, ret
, "Failed to parse endpoint\n");
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");
1506 isl7998x
->nr_mipi_lanes
= endpoint
.bus
.mipi_csi2
.num_data_lanes
;
1508 nr_inputs
= isl7998x_get_nr_inputs(dev
->of_node
);
1510 return dev_err_probe(dev
, nr_inputs
,
1511 "Invalid number of input ports\n");
1512 isl7998x
->nr_inputs
= nr_inputs
;
1514 v4l2_i2c_subdev_init(&isl7998x
->subdev
, client
, &isl7998x_subdev_ops
);
1515 isl7998x
->subdev
.flags
|= V4L2_SUBDEV_FL_HAS_DEVNODE
;
1517 ret
= isl7998x_mc_init(isl7998x
);
1521 isl7998x
->fmt
= &isl7998x_colour_fmts
[0];
1522 isl7998x
->norm
= V4L2_STD_NTSC
;
1523 isl7998x
->enabled
= 0;
1525 mutex_init(&isl7998x
->lock
);
1527 ret
= isl7998x_init_controls(isl7998x
);
1529 goto err_entity_cleanup
;
1531 ret
= v4l2_async_register_subdev(&isl7998x
->subdev
);
1533 goto err_controls_cleanup
;
1535 pm_runtime_enable(dev
);
1539 err_controls_cleanup
:
1540 isl7998x_remove_controls(isl7998x
);
1542 media_entity_cleanup(&isl7998x
->subdev
.entity
);
1547 static void isl7998x_remove(struct i2c_client
*client
)
1549 struct isl7998x
*isl7998x
= i2c_to_isl7998x(client
);
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
);
1557 static const struct of_device_id isl7998x_of_match
[] = {
1558 { .compatible
= "isil,isl79987", },
1561 MODULE_DEVICE_TABLE(of
, isl7998x_of_match
);
1563 static const struct i2c_device_id isl7998x_id
[] = {
1567 MODULE_DEVICE_TABLE(i2c
, isl7998x_id
);
1569 static int __maybe_unused
isl7998x_runtime_resume(struct device
*dev
)
1571 struct v4l2_subdev
*sd
= dev_get_drvdata(dev
);
1572 struct isl7998x
*isl7998x
= sd_to_isl7998x(sd
);
1575 gpiod_set_value(isl7998x
->rstb_gpio
, 1);
1576 gpiod_set_value(isl7998x
->pd_gpio
, 0);
1577 gpiod_set_value(isl7998x
->rstb_gpio
, 0);
1579 ret
= isl7998x_wait_power_on(isl7998x
);
1583 ret
= isl7998x_init(isl7998x
);
1590 gpiod_set_value(isl7998x
->pd_gpio
, 1);
1595 static int __maybe_unused
isl7998x_runtime_suspend(struct device
*dev
)
1597 struct v4l2_subdev
*sd
= dev_get_drvdata(dev
);
1598 struct isl7998x
*isl7998x
= sd_to_isl7998x(sd
);
1600 gpiod_set_value(isl7998x
->pd_gpio
, 1);
1605 static const struct dev_pm_ops isl7998x_pm_ops
= {
1606 SET_RUNTIME_PM_OPS(isl7998x_runtime_suspend
,
1607 isl7998x_runtime_resume
,
1611 static struct i2c_driver isl7998x_i2c_driver
= {
1614 .of_match_table
= isl7998x_of_match
,
1615 .pm
= &isl7998x_pm_ops
,
1617 .probe
= isl7998x_probe
,
1618 .remove
= isl7998x_remove
,
1619 .id_table
= isl7998x_id
,
1622 module_i2c_driver(isl7998x_i2c_driver
);
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");