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