xref: /rk3399_rockchip-uboot/drivers/video/drm/sii902x.c (revision e63a27f7a96beae2cdcc4ca813c8b95c07c7d2e6)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2024 Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <i2c.h>
10 #include <video_bridge.h>
11 #include <linux/delay.h>
12 #include <linux/iopoll.h>
13 #include <linux/media-bus-format.h>
14 #include <linux/hdmi.h>
15 
16 #include "rockchip_bridge.h"
17 #include "rockchip_display.h"
18 #include "rockchip_panel.h"
19 
20 #define SII902X_TPI_VIDEO_DATA			0x0
21 
22 #define SII902X_TPI_PIXEL_REPETITION		0x8
23 #define SII902X_TPI_AVI_PIXEL_REP_BUS_24BIT     BIT(5)
24 #define SII902X_TPI_AVI_PIXEL_REP_RISING_EDGE   BIT(4)
25 #define SII902X_TPI_AVI_PIXEL_REP_4X		3
26 #define SII902X_TPI_AVI_PIXEL_REP_2X		1
27 #define SII902X_TPI_AVI_PIXEL_REP_NONE		0
28 #define SII902X_TPI_CLK_RATIO_HALF		(0 << 6)
29 #define SII902X_TPI_CLK_RATIO_1X		(1 << 6)
30 #define SII902X_TPI_CLK_RATIO_2X		(2 << 6)
31 #define SII902X_TPI_CLK_RATIO_4X		(3 << 6)
32 
33 #define SII902X_TPI_AVI_IN_FORMAT		0x9
34 #define SII902X_TPI_AVI_INPUT_BITMODE_12BIT	BIT(7)
35 #define SII902X_TPI_AVI_INPUT_DITHER		BIT(6)
36 #define SII902X_TPI_AVI_INPUT_RANGE_LIMITED	(2 << 2)
37 #define SII902X_TPI_AVI_INPUT_RANGE_FULL	(1 << 2)
38 #define SII902X_TPI_AVI_INPUT_RANGE_AUTO	(0 << 2)
39 #define SII902X_TPI_AVI_INPUT_COLORSPACE_BLACK	(3 << 0)
40 #define SII902X_TPI_AVI_INPUT_COLORSPACE_YUV422	(2 << 0)
41 #define SII902X_TPI_AVI_INPUT_COLORSPACE_YUV444	(1 << 0)
42 #define SII902X_TPI_AVI_INPUT_COLORSPACE_RGB	(0 << 0)
43 
44 #define SII902X_TPI_AVI_INFOFRAME		0x0c
45 
46 #define SII902X_SYS_CTRL_DATA			0x1a
47 #define SII902X_SYS_CTRL_PWR_DWN		BIT(4)
48 #define SII902X_SYS_CTRL_AV_MUTE		BIT(3)
49 #define SII902X_SYS_CTRL_DDC_BUS_REQ		BIT(2)
50 #define SII902X_SYS_CTRL_DDC_BUS_GRTD		BIT(1)
51 #define SII902X_SYS_CTRL_OUTPUT_MODE		BIT(0)
52 #define SII902X_SYS_CTRL_OUTPUT_HDMI		1
53 #define SII902X_SYS_CTRL_OUTPUT_DVI		0
54 
55 #define SII902X_REG_CHIPID(n)			(0x1b + (n))
56 
57 #define SII902X_PWR_STATE_CTRL			0x1e
58 #define SII902X_AVI_POWER_STATE_MSK		GENMASK(1, 0)
59 #define SII902X_AVI_POWER_STATE_D(l)		((l) & SII902X_AVI_POWER_STATE_MSK)
60 
61 /* Audio  */
62 #define SII902X_TPI_I2S_ENABLE_MAPPING_REG	0x1f
63 #define SII902X_TPI_I2S_CONFIG_FIFO0		(0 << 0)
64 #define SII902X_TPI_I2S_CONFIG_FIFO1		(1 << 0)
65 #define SII902X_TPI_I2S_CONFIG_FIFO2		(2 << 0)
66 #define SII902X_TPI_I2S_CONFIG_FIFO3		(3 << 0)
67 #define SII902X_TPI_I2S_LEFT_RIGHT_SWAP		(1 << 2)
68 #define SII902X_TPI_I2S_AUTO_DOWNSAMPLE		(1 << 3)
69 #define SII902X_TPI_I2S_SELECT_SD0		(0 << 4)
70 #define SII902X_TPI_I2S_SELECT_SD1		(1 << 4)
71 #define SII902X_TPI_I2S_SELECT_SD2		(2 << 4)
72 #define SII902X_TPI_I2S_SELECT_SD3		(3 << 4)
73 #define SII902X_TPI_I2S_FIFO_ENABLE		(1 << 7)
74 
75 #define SII902X_TPI_I2S_INPUT_CONFIG_REG	0x20
76 #define SII902X_TPI_I2S_FIRST_BIT_SHIFT_YES	(0 << 0)
77 #define SII902X_TPI_I2S_FIRST_BIT_SHIFT_NO	(1 << 0)
78 #define SII902X_TPI_I2S_SD_DIRECTION_MSB_FIRST	(0 << 1)
79 #define SII902X_TPI_I2S_SD_DIRECTION_LSB_FIRST	(1 << 1)
80 #define SII902X_TPI_I2S_SD_JUSTIFY_LEFT		(0 << 2)
81 #define SII902X_TPI_I2S_SD_JUSTIFY_RIGHT	(1 << 2)
82 #define SII902X_TPI_I2S_WS_POLARITY_LOW		(0 << 3)
83 #define SII902X_TPI_I2S_WS_POLARITY_HIGH	(1 << 3)
84 #define SII902X_TPI_I2S_MCLK_MULTIPLIER_128	(0 << 4)
85 #define SII902X_TPI_I2S_MCLK_MULTIPLIER_256	(1 << 4)
86 #define SII902X_TPI_I2S_MCLK_MULTIPLIER_384	(2 << 4)
87 #define SII902X_TPI_I2S_MCLK_MULTIPLIER_512	(3 << 4)
88 #define SII902X_TPI_I2S_MCLK_MULTIPLIER_768	(4 << 4)
89 #define SII902X_TPI_I2S_MCLK_MULTIPLIER_1024	(5 << 4)
90 #define SII902X_TPI_I2S_MCLK_MULTIPLIER_1152	(6 << 4)
91 #define SII902X_TPI_I2S_MCLK_MULTIPLIER_192	(7 << 4)
92 #define SII902X_TPI_I2S_SCK_EDGE_FALLING	(0 << 7)
93 #define SII902X_TPI_I2S_SCK_EDGE_RISING		(1 << 7)
94 
95 #define SII902X_TPI_I2S_STRM_HDR_BASE		0x21
96 #define SII902X_TPI_I2S_STRM_HDR_SIZE		5
97 
98 #define SII902X_TPI_AUDIO_CONFIG_BYTE2_REG	0x26
99 #define SII902X_TPI_AUDIO_CODING_STREAM_HEADER	(0 << 0)
100 #define SII902X_TPI_AUDIO_CODING_PCM		(1 << 0)
101 #define SII902X_TPI_AUDIO_CODING_AC3		(2 << 0)
102 #define SII902X_TPI_AUDIO_CODING_MPEG1		(3 << 0)
103 #define SII902X_TPI_AUDIO_CODING_MP3		(4 << 0)
104 #define SII902X_TPI_AUDIO_CODING_MPEG2		(5 << 0)
105 #define SII902X_TPI_AUDIO_CODING_AAC		(6 << 0)
106 #define SII902X_TPI_AUDIO_CODING_DTS		(7 << 0)
107 #define SII902X_TPI_AUDIO_CODING_ATRAC		(8 << 0)
108 #define SII902X_TPI_AUDIO_MUTE_DISABLE		(0 << 4)
109 #define SII902X_TPI_AUDIO_MUTE_ENABLE		(1 << 4)
110 #define SII902X_TPI_AUDIO_LAYOUT_2_CHANNELS	(0 << 5)
111 #define SII902X_TPI_AUDIO_LAYOUT_8_CHANNELS	(1 << 5)
112 #define SII902X_TPI_AUDIO_INTERFACE_DISABLE	(0 << 6)
113 #define SII902X_TPI_AUDIO_INTERFACE_SPDIF	(1 << 6)
114 #define SII902X_TPI_AUDIO_INTERFACE_I2S		(2 << 6)
115 
116 #define SII902X_TPI_AUDIO_CONFIG_BYTE3_REG	0x27
117 #define SII902X_TPI_AUDIO_FREQ_STREAM		(0 << 3)
118 #define SII902X_TPI_AUDIO_FREQ_32KHZ		(1 << 3)
119 #define SII902X_TPI_AUDIO_FREQ_44KHZ		(2 << 3)
120 #define SII902X_TPI_AUDIO_FREQ_48KHZ		(3 << 3)
121 #define SII902X_TPI_AUDIO_FREQ_88KHZ		(4 << 3)
122 #define SII902X_TPI_AUDIO_FREQ_96KHZ		(5 << 3)
123 #define SII902X_TPI_AUDIO_FREQ_176KHZ		(6 << 3)
124 #define SII902X_TPI_AUDIO_FREQ_192KHZ		(7 << 3)
125 #define SII902X_TPI_AUDIO_SAMPLE_SIZE_STREAM	(0 << 6)
126 #define SII902X_TPI_AUDIO_SAMPLE_SIZE_16	(1 << 6)
127 #define SII902X_TPI_AUDIO_SAMPLE_SIZE_20	(2 << 6)
128 #define SII902X_TPI_AUDIO_SAMPLE_SIZE_24	(3 << 6)
129 
130 #define SII902X_TPI_AUDIO_CONFIG_BYTE4_REG	0x28
131 
132 #define SII902X_INT_ENABLE			0x3c
133 #define SII902X_INT_STATUS			0x3d
134 #define SII902X_HOTPLUG_EVENT			BIT(0)
135 #define SII902X_PLUGGED_STATUS			BIT(2)
136 
137 #define SII902X_TPI_SYNC_GEN_CTRL		0x60
138 #define SII902X_TPI_SYNC_POLAR_DETECT		0x61
139 #define SII902X_TPI_HBIT_TO_HSYNC		0x62
140 #define SII902X_EMBEDDED_SYNC_EXTRACTION_REG	0x63
141 #define SII902X_EMBEDDED_SYNC_EXTRACTION	BIT(6)
142 
143 #define SII902X_REG_TPI_RQB			0xc7
144 
145 /* Indirect internal register access */
146 #define SII902X_IND_SET_PAGE			0xbc
147 #define SII902X_IND_OFFSET			0xbd
148 #define SII902X_IND_VALUE			0xbe
149 
150 #define SII902X_TPI_MISC_INFOFRAME_BASE		0xbf
151 #define SII902X_TPI_MISC_INFOFRAME_END		0xde
152 #define SII902X_TPI_MISC_INFOFRAME_SIZE	\
153 	(SII902X_TPI_MISC_INFOFRAME_END - SII902X_TPI_MISC_INFOFRAME_BASE)
154 
155 #define SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS	500
156 
157 #define SII902X_AUDIO_PORT_INDEX		3
158 
159 struct sii902x {
160 	struct udevice *dev;
161 	struct udevice *power_supply;
162 	struct gpio_desc enable_gpio;
163 	struct gpio_desc reset_gpio;
164 	struct rockchip_bridge *bridge;
165 	struct drm_display_mode mode;
166 	struct ddc_adapter adap;
167 	struct hdmi_edid_data edid_data;
168 	int bus_format;
169 };
170 
171 enum sii902x_bus_format {
172 	FORMAT_RGB_INPUT,
173 	FORMAT_YCBCR422_INPUT,
174 	FORMAT_YCBCR444_INPUT,
175 };
176 
177 static inline struct sii902x *bridge_to_sii902x(struct rockchip_bridge *bridge)
178 {
179 	return container_of(&bridge, struct sii902x, bridge);
180 }
181 
182 static int sii902x_reg_update_bits(struct sii902x *sii902x, u8 reg, u8 mask, u8 val)
183 {
184 	u8 status;
185 
186 	status = dm_i2c_reg_read(sii902x->dev, reg);
187 	status &= ~mask;
188 	status |= val & mask;
189 
190 	return dm_i2c_reg_write(sii902x->dev, reg, status);
191 }
192 
193 static bool sii902x_bridge_detect(struct rockchip_bridge *bridge)
194 {
195 	struct udevice *dev = bridge->dev;
196 	u8 status;
197 
198 	status = dm_i2c_reg_read(dev, SII902X_INT_STATUS);
199 
200 	return (status & SII902X_PLUGGED_STATUS) ? true : false;
201 }
202 
203 static bool sii902x_check_embedded_format(uint32_t bus_format)
204 {
205 	switch (bus_format) {
206 	case MEDIA_BUS_FMT_YUYV8_2X8:
207 	case MEDIA_BUS_FMT_YVYU8_2X8:
208 	case MEDIA_BUS_FMT_UYVY8_2X8:
209 	case MEDIA_BUS_FMT_VYUY8_2X8:
210 	case MEDIA_BUS_FMT_YUYV8_1X16:
211 	case MEDIA_BUS_FMT_YVYU8_1X16:
212 	case MEDIA_BUS_FMT_UYVY8_1X16:
213 	case MEDIA_BUS_FMT_VYUY8_1X16:
214 		return true;
215 	default:
216 		return false;
217 	}
218 }
219 
220 static void sii902x_set_embedded_sync(struct sii902x *sii902x)
221 {
222 	struct udevice *dev = sii902x->dev;
223 	unsigned char data[8];
224 	struct videomode vm;
225 
226 	if (!sii902x_check_embedded_format(sii902x->bus_format))
227 		return;
228 
229 	switch (sii902x->bus_format) {
230 	case MEDIA_BUS_FMT_YUYV8_2X8:
231 	case MEDIA_BUS_FMT_YVYU8_2X8:
232 	case MEDIA_BUS_FMT_UYVY8_2X8:
233 	case MEDIA_BUS_FMT_VYUY8_2X8:
234 		sii902x_reg_update_bits(sii902x, SII902X_TPI_SYNC_GEN_CTRL, 0x20, 0x20);
235 		break;
236 	default:
237 		break;
238 	}
239 
240 	sii902x_reg_update_bits(sii902x,  SII902X_TPI_SYNC_GEN_CTRL, 0x80, 0x00);
241 	dm_i2c_reg_write(dev, SII902X_EMBEDDED_SYNC_EXTRACTION_REG, 0x00);
242 	sii902x_reg_update_bits(sii902x, SII902X_TPI_SYNC_GEN_CTRL, 0x80, 0x80);
243 
244 	drm_display_mode_to_videomode(&sii902x->mode, &vm);
245 	data[0] = vm.hfront_porch & 0xff;
246 	data[1] = (vm.hfront_porch >> 8) & 0x03;
247 	if (sii902x->mode.flags & DRM_MODE_FLAG_INTERLACE) {
248 		data[2] = (sii902x->mode.vtotal >> 1) & 0xff;
249 		data[3] = ((sii902x->mode.vtotal >> 1) >> 8) & 0x1f;
250 	} else {
251 		data[2] = 0;
252 		data[3] = 0;
253 	}
254 	data[4] = vm.hsync_len & 0xff;
255 	data[5] = (vm.hsync_len >> 8) & 0x03;
256 	data[6] = vm.vfront_porch;
257 	data[7] = vm.vsync_len;
258 	dm_i2c_write(dev, SII902X_TPI_HBIT_TO_HSYNC, data, 8);
259 
260 	sii902x_reg_update_bits(sii902x, SII902X_TPI_SYNC_GEN_CTRL, 0x80, 0x80);
261 	sii902x_reg_update_bits(sii902x, SII902X_EMBEDDED_SYNC_EXTRACTION_REG, 0x40, 0x40);
262 
263 	sii902x_reg_update_bits(sii902x, SII902X_EMBEDDED_SYNC_EXTRACTION_REG,
264 				SII902X_EMBEDDED_SYNC_EXTRACTION,
265 				SII902X_EMBEDDED_SYNC_EXTRACTION);
266 }
267 
268 static void sii902x_set_format(struct sii902x *sii902x)
269 {
270 	struct udevice *dev = sii902x->dev;
271 	u8 val;
272 
273 	switch (sii902x->bus_format) {
274 	case MEDIA_BUS_FMT_YUYV8_1X16:
275 	case MEDIA_BUS_FMT_YVYU8_1X16:
276 	case MEDIA_BUS_FMT_UYVY8_1X16:
277 	case MEDIA_BUS_FMT_VYUY8_1X16:
278 	case MEDIA_BUS_FMT_YUYV8_2X8:
279 	case MEDIA_BUS_FMT_YVYU8_2X8:
280 	case MEDIA_BUS_FMT_UYVY8_2X8:
281 	case MEDIA_BUS_FMT_VYUY8_2X8:
282 		val = SII902X_TPI_AVI_INPUT_COLORSPACE_YUV422;
283 		break;
284 	case MEDIA_BUS_FMT_YUV8_1X24:
285 	case MEDIA_BUS_FMT_VUY8_1X24:
286 		val = SII902X_TPI_AVI_INPUT_COLORSPACE_YUV444;
287 		break;
288 	case MEDIA_BUS_FMT_RGB888_1X24:
289 	default:
290 		val = SII902X_TPI_AVI_INPUT_COLORSPACE_RGB;
291 		break;
292 	}
293 
294 	val |= SII902X_TPI_AVI_INPUT_RANGE_AUTO;
295 	val &= ~(SII902X_TPI_AVI_INPUT_DITHER |
296 		 SII902X_TPI_AVI_INPUT_BITMODE_12BIT);
297 	dm_i2c_reg_write(dev, SII902X_TPI_AVI_IN_FORMAT, val);
298 
299 	sii902x_set_embedded_sync(sii902x);
300 }
301 
302 static void sii902x_set_connector_display_info(struct sii902x *sii902x,
303 					       struct connector_state *conn_state)
304 {
305 	conn_state->bus_format = sii902x->bus_format;
306 	switch (conn_state->bus_format) {
307 	case MEDIA_BUS_FMT_YUYV8_2X8:
308 	case MEDIA_BUS_FMT_YVYU8_2X8:
309 	case MEDIA_BUS_FMT_UYVY8_2X8:
310 	case MEDIA_BUS_FMT_VYUY8_2X8:
311 		conn_state->output_mode = ROCKCHIP_OUT_MODE_BT656;
312 		conn_state->output_if = VOP_OUTPUT_IF_BT656;
313 		conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
314 		conn_state->color_encoding = DRM_COLOR_YCBCR_BT601;
315 		break;
316 	case MEDIA_BUS_FMT_YUYV8_1X16:
317 	case MEDIA_BUS_FMT_YVYU8_1X16:
318 	case MEDIA_BUS_FMT_UYVY8_1X16:
319 	case MEDIA_BUS_FMT_VYUY8_1X16:
320 		conn_state->output_mode = ROCKCHIP_OUT_MODE_BT1120;
321 		conn_state->output_if = VOP_OUTPUT_IF_BT1120;
322 		conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
323 		conn_state->color_encoding = DRM_COLOR_YCBCR_BT709;
324 		break;
325 	case MEDIA_BUS_FMT_RGB888_1X24:
326 	default:
327 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
328 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
329 		conn_state->color_range = DRM_COLOR_YCBCR_FULL_RANGE;
330 		conn_state->color_encoding = DRM_COLOR_YCBCR_BT709;
331 		break;
332 	}
333 }
334 
335 static void sii902x_bridge_mode_set(struct rockchip_bridge *bridge,
336 				    const struct drm_display_mode *mode)
337 {
338 	struct sii902x *sii902x = dev_get_priv(bridge->dev);
339 	struct connector_state *conn_state = &bridge->state->conn_state;
340 	struct edid *edid = (struct edid *)conn_state->edid;
341 	struct udevice *dev = sii902x->dev;
342 	struct hdmi_avi_infoframe frame;
343 	u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
344 	u8 output_mode;
345 	u16 pixel_clock_10kHz = mode->clock / 10;
346 	int ret, vrefresh;
347 
348 	if (drm_detect_hdmi_monitor(edid))
349 		output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI;
350 	else
351 		output_mode = SII902X_SYS_CTRL_OUTPUT_DVI;
352 
353 	sii902x_reg_update_bits(sii902x, SII902X_SYS_CTRL_DATA,
354 				SII902X_SYS_CTRL_OUTPUT_MODE,
355 				output_mode);
356 
357 	drm_mode_copy(&sii902x->mode, mode);
358 	vrefresh = drm_mode_vrefresh(mode) * 100;
359 	buf[0] = pixel_clock_10kHz & 0xff;
360 	buf[1] = pixel_clock_10kHz >> 8;
361 	buf[2] = vrefresh & 0xff;
362 	buf[3] = vrefresh >> 8;
363 	buf[4] = mode->crtc_htotal;
364 	buf[5] = mode->crtc_htotal >> 8;
365 	buf[6] = mode->crtc_vtotal;
366 	buf[7] = mode->crtc_vtotal >> 8;
367 	buf[8] = SII902X_TPI_CLK_RATIO_1X | SII902X_TPI_AVI_PIXEL_REP_NONE |
368 		 SII902X_TPI_AVI_PIXEL_REP_BUS_24BIT;
369 	switch (sii902x->bus_format) {
370 	case MEDIA_BUS_FMT_YUYV8_1X16:
371 	case MEDIA_BUS_FMT_YVYU8_1X16:
372 	case MEDIA_BUS_FMT_UYVY8_1X16:
373 	case MEDIA_BUS_FMT_VYUY8_1X16:
374 	case MEDIA_BUS_FMT_YUYV8_2X8:
375 	case MEDIA_BUS_FMT_YVYU8_2X8:
376 	case MEDIA_BUS_FMT_UYVY8_2X8:
377 	case MEDIA_BUS_FMT_VYUY8_2X8:
378 		buf[8] |= SII902X_TPI_AVI_PIXEL_REP_RISING_EDGE;
379 		break;
380 	default:
381 		break;
382 	}
383 
384 	buf[9] = SII902X_TPI_AVI_INPUT_RANGE_AUTO;
385 	switch (sii902x->bus_format) {
386 	case MEDIA_BUS_FMT_YUYV8_1X16:
387 	case MEDIA_BUS_FMT_YVYU8_1X16:
388 	case MEDIA_BUS_FMT_UYVY8_1X16:
389 	case MEDIA_BUS_FMT_VYUY8_1X16:
390 	case MEDIA_BUS_FMT_YUYV8_2X8:
391 	case MEDIA_BUS_FMT_YVYU8_2X8:
392 	case MEDIA_BUS_FMT_UYVY8_2X8:
393 	case MEDIA_BUS_FMT_VYUY8_2X8:
394 		buf[9] |= SII902X_TPI_AVI_INPUT_COLORSPACE_YUV422;
395 		break;
396 	case MEDIA_BUS_FMT_YUV8_1X24:
397 	case MEDIA_BUS_FMT_VUY8_1X24:
398 		buf[9] |= SII902X_TPI_AVI_INPUT_COLORSPACE_YUV444;
399 		break;
400 	case MEDIA_BUS_FMT_RGB888_1X24:
401 	default:
402 		buf[9] |= SII902X_TPI_AVI_INPUT_COLORSPACE_RGB;
403 		break;
404 	}
405 
406 	ret = dm_i2c_write(dev, SII902X_TPI_VIDEO_DATA, buf, 10);
407 	if (ret) {
408 		dev_err(dev, "failed to set video data\n");
409 		return;
410 	}
411 
412 	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, &sii902x->mode, false);
413 	if (ret < 0) {
414 		dev_err(dev, "couldn't fill AVI infoframe\n");
415 		return;
416 	}
417 
418 	ret = hdmi_avi_infoframe_pack(&frame, buf, sizeof(buf));
419 	if (ret < 0) {
420 		dev_err(dev, "failed to pack AVI infoframe: %d\n", ret);
421 		return;
422 	}
423 
424 	/* Do not send the infoframe header, but keep the CRC field. */
425 	dm_i2c_write(dev, SII902X_TPI_AVI_INFOFRAME,
426 		     buf + HDMI_INFOFRAME_HEADER_SIZE - 1,
427 		     HDMI_AVI_INFOFRAME_SIZE + 1);
428 	sii902x_set_format(sii902x);
429 	sii902x_set_connector_display_info(sii902x, conn_state);
430 }
431 
432 static void sii902x_bridge_enable(struct rockchip_bridge *bridge)
433 {
434 	struct sii902x *sii902x = dev_get_priv(bridge->dev);
435 
436 	sii902x_reg_update_bits(sii902x, SII902X_PWR_STATE_CTRL,
437 				SII902X_AVI_POWER_STATE_MSK,
438 				SII902X_AVI_POWER_STATE_D(0));
439 	sii902x_reg_update_bits(sii902x, SII902X_SYS_CTRL_DATA, SII902X_SYS_CTRL_PWR_DWN, 0);
440 }
441 
442 static void sii902x_bridge_disable(struct rockchip_bridge *bridge)
443 {
444 	struct sii902x *sii902x = dev_get_priv(bridge->dev);
445 
446 	sii902x_reg_update_bits(sii902x, SII902X_SYS_CTRL_DATA,
447 				SII902X_SYS_CTRL_PWR_DWN,
448 				SII902X_SYS_CTRL_PWR_DWN);
449 }
450 
451 static const struct rockchip_bridge_funcs sii902x_bridge_funcs = {
452 	.detect		= sii902x_bridge_detect,
453 	.mode_set	= sii902x_bridge_mode_set,
454 	.enable		= sii902x_bridge_enable,
455 	.post_disable	= sii902x_bridge_disable,
456 };
457 
458 static void sii902x_reset(struct sii902x *sii902x)
459 {
460 	if (!dm_gpio_is_valid(&sii902x->reset_gpio))
461 		return;
462 
463 	dm_gpio_set_value(&sii902x->reset_gpio, 1);
464 
465 	/* The datasheet says treset-min = 100us. Make it 150us to be sure. */
466 	udelay(500);
467 
468 	dm_gpio_set_value(&sii902x->reset_gpio, 0);
469 }
470 
471 #define SII902X_READ_REG(v)	dm_i2c_reg_read(sii902x->dev, v)
472 
473 /*
474  * The purpose of sii902x_i2c_bypass_select is to enable the pass through
475  * mode of the HDMI transmitter. Do not use regmap from within this function,
476  * only use sii902x_*_unlocked functions to read/modify/write registers.
477  * We are holding the parent adapter lock here, keep this in mind before
478  * adding more i2c transactions.
479  *
480  * Also, since SII902X_SYS_CTRL_DATA is used with regmap_update_bits elsewhere
481  * in this driver, we need to make sure that we only touch 0x1A[2:1] from
482  * within sii902x_i2c_bypass_select and sii902x_i2c_bypass_deselect, and that
483  * we leave the remaining bits as we have found them.
484  */
485 static int sii902x_i2c_bypass_select(struct sii902x *sii902x)
486 {
487 	struct udevice *dev = sii902x->dev;
488 	u8 status;
489 	int ret;
490 
491 	sii902x_reg_update_bits(sii902x, SII902X_SYS_CTRL_DATA,
492 				SII902X_SYS_CTRL_DDC_BUS_REQ,
493 				SII902X_SYS_CTRL_DDC_BUS_REQ);
494 
495 	ret = readx_poll_timeout(SII902X_READ_REG, SII902X_SYS_CTRL_DATA, status,
496 				 status & SII902X_SYS_CTRL_DDC_BUS_GRTD,
497 				 SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS * 1000);
498 	if (ret) {
499 		dev_err(dev, "Failed to acquire the i2c bus\n");
500 		return -ETIMEDOUT;
501 	}
502 
503 	dm_i2c_reg_write(dev, SII902X_SYS_CTRL_DATA, status);
504 
505 	return 0;
506 }
507 
508 /*
509  * The purpose of sii902x_i2c_bypass_deselect is to disable the pass through
510  * mode of the HDMI transmitter. Do not use regmap from within this function,
511  * only use sii902x_*_unlocked functions to read/modify/write registers.
512  * We are holding the parent adapter lock here, keep this in mind before
513  * adding more i2c transactions.
514  *
515  * Also, since SII902X_SYS_CTRL_DATA is used with regmap_update_bits elsewhere
516  * in this driver, we need to make sure that we only touch 0x1A[2:1] from
517  * within sii902x_i2c_bypass_select and sii902x_i2c_bypass_deselect, and that
518  * we leave the remaining bits as we have found them.
519  */
520 static int sii902x_i2c_bypass_deselect(struct sii902x *sii902x)
521 {
522 	struct udevice *dev = sii902x->dev;
523 	unsigned int retries;
524 	u8 status;
525 	int ret;
526 
527 	/*
528 	 * When the HDMI transmitter is in pass through mode, we need an
529 	 * (undocumented) additional delay between STOP and START conditions
530 	 * to guarantee the bus won't get stuck.
531 	 */
532 	udelay(30);
533 
534 	/*
535 	 * Sometimes the I2C bus can stall after failure to use the
536 	 * EDID channel. Retry a few times to see if things clear
537 	 * up, else continue anyway.
538 	 */
539 	retries = 5;
540 	do {
541 		status = dm_i2c_reg_read(dev, SII902X_SYS_CTRL_DATA);
542 		retries--;
543 	} while (status < 0 && retries);
544 	if (status < 0) {
545 		dev_err(dev, "failed to read status (%d)\n", status);
546 		return status;
547 	}
548 
549 	ret = sii902x_reg_update_bits(sii902x, SII902X_SYS_CTRL_DATA,
550 				      SII902X_SYS_CTRL_DDC_BUS_REQ |
551 				      SII902X_SYS_CTRL_DDC_BUS_GRTD, 0);
552 	if (ret)
553 		return ret;
554 
555 	ret = readx_poll_timeout(SII902X_READ_REG, SII902X_SYS_CTRL_DATA, status,
556 				 !(status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
557 					     SII902X_SYS_CTRL_DDC_BUS_GRTD)),
558 				 SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS * 1000);
559 	if (ret) {
560 		dev_err(dev, "failed to release the i2c bus\n");
561 		return -ETIMEDOUT;
562 	}
563 
564 	return 0;
565 }
566 
567 static int sii902x_i2c_xfer(struct ddc_adapter *adap, struct i2c_msg *msgs, int num)
568 {
569 	struct sii902x *sii902x = container_of(adap, struct sii902x, adap);
570 	struct udevice *dev = sii902x->dev;
571 	u8 addr = msgs[0].addr;
572 	int i;
573 	int ret;
574 
575 	ret = sii902x_i2c_bypass_select(sii902x);
576 	if (ret)
577 		return -EINVAL;
578 
579 	debug("i2c xfer: num: %d, addr: %#x\n", num, addr);
580 
581 	for (i = 0; i < num; i++) {
582 		debug("xfer: num: %d/%d, len: %d, flags: %#x\n",
583 		      i + 1, num, msgs[i].len, msgs[i].flags);
584 
585 		ret = dm_i2c_xfer(dev, msgs, num);
586 		if (ret < 0)
587 			break;
588 	}
589 
590 	ret = sii902x_i2c_bypass_deselect(sii902x);
591 	if (ret)
592 		return -EINVAL;
593 
594 	if (!ret)
595 		ret = num;
596 
597 	return ret;
598 }
599 
600 static int sii902x_init(struct sii902x *sii902x)
601 {
602 	struct udevice *dev = sii902x->dev;
603 	u8 chipid[4];
604 	u8 status;
605 	int ret;
606 
607 	sii902x_reset(sii902x);
608 
609 	ret = dm_i2c_reg_write(dev, SII902X_REG_TPI_RQB, 0x0);
610 	if (ret) {
611 		dev_err(dev, "enable TPI mode failed %d\n", ret);
612 		return ret;
613 	}
614 
615 	ret = dm_i2c_read(dev, SII902X_REG_CHIPID(0), chipid, 4);
616 	if (ret) {
617 		dev_err(dev, "regmap_read failed %d\n", ret);
618 		return ret;
619 	}
620 
621 	if (chipid[0] != 0xb0) {
622 		dev_err(dev, "Invalid chipid: %02x (expecting 0xb0)\n",
623 			chipid[0]);
624 		return -EINVAL;
625 	}
626 
627 	/* Clear all pending interrupts */
628 	status = dm_i2c_reg_read(dev, SII902X_INT_STATUS);
629 	dm_i2c_reg_write(dev, SII902X_INT_STATUS, status);
630 
631 	sii902x->adap.i2c_bus = dev->parent;
632 	sii902x->adap.ddc_xfer = sii902x_i2c_xfer;
633 
634 	sii902x->edid_data.mode_buf = malloc(MODE_LEN * sizeof(struct drm_display_mode));
635 	if (!sii902x->edid_data.mode_buf) {
636 		dev_err(dev, "failed to malloc mode buffer for edid\n");
637 		return -ENOMEM;
638 	}
639 
640 	return 0;
641 }
642 
643 static int sii902x_probe(struct udevice *dev)
644 {
645 	struct sii902x *sii902x = dev_get_priv(dev);
646 	struct rockchip_bridge *bridge = (struct rockchip_bridge *)dev_get_driver_data(dev);
647 	int val;
648 	int ret;
649 
650 	sii902x->dev = dev;
651 	sii902x->bridge = bridge;
652 	bridge->dev = dev;
653 
654 	ret = gpio_request_by_name(dev, "reset-gpio", 0,
655 				   &sii902x->reset_gpio, GPIOD_IS_OUT);
656 	if (ret && ret != -ENOENT) {
657 		dev_err(dev, "Cannot get reset GPIO: %d\n", ret);
658 		return ret;
659 	}
660 
661 	ret = gpio_request_by_name(dev, "enable-gpio", 0,
662 				   &sii902x->enable_gpio, GPIOD_IS_OUT);
663 	if (ret && ret != -ENOENT) {
664 		dev_err(dev, "Cannot get enable GPIO: %d\n", ret);
665 		return ret;
666 	} else {
667 		dm_gpio_set_value(&sii902x->enable_gpio, 1);
668 		udelay(2000);
669 	}
670 
671 	val = ofnode_read_u32_default(dev->node, "bus-format", -1);
672 	if (val < 0) {
673 		sii902x->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
674 	} else {
675 		switch (val) {
676 		case FORMAT_RGB_INPUT:
677 			sii902x->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
678 			break;
679 		case FORMAT_YCBCR422_INPUT:
680 			sii902x->bus_format = MEDIA_BUS_FMT_YUYV8_1X16;
681 			break;
682 		case FORMAT_YCBCR444_INPUT:
683 			sii902x->bus_format = MEDIA_BUS_FMT_YUV8_1X24;
684 			break;
685 		default:
686 			sii902x->bus_format = val;
687 			break;
688 		}
689 	}
690 
691 	ret = sii902x_init(sii902x);
692 	if (ret < 0) {
693 		dev_err(dev, "Failed to init sii902x %d\n", ret);
694 		return ret;
695 	}
696 
697 	printf("sii902x init successfully\n");
698 
699 	return 0;
700 }
701 
702 static struct rockchip_bridge sii902x_driver_data = {
703 	.funcs = &sii902x_bridge_funcs,
704 };
705 
706 static const struct udevice_id sii902x_of_match[] = {
707 	{
708 		.compatible = "sil,sii9022",
709 		.data = (ulong)&sii902x_driver_data,
710 	},
711 	{}
712 };
713 
714 static int sii902x_get_timing(struct udevice *dev)
715 {
716 	struct sii902x *sii902x = dev_get_priv(dev);
717 	struct rockchip_bridge *bridge = sii902x->bridge;
718 	struct display_state *state = bridge->state;
719 	struct connector_state *conn_state = &state->conn_state;
720 	struct drm_display_mode *mode = &conn_state->mode;
721 	int ret;
722 
723 	ret = drm_do_get_edid(&sii902x->adap, conn_state->edid);
724 	if (!ret) {
725 		ret = drm_add_edid_modes(&sii902x->edid_data, conn_state->edid);
726 	}
727 	if (ret < 0) {
728 		dev_err(dev, "Failed to get edid %d\n", ret);
729 		return ret;
730 	}
731 
732 	drm_mode_max_resolution_filter(&sii902x->edid_data, &state->crtc_state.max_output);
733 	if (!drm_mode_prune_invalid(&sii902x->edid_data)) {
734 		dev_err(dev, "Failed to find valid display mode\n");
735 		return -EINVAL;
736 	}
737 
738 	drm_mode_sort(&sii902x->edid_data);
739 	*mode = *sii902x->edid_data.preferred_mode;
740 
741 	return 0;
742 }
743 
744 struct video_bridge_ops sii902x_ops = {
745 	.get_timing = sii902x_get_timing,
746 };
747 
748 U_BOOT_DRIVER(sii902x) = {
749 	.name = "sii902x",
750 	.id = UCLASS_VIDEO_BRIDGE,
751 	.of_match = sii902x_of_match,
752 	.probe = sii902x_probe,
753 	.priv_auto_alloc_size = sizeof(struct sii902x),
754 	.ops = &sii902x_ops,
755 };
756