xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_rgb.c (revision bf2d0e5799ef55070017325d7d6459f2262ee682)
1 /*
2  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <dm/of_access.h>
9 #include <errno.h>
10 #include <syscon.h>
11 #include <regmap.h>
12 #include <dm/device.h>
13 #include <dm/read.h>
14 #include <dm/pinctrl.h>
15 #include <linux/media-bus-format.h>
16 #include <asm/gpio.h>
17 #include <backlight.h>
18 
19 #include "rockchip_display.h"
20 #include "rockchip_crtc.h"
21 #include "rockchip_connector.h"
22 #include "rockchip_phy.h"
23 #include "rockchip_panel.h"
24 
25 #define HIWORD_UPDATE(v, l, h)		(((v) << (l)) | (GENMASK(h, l) << 16))
26 
27 #define PX30_GRF_PD_VO_CON1		0x0438
28 #define PX30_RGB_DATA_SYNC_BYPASS(v)	HIWORD_UPDATE(v, 3, 3)
29 #define PX30_RGB_VOP_SEL(v)		HIWORD_UPDATE(v, 2, 2)
30 
31 #define RK1808_GRF_PD_VO_CON1		0x0444
32 #define RK1808_RGB_DATA_SYNC_BYPASS(v)	HIWORD_UPDATE(v, 3, 3)
33 
34 #define RV1106_VENC_GRF_VOP_IO_WRAPPER	0x1000c
35 #define RV1106_IO_BYPASS_SEL(v)		HIWORD_UPDATE(v, 0, 1)
36 #define RV1106_VOGRF_VOP_PIPE_BYPASS	0x60034
37 #define RV1106_VOP_PIPE_BYPASS(v)	HIWORD_UPDATE(v, 0, 1)
38 
39 #define RV1126_GRF_IOFUNC_CON3          0x1026c
40 #define RV1126_LCDC_IO_BYPASS(v)        HIWORD_UPDATE(v, 0, 0)
41 
42 #define RV1126B_GRF_VOP_LCDC_CON	0x30b9c
43 #define RV1126B_VOP_MCU_SEL(v)		HIWORD_UPDATE(v, 15, 15)
44 
45 #define RK3288_GRF_SOC_CON6		0x025c
46 #define RK3288_LVDS_LCDC_SEL(v)		HIWORD_UPDATE(v,  3,  3)
47 #define RK3288_GRF_SOC_CON7		0x0260
48 #define RK3288_LVDS_PWRDWN(v)		HIWORD_UPDATE(v, 15, 15)
49 #define RK3288_LVDS_CON_ENABLE_2(v)	HIWORD_UPDATE(v, 12, 12)
50 #define RK3288_LVDS_CON_ENABLE_1(v)	HIWORD_UPDATE(v, 11, 11)
51 #define RK3288_LVDS_CON_CLKINV(v)	HIWORD_UPDATE(v,  8,  8)
52 #define RK3288_LVDS_CON_TTL_EN(v)	HIWORD_UPDATE(v,  6,  6)
53 
54 #define RK3368_GRF_SOC_CON15		0x043c
55 #define RK3368_FORCE_JETAG(v)		HIWORD_UPDATE(v,  13,  13)
56 
57 #define RK3506_GRF_SOC_CON2		0x0008
58 #define RK3506_GRF_VOP_DATA_BYPASS(v)	HIWORD_UPDATE(v, 1, 2)
59 
60 #define RK3562_GRF_IOC_VO_IO_CON	0x10500
61 #define RK3562_RGB_DATA_BYPASS(v)	HIWORD_UPDATE(v, 6, 6)
62 
63 #define RK3568_GRF_VO_CON1		0X0364
64 #define RK3568_RGB_DATA_BYPASS(v)	HIWORD_UPDATE(v, 6, 6)
65 
66 #define RK3576_VCCIO_IOC_MISC_CON8	0x6420
67 #define RK3576_VOP_MCU_SEL(v)		HIWORD_UPDATE(v, 10, 10)
68 #define RK3576_VOP_DLL_SEL(v)		HIWORD_UPDATE(v, 8, 8)
69 #define RK3576_VOP_DCLK_DELAYLINE(v)	HIWORD_UPDATE(v, 0, 6)
70 
71 struct rockchip_rgb;
72 
73 struct rockchip_rgb_funcs {
74 	void (*prepare)(struct rockchip_rgb *rgb, int pipe);
75 	void (*unprepare)(struct rockchip_rgb *rgb);
76 };
77 
78 struct rockchip_rgb_data {
79 	u32 rgb_max_dclk_rate;
80 	u32 mcu_max_dclk_rate;
81 	u32 dclk_delayline;
82 	const struct rockchip_rgb_funcs *funcs;
83 };
84 
85 struct rockchip_rgb {
86 	struct rockchip_connector connector;
87 	int id;
88 	struct udevice *dev;
89 	struct regmap *grf;
90 	bool data_sync_bypass;
91 	struct rockchip_phy *phy;
92 	const struct rockchip_rgb_funcs *funcs;
93 	u32 max_dclk_rate;
94 	u32 dclk_delayline;
95 };
96 
97 struct mcu_cmd_header {
98 	u8 data_type;
99 	u8 delay;
100 	u8 payload_length;
101 } __packed;
102 
103 struct mcu_cmd_desc {
104 	struct mcu_cmd_header header;
105 	const u8 *payload;
106 };
107 
108 struct mcu_cmd_seq {
109 	struct mcu_cmd_desc *cmds;
110 	unsigned int cmd_cnt;
111 };
112 
113 struct rockchip_mcu_panel_desc {
114 	struct mcu_cmd_seq *init_seq;
115 	struct mcu_cmd_seq *exit_seq;
116 
117 	struct {
118 		unsigned int width;
119 		unsigned int height;
120 	} size;
121 
122 	struct {
123 		unsigned int prepare;
124 		unsigned int enable;
125 		unsigned int disable;
126 		unsigned int unprepare;
127 		unsigned int reset;
128 		unsigned int init;
129 	} delay;
130 
131 	unsigned int bpc;
132 	u32 bus_format;
133 	u32 bus_flags;
134 	bool power_invert;
135 };
136 
137 struct rockchip_mcu_panel {
138 	struct rockchip_panel base;
139 	struct rockchip_mcu_panel_desc *desc;
140 	struct udevice *power_supply;
141 	struct udevice *backlight;
142 
143 	struct gpio_desc enable_gpio;
144 	struct gpio_desc reset_gpio;
145 
146 	bool prepared;
147 	bool enabled;
148 };
149 
to_rockchip_mcu_panel(struct rockchip_panel * panel)150 static inline struct rockchip_mcu_panel *to_rockchip_mcu_panel(struct rockchip_panel *panel)
151 {
152 	return container_of(panel, struct rockchip_mcu_panel, base);
153 }
154 
rockchip_rgb_connector_prepare(struct rockchip_connector * conn,struct display_state * state)155 static int rockchip_rgb_connector_prepare(struct rockchip_connector *conn,
156 					  struct display_state *state)
157 {
158 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
159 	struct crtc_state *crtc_state = &state->crtc_state;
160 	int pipe = crtc_state->crtc_id;
161 	int ret;
162 
163 	pinctrl_select_state(rgb->dev, "default");
164 
165 	if (rgb->funcs && rgb->funcs->prepare)
166 		rgb->funcs->prepare(rgb, pipe);
167 
168 	if (rgb->phy) {
169 		ret = rockchip_phy_set_mode(rgb->phy, PHY_MODE_VIDEO_TTL);
170 		if (ret) {
171 			dev_err(rgb->dev, "failed to set phy mode: %d\n", ret);
172 			return ret;
173 		}
174 
175 		rockchip_phy_power_on(rgb->phy);
176 	}
177 
178 	return 0;
179 }
180 
rockchip_rgb_connector_unprepare(struct rockchip_connector * conn,struct display_state * state)181 static void rockchip_rgb_connector_unprepare(struct rockchip_connector *conn,
182 					     struct display_state *state)
183 {
184 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
185 
186 	if (rgb->phy)
187 		rockchip_phy_power_off(rgb->phy);
188 
189 	if (rgb->funcs && rgb->funcs->unprepare)
190 		rgb->funcs->unprepare(rgb);
191 
192 	pinctrl_select_state(rgb->dev, "sleep");
193 }
194 
rockchip_rgb_connector_init(struct rockchip_connector * conn,struct display_state * state)195 static int rockchip_rgb_connector_init(struct rockchip_connector *conn, struct display_state *state)
196 {
197 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
198 	struct connector_state *conn_state = &state->conn_state;
199 
200 	rgb->phy = conn->phy;
201 
202 	conn_state->color_range = DRM_COLOR_YCBCR_FULL_RANGE;
203 	conn_state->color_encoding = DRM_COLOR_YCBCR_BT709;
204 	conn_state->disp_info  = rockchip_get_disp_info(conn_state->type, rgb->id);
205 
206 	switch (conn_state->bus_format) {
207 	case MEDIA_BUS_FMT_RGB666_1X18:
208 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P666;
209 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
210 		break;
211 	case MEDIA_BUS_FMT_RGB565_1X16:
212 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P565;
213 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
214 		break;
215 	case MEDIA_BUS_FMT_RGB565_2X8_LE:
216 	case MEDIA_BUS_FMT_BGR565_2X8_LE:
217 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S565;
218 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
219 		break;
220 	case MEDIA_BUS_FMT_RGB666_3X6:
221 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S666;
222 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
223 		break;
224 	case MEDIA_BUS_FMT_RGB888_3X8:
225 	case MEDIA_BUS_FMT_BGR888_3X8:
226 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S888;
227 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
228 		break;
229 	case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
230 	case MEDIA_BUS_FMT_BGR888_DUMMY_4X8:
231 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S888_DUMMY;
232 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
233 		break;
234 	case MEDIA_BUS_FMT_YUYV8_2X8:
235 	case MEDIA_BUS_FMT_YVYU8_2X8:
236 	case MEDIA_BUS_FMT_UYVY8_2X8:
237 	case MEDIA_BUS_FMT_VYUY8_2X8:
238 		conn_state->output_mode = ROCKCHIP_OUT_MODE_BT656;
239 		conn_state->output_if = VOP_OUTPUT_IF_BT656;
240 		conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
241 		conn_state->color_encoding = DRM_COLOR_YCBCR_BT601;
242 		break;
243 	case MEDIA_BUS_FMT_YUYV8_1X16:
244 	case MEDIA_BUS_FMT_YVYU8_1X16:
245 	case MEDIA_BUS_FMT_UYVY8_1X16:
246 	case MEDIA_BUS_FMT_VYUY8_1X16:
247 		conn_state->output_mode = ROCKCHIP_OUT_MODE_BT1120;
248 		conn_state->output_if = VOP_OUTPUT_IF_BT1120;
249 		conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
250 		break;
251 	case MEDIA_BUS_FMT_RGB888_1X24:
252 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
253 	default:
254 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
255 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
256 		break;
257 	}
258 
259 	return 0;
260 }
261 
rockchip_rgb_connector_mode_valid(struct rockchip_connector * conn,struct display_state * state)262 static int rockchip_rgb_connector_mode_valid(struct rockchip_connector *conn,
263 					     struct display_state *state)
264 {
265 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
266 	struct connector_state *conn_state = &state->conn_state;
267 	struct crtc_state *crtc_state = &state->crtc_state;
268 	struct drm_display_mode *mode = &conn_state->mode;
269 	u32 request_clock = mode->clock;
270 	u32 max_clock = rgb->max_dclk_rate;
271 
272 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
273 		request_clock *= 2;
274 
275 	if (rgb->data_sync_bypass)
276 		request_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format) *
277 				 (crtc_state->mcu_timing.mcu_pix_total + 1);
278 
279 	if (max_clock != 0 && request_clock > max_clock) {
280 		printf("mode [%dx%d] clock %d is higher than max_clock %d\n",
281 		       mode->hdisplay, mode->vdisplay, request_clock, max_clock);
282 		return -EINVAL;
283 	}
284 
285 	return 0;
286 }
287 
288 static const struct rockchip_connector_funcs rockchip_rgb_connector_funcs = {
289 	.init = rockchip_rgb_connector_init,
290 	.prepare = rockchip_rgb_connector_prepare,
291 	.unprepare = rockchip_rgb_connector_unprepare,
292 	.mode_valid = rockchip_rgb_connector_mode_valid,
293 };
294 
rockchip_mcu_panel_send_cmds(struct display_state * state,struct mcu_cmd_seq * cmds)295 static int rockchip_mcu_panel_send_cmds(struct display_state *state,
296 					struct mcu_cmd_seq *cmds)
297 {
298 	int i;
299 
300 	if (!cmds)
301 		return -EINVAL;
302 
303 	display_send_mcu_cmd(state, MCU_SETBYPASS, 1);
304 	for (i = 0; i < cmds->cmd_cnt; i++) {
305 		struct mcu_cmd_desc *desc = &cmds->cmds[i];
306 		int value = 0;
307 
308 		value = desc->payload[0];
309 		display_send_mcu_cmd(state, desc->header.data_type, value);
310 
311 		if (desc->header.delay)
312 			mdelay(desc->header.delay);
313 	}
314 	display_send_mcu_cmd(state, MCU_SETBYPASS, 0);
315 
316 	return 0;
317 }
318 
rockchip_mcu_panel_prepare(struct rockchip_panel * panel)319 static void rockchip_mcu_panel_prepare(struct rockchip_panel *panel)
320 {
321 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
322 	int ret;
323 
324 	if (mcu_panel->prepared)
325 		return;
326 
327 	if (dm_gpio_is_valid(&mcu_panel->enable_gpio))
328 		dm_gpio_set_value(&mcu_panel->enable_gpio, 1);
329 
330 	if (mcu_panel->desc->delay.prepare)
331 		mdelay(mcu_panel->desc->delay.prepare);
332 
333 	if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
334 		dm_gpio_set_value(&mcu_panel->reset_gpio, 1);
335 
336 	if (mcu_panel->desc->delay.reset)
337 		mdelay(mcu_panel->desc->delay.reset);
338 
339 	if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
340 		dm_gpio_set_value(&mcu_panel->reset_gpio, 0);
341 
342 	if (mcu_panel->desc->delay.init)
343 		mdelay(mcu_panel->desc->delay.init);
344 
345 	if (mcu_panel->desc->init_seq) {
346 		ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->init_seq);
347 		if (ret)
348 			printf("failed to send mcu panel init cmds: %d\n", ret);
349 	}
350 
351 	mcu_panel->prepared = true;
352 }
353 
rockchip_mcu_panel_unprepare(struct rockchip_panel * panel)354 static void rockchip_mcu_panel_unprepare(struct rockchip_panel *panel)
355 {
356 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
357 	int ret;
358 
359 	if (!mcu_panel->prepared)
360 		return;
361 
362 	if (mcu_panel->desc->exit_seq) {
363 		ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->exit_seq);
364 		if (ret)
365 			printf("failed to send mcu panel exit cmds: %d\n", ret);
366 	}
367 
368 	if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
369 		dm_gpio_set_value(&mcu_panel->reset_gpio, 1);
370 
371 	if (dm_gpio_is_valid(&mcu_panel->enable_gpio))
372 		dm_gpio_set_value(&mcu_panel->enable_gpio, 0);
373 
374 	if (mcu_panel->desc->delay.unprepare)
375 		mdelay(mcu_panel->desc->delay.unprepare);
376 
377 	mcu_panel->prepared = false;
378 }
379 
rockchip_mcu_panel_enable(struct rockchip_panel * panel)380 static void rockchip_mcu_panel_enable(struct rockchip_panel *panel)
381 {
382 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
383 
384 	if (mcu_panel->enabled)
385 		return;
386 
387 	if (mcu_panel->desc->delay.enable)
388 		mdelay(mcu_panel->desc->delay.enable);
389 
390 	if (mcu_panel->backlight)
391 		backlight_enable(mcu_panel->backlight);
392 
393 	mcu_panel->enabled = true;
394 }
395 
rockchip_mcu_panel_disable(struct rockchip_panel * panel)396 static void rockchip_mcu_panel_disable(struct rockchip_panel *panel)
397 {
398 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
399 
400 	if (!mcu_panel->enabled)
401 		return;
402 
403 	if (mcu_panel->backlight)
404 		backlight_disable(mcu_panel->backlight);
405 
406 	if (mcu_panel->desc->delay.disable)
407 		mdelay(mcu_panel->desc->delay.disable);
408 
409 	mcu_panel->enabled = false;
410 }
411 
412 static const struct rockchip_panel_funcs rockchip_mcu_panel_funcs = {
413 	.prepare = rockchip_mcu_panel_prepare,
414 	.unprepare = rockchip_mcu_panel_unprepare,
415 	.enable = rockchip_mcu_panel_enable,
416 	.disable = rockchip_mcu_panel_disable,
417 };
418 
rockchip_mcu_panel_parse_cmds(const u8 * data,int length,struct mcu_cmd_seq * pcmds)419 static int rockchip_mcu_panel_parse_cmds(const u8 *data, int length,
420 					 struct mcu_cmd_seq *pcmds)
421 {
422 	int len;
423 	const u8 *buf;
424 	const struct mcu_cmd_header *header;
425 	int i, cnt = 0;
426 
427 	/* scan commands */
428 	cnt = 0;
429 	buf = data;
430 	len = length;
431 	while (len > sizeof(*header)) {
432 		header = (const struct mcu_cmd_header *)buf;
433 		buf += sizeof(*header) + header->payload_length;
434 		len -= sizeof(*header) + header->payload_length;
435 		cnt++;
436 	}
437 
438 	pcmds->cmds = calloc(cnt, sizeof(struct mcu_cmd_desc));
439 	if (!pcmds->cmds)
440 		return -ENOMEM;
441 
442 	pcmds->cmd_cnt = cnt;
443 
444 	buf = data;
445 	len = length;
446 	for (i = 0; i < cnt; i++) {
447 		struct mcu_cmd_desc *desc = &pcmds->cmds[i];
448 
449 		header = (const struct mcu_cmd_header *)buf;
450 		length -= sizeof(*header);
451 		buf += sizeof(*header);
452 		desc->header.data_type = header->data_type;
453 		desc->header.delay = header->delay;
454 		desc->header.payload_length = header->payload_length;
455 		desc->payload = buf;
456 		buf += header->payload_length;
457 		length -= header->payload_length;
458 	}
459 
460 	return 0;
461 }
462 
rockchip_mcu_panel_init(struct rockchip_mcu_panel * mcu_panel,ofnode mcu_panel_node)463 static int rockchip_mcu_panel_init(struct rockchip_mcu_panel *mcu_panel, ofnode mcu_panel_node)
464 {
465 	const void *data;
466 	int len;
467 	int ret;
468 
469 	ret = gpio_request_by_name_nodev(mcu_panel_node, "enable-gpios", 0,
470 					 &mcu_panel->enable_gpio, GPIOD_IS_OUT);
471 	if (ret && ret != -ENOENT) {
472 		printf("%s: Cannot get mcu panel enable GPIO: %d\n", __func__, ret);
473 		return ret;
474 	}
475 
476 	ret = gpio_request_by_name_nodev(mcu_panel_node, "reset-gpios", 0,
477 					 &mcu_panel->reset_gpio, GPIOD_IS_OUT);
478 	if (ret && ret != -ENOENT) {
479 		printf("%s: Cannot get mcu panel reset GPIO: %d\n", __func__, ret);
480 		return ret;
481 	}
482 
483 	mcu_panel->desc = malloc(sizeof(struct rockchip_mcu_panel_desc));
484 	if (!mcu_panel->desc)
485 		return -ENOMEM;
486 
487 	mcu_panel->desc->power_invert = ofnode_read_bool(mcu_panel_node, "power-invert");
488 
489 	mcu_panel->desc->delay.prepare = ofnode_read_u32_default(mcu_panel_node, "prepare-delay-ms", 0);
490 	mcu_panel->desc->delay.unprepare = ofnode_read_u32_default(mcu_panel_node, "unprepare-delay-ms", 0);
491 	mcu_panel->desc->delay.enable = ofnode_read_u32_default(mcu_panel_node, "enable-delay-ms", 0);
492 	mcu_panel->desc->delay.disable = ofnode_read_u32_default(mcu_panel_node, "disable-delay-ms", 0);
493 	mcu_panel->desc->delay.init = ofnode_read_u32_default(mcu_panel_node, "init-delay-ms", 0);
494 	mcu_panel->desc->delay.reset = ofnode_read_u32_default(mcu_panel_node, "reset-delay-ms", 0);
495 
496 	mcu_panel->desc->bus_format = ofnode_read_u32_default(mcu_panel_node, "bus-format",
497 							      MEDIA_BUS_FMT_RBG888_1X24);
498 	mcu_panel->desc->bpc = ofnode_read_u32_default(mcu_panel_node, "bpc", 8);
499 
500 	data = ofnode_get_property(mcu_panel_node, "panel-init-sequence", &len);
501 	if (data) {
502 		mcu_panel->desc->init_seq = calloc(1, sizeof(*mcu_panel->desc->init_seq));
503 		if (!mcu_panel->desc->init_seq)
504 			return -ENOMEM;
505 
506 		ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->init_seq);
507 		if (ret) {
508 			printf("failed to parse panel init sequence\n");
509 			goto free_on_cmds;
510 		}
511 	}
512 
513 	data = ofnode_get_property(mcu_panel_node, "panel-exit-sequence", &len);
514 	if (data) {
515 		mcu_panel->desc->exit_seq = calloc(1, sizeof(*mcu_panel->desc->exit_seq));
516 		if (!mcu_panel->desc->exit_seq) {
517 			ret = -ENOMEM;
518 			goto free_on_cmds;
519 		}
520 
521 		ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->exit_seq);
522 		if (ret) {
523 			printf("failed to parse panel exit sequence\n");
524 			goto free_cmds;
525 		}
526 	}
527 
528 	return 0;
529 
530 free_cmds:
531 	free(mcu_panel->desc->exit_seq);
532 free_on_cmds:
533 	free(mcu_panel->desc->init_seq);
534 	return ret;
535 }
536 
rockchip_rgb_probe(struct udevice * dev)537 static int rockchip_rgb_probe(struct udevice *dev)
538 {
539 	struct rockchip_rgb *rgb = dev_get_priv(dev);
540 	const struct rockchip_rgb_data *rgb_data;
541 	ofnode mcu_panel_node;
542 	int phandle;
543 	int ret;
544 
545 	rgb->data_sync_bypass = dev_read_bool(dev, "rockchip,data-sync-bypass");
546 	rgb_data = (const struct rockchip_rgb_data *)dev_get_driver_data(dev);
547 	if (rgb_data) {
548 		rgb->funcs = rgb_data->funcs;
549 		if (rgb->data_sync_bypass)
550 			rgb->max_dclk_rate = rgb_data->mcu_max_dclk_rate;
551 		else
552 			rgb->max_dclk_rate = rgb_data->rgb_max_dclk_rate;
553 		rgb->dclk_delayline = rgb_data->dclk_delayline;
554 	}
555 	rgb->dev = dev;
556 	rgb->grf = syscon_get_regmap(dev_get_parent(dev));
557 	rgb->id = of_alias_get_id(ofnode_to_np(dev->node), "rgb");
558 	if (rgb->id < 0)
559 		rgb->id = 0;
560 
561 	mcu_panel_node = dev_read_subnode(dev, "mcu-panel");
562 	if (ofnode_valid(mcu_panel_node) && ofnode_is_available(mcu_panel_node)) {
563 		struct rockchip_mcu_panel *mcu_panel;
564 
565 		mcu_panel = malloc(sizeof(struct rockchip_mcu_panel));
566 		if (!mcu_panel) {
567 			printf("failed to alloc mcu_panel data\n");
568 			return -ENOMEM;
569 		}
570 
571 		ret = rockchip_mcu_panel_init(mcu_panel, mcu_panel_node);
572 		if (ret < 0) {
573 			printf("failed to init mcu_panel: %d\n", ret);
574 			return ret;
575 		}
576 
577 		phandle = ofnode_read_u32_default(mcu_panel_node, "backlight", -1);
578 		if (phandle < 0) {
579 			printf("failed to find backlight phandle\n");
580 			return -EINVAL;
581 		}
582 
583 		ret = uclass_get_device_by_phandle_id(UCLASS_PANEL_BACKLIGHT, phandle,
584 						      &mcu_panel->backlight);
585 		if (ret && ret != -ENOENT) {
586 			printf("%s: failed to get backlight device: %d\n", __func__, ret);
587 			return ret;
588 		}
589 
590 		mcu_panel->base.dev = dev;
591 		mcu_panel->base.bus_format = mcu_panel->desc->bus_format;
592 		mcu_panel->base.bpc = mcu_panel->desc->bpc;
593 		mcu_panel->base.funcs = &rockchip_mcu_panel_funcs;
594 		mcu_panel->enabled = false;
595 		mcu_panel->prepared = false;
596 
597 		rgb->connector.panel = &mcu_panel->base;
598 	}
599 
600 	rockchip_connector_bind(&rgb->connector, dev, rgb->id, &rockchip_rgb_connector_funcs,
601 				NULL, DRM_MODE_CONNECTOR_LVDS);
602 
603 	return 0;
604 }
605 
rv1106_rgb_prepare(struct rockchip_rgb * rgb,int pipe)606 static void rv1106_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
607 {
608 	regmap_write(rgb->grf, RV1106_VENC_GRF_VOP_IO_WRAPPER,
609 		     RV1106_IO_BYPASS_SEL(rgb->data_sync_bypass ? 0x3 : 0x0));
610 	regmap_write(rgb->grf, RV1106_VOGRF_VOP_PIPE_BYPASS,
611 		     RV1106_VOP_PIPE_BYPASS(rgb->data_sync_bypass ? 0x3 : 0x0));
612 }
613 
614 static const struct rockchip_rgb_funcs rv1106_rgb_funcs = {
615 	.prepare = rv1106_rgb_prepare,
616 };
617 
618 static const struct rockchip_rgb_data rv1106_rgb = {
619 	.rgb_max_dclk_rate = 74250,
620 	.mcu_max_dclk_rate = 150000,
621 	.funcs = &rv1106_rgb_funcs,
622 };
623 
rv1126_rgb_prepare(struct rockchip_rgb * rgb,int pipe)624 static void rv1126_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
625 {
626 	regmap_write(rgb->grf, RV1126_GRF_IOFUNC_CON3,
627 		     RV1126_LCDC_IO_BYPASS(rgb->data_sync_bypass));
628 }
629 
630 static const struct rockchip_rgb_funcs rv1126_rgb_funcs = {
631 	.prepare = rv1126_rgb_prepare,
632 };
633 
634 static const struct rockchip_rgb_data rv1126_rgb = {
635 	.funcs = &rv1126_rgb_funcs,
636 };
637 
rv1126b_rgb_prepare(struct rockchip_rgb * rgb,int pipe)638 static void rv1126b_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
639 {
640 	regmap_write(rgb->grf, RV1126B_GRF_VOP_LCDC_CON,
641 		     RV1126B_VOP_MCU_SEL(rgb->data_sync_bypass));
642 }
643 
644 static const struct rockchip_rgb_funcs rv1126b_rgb_funcs = {
645 	.prepare = rv1126b_rgb_prepare,
646 };
647 
648 static const struct rockchip_rgb_data rv1126b_rgb = {
649 	.rgb_max_dclk_rate = 150000,
650 	.mcu_max_dclk_rate = 150000,
651 	.funcs = &rv1126b_rgb_funcs,
652 };
653 
px30_rgb_prepare(struct rockchip_rgb * rgb,int pipe)654 static void px30_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
655 {
656 	regmap_write(rgb->grf, PX30_GRF_PD_VO_CON1, PX30_RGB_VOP_SEL(pipe) |
657 		     PX30_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass));
658 }
659 
660 static const struct rockchip_rgb_funcs px30_rgb_funcs = {
661 	.prepare = px30_rgb_prepare,
662 };
663 
664 static const struct rockchip_rgb_data px30_rgb = {
665 	.funcs = &px30_rgb_funcs,
666 };
667 
rk1808_rgb_prepare(struct rockchip_rgb * rgb,int pipe)668 static void rk1808_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
669 {
670 	regmap_write(rgb->grf, RK1808_GRF_PD_VO_CON1,
671 		     RK1808_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass));
672 }
673 
674 static const struct rockchip_rgb_funcs rk1808_rgb_funcs = {
675 	.prepare = rk1808_rgb_prepare,
676 };
677 
678 static const struct rockchip_rgb_data rk1808_rgb = {
679 	.funcs = &rk1808_rgb_funcs,
680 };
681 
rk3288_rgb_prepare(struct rockchip_rgb * rgb,int pipe)682 static void rk3288_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
683 {
684 	regmap_write(rgb->grf, RK3288_GRF_SOC_CON6, RK3288_LVDS_LCDC_SEL(pipe));
685 	regmap_write(rgb->grf, RK3288_GRF_SOC_CON7,
686 		     RK3288_LVDS_PWRDWN(0) | RK3288_LVDS_CON_ENABLE_2(1) |
687 		     RK3288_LVDS_CON_ENABLE_1(1) | RK3288_LVDS_CON_CLKINV(0) |
688 		     RK3288_LVDS_CON_TTL_EN(1));
689 }
690 
rk3288_rgb_unprepare(struct rockchip_rgb * rgb)691 static void rk3288_rgb_unprepare(struct rockchip_rgb *rgb)
692 {
693 	regmap_write(rgb->grf, RK3288_GRF_SOC_CON7,
694 		     RK3288_LVDS_PWRDWN(1) | RK3288_LVDS_CON_ENABLE_2(0) |
695 		     RK3288_LVDS_CON_ENABLE_1(0) | RK3288_LVDS_CON_TTL_EN(0));
696 }
697 
698 static const struct rockchip_rgb_funcs rk3288_rgb_funcs = {
699 	.prepare = rk3288_rgb_prepare,
700 	.unprepare = rk3288_rgb_unprepare,
701 };
702 
703 static const struct rockchip_rgb_data rk3288_rgb = {
704 	.funcs = &rk3288_rgb_funcs,
705 };
706 
rk3368_rgb_prepare(struct rockchip_rgb * rgb,int pipe)707 static void rk3368_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
708 {
709 	regmap_write(rgb->grf, RK3368_GRF_SOC_CON15, RK3368_FORCE_JETAG(0));
710 }
711 
712 static const struct rockchip_rgb_funcs rk3368_rgb_funcs = {
713 	.prepare = rk3368_rgb_prepare,
714 };
715 
716 static const struct rockchip_rgb_data rk3368_rgb = {
717 	.funcs = &rk3368_rgb_funcs,
718 };
719 
rk3506_rgb_prepare(struct rockchip_rgb * rgb,int pipe)720 static void rk3506_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
721 {
722 	regmap_write(rgb->grf, RK3506_GRF_SOC_CON2,
723 		     RK3506_GRF_VOP_DATA_BYPASS(rgb->data_sync_bypass ? 0x3 : 0x0));
724 }
725 
726 static const struct rockchip_rgb_funcs rk3506_rgb_funcs = {
727 	.prepare = rk3506_rgb_prepare,
728 };
729 
730 static const struct rockchip_rgb_data rk3506_rgb = {
731 	.rgb_max_dclk_rate = 120000,
732 	.mcu_max_dclk_rate = 120000,
733 	.funcs = &rk3506_rgb_funcs,
734 };
735 
rk3562_rgb_prepare(struct rockchip_rgb * rgb,int pipe)736 static void rk3562_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
737 {
738 	regmap_write(rgb->grf, RK3562_GRF_IOC_VO_IO_CON,
739 		     RK3562_RGB_DATA_BYPASS(rgb->data_sync_bypass));
740 }
741 
742 static const struct rockchip_rgb_funcs rk3562_rgb_funcs = {
743 	.prepare = rk3562_rgb_prepare,
744 };
745 
746 static const struct rockchip_rgb_data rk3562_rgb = {
747 	.funcs = &rk3562_rgb_funcs,
748 };
749 
rk3568_rgb_prepare(struct rockchip_rgb * rgb,int pipe)750 static void rk3568_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
751 {
752 	regmap_write(rgb->grf, RK3568_GRF_VO_CON1, RK3568_RGB_DATA_BYPASS(rgb->data_sync_bypass));
753 }
754 
755 static const struct rockchip_rgb_funcs rk3568_rgb_funcs = {
756 	.prepare = rk3568_rgb_prepare,
757 };
758 
759 static const struct rockchip_rgb_data rk3568_rgb = {
760 	.funcs = &rk3568_rgb_funcs,
761 };
762 
rk3576_rgb_prepare(struct rockchip_rgb * rgb,int pipe)763 static void rk3576_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
764 {
765 	regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8,
766 		     RK3576_VOP_MCU_SEL(rgb->data_sync_bypass));
767 	regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8,
768 		     RK3576_VOP_DLL_SEL(true));
769 	regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8,
770 		     RK3576_VOP_DCLK_DELAYLINE(rgb->dclk_delayline));
771 }
772 
773 static const struct rockchip_rgb_funcs rk3576_rgb_funcs = {
774 	.prepare = rk3576_rgb_prepare,
775 };
776 
777 static const struct rockchip_rgb_data rk3576_rgb = {
778 	.dclk_delayline = 5,
779 	.funcs = &rk3576_rgb_funcs,
780 };
781 
782 static const struct udevice_id rockchip_rgb_ids[] = {
783 	{
784 		.compatible = "rockchip,px30-rgb",
785 		.data = (ulong)&px30_rgb,
786 	},
787 	{
788 		.compatible = "rockchip,rk1808-rgb",
789 		.data = (ulong)&rk1808_rgb,
790 	},
791 	{
792 		.compatible = "rockchip,rk3066-rgb",
793 	},
794 	{
795 		.compatible = "rockchip,rk3128-rgb",
796 	},
797 	{
798 		.compatible = "rockchip,rk3288-rgb",
799 		.data = (ulong)&rk3288_rgb,
800 	},
801 	{
802 		.compatible = "rockchip,rk3308-rgb",
803 	},
804 	{
805 		.compatible = "rockchip,rk3368-rgb",
806 		.data = (ulong)&rk3368_rgb,
807 	},
808 	{
809 		.compatible = "rockchip,rk3506-rgb",
810 		.data = (ulong)&rk3506_rgb,
811 	},
812 	{
813 		.compatible = "rockchip,rk3562-rgb",
814 		.data = (ulong)&rk3562_rgb,
815 	},
816 	{
817 		.compatible = "rockchip,rk3568-rgb",
818 		.data = (ulong)&rk3568_rgb,
819 	},
820 	{
821 		.compatible = "rockchip,rk3576-rgb",
822 		.data = (ulong)&rk3576_rgb,
823 	},
824 	{
825 		.compatible = "rockchip,rk3588-rgb",
826 	},
827 	{
828 		.compatible = "rockchip,rv1106-rgb",
829 		.data = (ulong)&rv1106_rgb,
830 	},
831 	{
832 		.compatible = "rockchip,rv1108-rgb",
833 	},
834 	{
835 		.compatible = "rockchip,rv1126-rgb",
836 		.data = (ulong)&rv1126_rgb,
837 	},
838 	{
839 		.compatible = "rockchip,rv1126b-rgb",
840 		.data = (ulong)&rv1126b_rgb,
841 	},
842 	{}
843 };
844 
845 U_BOOT_DRIVER(rockchip_rgb) = {
846 	.name = "rockchip_rgb",
847 	.id = UCLASS_DISPLAY,
848 	.of_match = rockchip_rgb_ids,
849 	.probe = rockchip_rgb_probe,
850 	.priv_auto_alloc_size = sizeof(struct rockchip_rgb),
851 };
852