xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_rgb.c (revision 0fd9ded2d2bcf40bfefc48cde35176ea51e29e7e)
19e02a86eSWyon Bi /*
29e02a86eSWyon Bi  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
39e02a86eSWyon Bi  *
49e02a86eSWyon Bi  * SPDX-License-Identifier:	GPL-2.0+
59e02a86eSWyon Bi  */
69e02a86eSWyon Bi 
79e02a86eSWyon Bi #include <common.h>
8cb17ca6cSSandy Huang #include <dm/of_access.h>
99e02a86eSWyon Bi #include <errno.h>
109e02a86eSWyon Bi #include <syscon.h>
119e02a86eSWyon Bi #include <regmap.h>
129e02a86eSWyon Bi #include <dm/device.h>
139e02a86eSWyon Bi #include <dm/read.h>
14350f6a18SWyon Bi #include <dm/pinctrl.h>
156b93bf2bSWyon Bi #include <linux/media-bus-format.h>
16b5dbb15aSDamon Ding #include <asm/gpio.h>
17b5dbb15aSDamon Ding #include <backlight.h>
189e02a86eSWyon Bi 
199e02a86eSWyon Bi #include "rockchip_display.h"
209e02a86eSWyon Bi #include "rockchip_crtc.h"
219e02a86eSWyon Bi #include "rockchip_connector.h"
2249627130SWyon Bi #include "rockchip_phy.h"
23b5dbb15aSDamon Ding #include "rockchip_panel.h"
249e02a86eSWyon Bi 
251953e619SWyon Bi #define HIWORD_UPDATE(v, h, l)		(((v) << (l)) | (GENMASK(h, l) << 16))
261953e619SWyon Bi 
279e02a86eSWyon Bi #define PX30_GRF_PD_VO_CON1		0x0438
286b9c0415SSandy Huang #define PX30_RGB_DATA_SYNC_BYPASS(v)	HIWORD_UPDATE(v, 3, 3)
299e02a86eSWyon Bi #define PX30_RGB_VOP_SEL(v)		HIWORD_UPDATE(v, 2, 2)
309e02a86eSWyon Bi 
316b9c0415SSandy Huang #define RK1808_GRF_PD_VO_CON1		0x0444
326b9c0415SSandy Huang #define RK1808_RGB_DATA_SYNC_BYPASS(v)	HIWORD_UPDATE(v, 3, 3)
336b9c0415SSandy Huang 
34e8dd2b64SDamon Ding #define RV1106_VENC_GRF_VOP_IO_WRAPPER	0x1000c
35e8dd2b64SDamon Ding #define RV1106_IO_BYPASS_SEL(v)		HIWORD_UPDATE(v, 0, 1)
36e8dd2b64SDamon Ding #define RV1106_VOGRF_VOP_PIPE_BYPASS	0x60034
37e8dd2b64SDamon Ding #define RV1106_VOP_PIPE_BYPASS(v)	HIWORD_UPDATE(v, 0, 1)
38e8dd2b64SDamon Ding 
39406bb09aSAndy Yan #define RV1126_GRF_IOFUNC_CON3          0x1026c
40406bb09aSAndy Yan #define RV1126_LCDC_IO_BYPASS(v)        HIWORD_UPDATE(v, 0, 0)
41406bb09aSAndy Yan 
4249627130SWyon Bi #define RK3288_GRF_SOC_CON6		0x025c
4349627130SWyon Bi #define RK3288_LVDS_LCDC_SEL(v)		HIWORD_UPDATE(v,  3,  3)
4449627130SWyon Bi #define RK3288_GRF_SOC_CON7		0x0260
4549627130SWyon Bi #define RK3288_LVDS_PWRDWN(v)		HIWORD_UPDATE(v, 15, 15)
4649627130SWyon Bi #define RK3288_LVDS_CON_ENABLE_2(v)	HIWORD_UPDATE(v, 12, 12)
4749627130SWyon Bi #define RK3288_LVDS_CON_ENABLE_1(v)	HIWORD_UPDATE(v, 11, 11)
4849627130SWyon Bi #define RK3288_LVDS_CON_CLKINV(v)	HIWORD_UPDATE(v,  8,  8)
4949627130SWyon Bi #define RK3288_LVDS_CON_TTL_EN(v)	HIWORD_UPDATE(v,  6,  6)
5049627130SWyon Bi 
516383df2bSSandy Huang #define RK3368_GRF_SOC_CON15		0x043c
526383df2bSSandy Huang #define RK3368_FORCE_JETAG(v)		HIWORD_UPDATE(v,  13,  13)
536383df2bSSandy Huang 
54078f1c2cSDamon Ding #define RK3562_GRF_IOC_VO_IO_CON	0x10500
55078f1c2cSDamon Ding #define RK3562_RGB_DATA_BYPASS(v)	HIWORD_UPDATE(v, 6, 6)
56078f1c2cSDamon Ding 
57c55d261eSSandy Huang #define RK3568_GRF_VO_CON1		0X0364
58c55d261eSSandy Huang #define RK3568_RGB_DATA_BYPASS(v)	HIWORD_UPDATE(v, 6, 6)
59c55d261eSSandy Huang 
60181a4463SDamon Ding #define RK3576_VCCIO_IOC_MISC_CON8	0x6420
61181a4463SDamon Ding #define RK3576_VOP_MCU_SEL(v)		HIWORD_UPDATE(v, 10, 10)
62*0fd9ded2SDamon Ding #define RK3576_VOP_DLL_SEL(v)		HIWORD_UPDATE(v, 8, 8)
63*0fd9ded2SDamon Ding #define RK3576_VOP_DCLK_DELAYLINE(v)	HIWORD_UPDATE(v, 0, 6)
64181a4463SDamon Ding 
656b9c0415SSandy Huang struct rockchip_rgb;
666b9c0415SSandy Huang 
676b9c0415SSandy Huang struct rockchip_rgb_funcs {
684ec7b4d4SSandy Huang 	void (*prepare)(struct rockchip_rgb *rgb, int pipe);
694ec7b4d4SSandy Huang 	void (*unprepare)(struct rockchip_rgb *rgb);
709e02a86eSWyon Bi };
719e02a86eSWyon Bi 
724ed82c15SDamon Ding struct rockchip_rgb_data {
734ed82c15SDamon Ding 	u32 rgb_max_dclk_rate;
744ed82c15SDamon Ding 	u32 mcu_max_dclk_rate;
75*0fd9ded2SDamon Ding 	u32 dclk_delayline;
764ed82c15SDamon Ding 	const struct rockchip_rgb_funcs *funcs;
774ed82c15SDamon Ding };
784ed82c15SDamon Ding 
796b9c0415SSandy Huang struct rockchip_rgb {
800594ce39SZhang Yubing 	struct rockchip_connector connector;
81cb17ca6cSSandy Huang 	int id;
8249627130SWyon Bi 	struct udevice *dev;
836b9c0415SSandy Huang 	struct regmap *grf;
84406bb09aSAndy Yan 	bool data_sync_bypass;
8549627130SWyon Bi 	struct rockchip_phy *phy;
866b9c0415SSandy Huang 	const struct rockchip_rgb_funcs *funcs;
874ed82c15SDamon Ding 	u32 max_dclk_rate;
88*0fd9ded2SDamon Ding 	u32 dclk_delayline;
896b9c0415SSandy Huang };
906b9c0415SSandy Huang 
91b5dbb15aSDamon Ding struct mcu_cmd_header {
92b5dbb15aSDamon Ding 	u8 data_type;
93b5dbb15aSDamon Ding 	u8 delay;
94b5dbb15aSDamon Ding 	u8 payload_length;
95b5dbb15aSDamon Ding } __packed;
96b5dbb15aSDamon Ding 
97b5dbb15aSDamon Ding struct mcu_cmd_desc {
98b5dbb15aSDamon Ding 	struct mcu_cmd_header header;
99b5dbb15aSDamon Ding 	const u8 *payload;
100b5dbb15aSDamon Ding };
101b5dbb15aSDamon Ding 
102b5dbb15aSDamon Ding struct mcu_cmd_seq {
103b5dbb15aSDamon Ding 	struct mcu_cmd_desc *cmds;
104b5dbb15aSDamon Ding 	unsigned int cmd_cnt;
105b5dbb15aSDamon Ding };
106b5dbb15aSDamon Ding 
107b5dbb15aSDamon Ding struct rockchip_mcu_panel_desc {
108b5dbb15aSDamon Ding 	struct mcu_cmd_seq *init_seq;
109b5dbb15aSDamon Ding 	struct mcu_cmd_seq *exit_seq;
110b5dbb15aSDamon Ding 
111b5dbb15aSDamon Ding 	struct {
112b5dbb15aSDamon Ding 		unsigned int width;
113b5dbb15aSDamon Ding 		unsigned int height;
114b5dbb15aSDamon Ding 	} size;
115b5dbb15aSDamon Ding 
116b5dbb15aSDamon Ding 	struct {
117b5dbb15aSDamon Ding 		unsigned int prepare;
118b5dbb15aSDamon Ding 		unsigned int enable;
119b5dbb15aSDamon Ding 		unsigned int disable;
120b5dbb15aSDamon Ding 		unsigned int unprepare;
121b5dbb15aSDamon Ding 		unsigned int reset;
122b5dbb15aSDamon Ding 		unsigned int init;
123b5dbb15aSDamon Ding 	} delay;
124b5dbb15aSDamon Ding 
125b5dbb15aSDamon Ding 	unsigned int bpc;
126b5dbb15aSDamon Ding 	u32 bus_format;
127b5dbb15aSDamon Ding 	u32 bus_flags;
128b5dbb15aSDamon Ding 	bool power_invert;
129b5dbb15aSDamon Ding };
130b5dbb15aSDamon Ding 
131b5dbb15aSDamon Ding struct rockchip_mcu_panel {
132b5dbb15aSDamon Ding 	struct rockchip_panel base;
133b5dbb15aSDamon Ding 	struct rockchip_mcu_panel_desc *desc;
134b5dbb15aSDamon Ding 	struct udevice *power_supply;
135b5dbb15aSDamon Ding 	struct udevice *backlight;
136b5dbb15aSDamon Ding 
137b5dbb15aSDamon Ding 	struct gpio_desc enable_gpio;
138b5dbb15aSDamon Ding 	struct gpio_desc reset_gpio;
139b5dbb15aSDamon Ding 
140b5dbb15aSDamon Ding 	bool prepared;
141b5dbb15aSDamon Ding 	bool enabled;
142b5dbb15aSDamon Ding };
143b5dbb15aSDamon Ding 
144b5dbb15aSDamon Ding static inline struct rockchip_mcu_panel *to_rockchip_mcu_panel(struct rockchip_panel *panel)
145b5dbb15aSDamon Ding {
146b5dbb15aSDamon Ding 	return container_of(panel, struct rockchip_mcu_panel, base);
147b5dbb15aSDamon Ding }
148b5dbb15aSDamon Ding 
1490594ce39SZhang Yubing static int rockchip_rgb_connector_prepare(struct rockchip_connector *conn,
1500594ce39SZhang Yubing 					  struct display_state *state)
1519e02a86eSWyon Bi {
1520594ce39SZhang Yubing 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
1539e02a86eSWyon Bi 	struct crtc_state *crtc_state = &state->crtc_state;
1549e02a86eSWyon Bi 	int pipe = crtc_state->crtc_id;
1559e3ffb10SGuochun Huang 	int ret;
1569e02a86eSWyon Bi 
157350f6a18SWyon Bi 	pinctrl_select_state(rgb->dev, "default");
158350f6a18SWyon Bi 
1594ec7b4d4SSandy Huang 	if (rgb->funcs && rgb->funcs->prepare)
1604ec7b4d4SSandy Huang 		rgb->funcs->prepare(rgb, pipe);
1619e02a86eSWyon Bi 
1629e3ffb10SGuochun Huang 	if (rgb->phy) {
1639e3ffb10SGuochun Huang 		ret = rockchip_phy_set_mode(rgb->phy, PHY_MODE_VIDEO_TTL);
1649e3ffb10SGuochun Huang 		if (ret) {
1659e3ffb10SGuochun Huang 			dev_err(rgb->dev, "failed to set phy mode: %d\n", ret);
1669e3ffb10SGuochun Huang 			return ret;
1679e3ffb10SGuochun Huang 		}
1685a7ad828SGuochun Huang 
1699e3ffb10SGuochun Huang 		rockchip_phy_power_on(rgb->phy);
1709e3ffb10SGuochun Huang 	}
17149627130SWyon Bi 
1729e02a86eSWyon Bi 	return 0;
1739e02a86eSWyon Bi }
1749e02a86eSWyon Bi 
1750594ce39SZhang Yubing static void rockchip_rgb_connector_unprepare(struct rockchip_connector *conn,
1760594ce39SZhang Yubing 					     struct display_state *state)
1779e02a86eSWyon Bi {
1780594ce39SZhang Yubing 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
1796b9c0415SSandy Huang 
18049627130SWyon Bi 	if (rgb->phy)
18149627130SWyon Bi 		rockchip_phy_power_off(rgb->phy);
18249627130SWyon Bi 
1834ec7b4d4SSandy Huang 	if (rgb->funcs && rgb->funcs->unprepare)
1844ec7b4d4SSandy Huang 		rgb->funcs->unprepare(rgb);
1856b9c0415SSandy Huang 
186350f6a18SWyon Bi 	pinctrl_select_state(rgb->dev, "sleep");
1879e02a86eSWyon Bi }
1889e02a86eSWyon Bi 
1890594ce39SZhang Yubing static int rockchip_rgb_connector_init(struct rockchip_connector *conn, struct display_state *state)
19058c17f51SSandy Huang {
1910594ce39SZhang Yubing 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
19258c17f51SSandy Huang 	struct connector_state *conn_state = &state->conn_state;
19358c17f51SSandy Huang 
1940594ce39SZhang Yubing 	rgb->phy = conn->phy;
19549627130SWyon Bi 
196df0a5c43SDamon Ding 	conn_state->color_range = DRM_COLOR_YCBCR_FULL_RANGE;
197df0a5c43SDamon Ding 	conn_state->color_encoding = DRM_COLOR_YCBCR_BT709;
198cb17ca6cSSandy Huang 	conn_state->disp_info  = rockchip_get_disp_info(conn_state->type, rgb->id);
1999e02a86eSWyon Bi 
2006b93bf2bSWyon Bi 	switch (conn_state->bus_format) {
2016b93bf2bSWyon Bi 	case MEDIA_BUS_FMT_RGB666_1X18:
2026b93bf2bSWyon Bi 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P666;
203c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
2046b93bf2bSWyon Bi 		break;
2056b93bf2bSWyon Bi 	case MEDIA_BUS_FMT_RGB565_1X16:
2066b93bf2bSWyon Bi 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P565;
207c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
2086b93bf2bSWyon Bi 		break;
20901c3fe29SDamon Ding 	case MEDIA_BUS_FMT_RGB565_2X8_LE:
21001c3fe29SDamon Ding 	case MEDIA_BUS_FMT_BGR565_2X8_LE:
21101c3fe29SDamon Ding 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S565;
21201c3fe29SDamon Ding 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
21301c3fe29SDamon Ding 		break;
21401c3fe29SDamon Ding 	case MEDIA_BUS_FMT_RGB666_3X6:
21501c3fe29SDamon Ding 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S666;
21601c3fe29SDamon Ding 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
21701c3fe29SDamon Ding 		break;
218b7b383ebSDamon Ding 	case MEDIA_BUS_FMT_RGB888_3X8:
219b7b383ebSDamon Ding 	case MEDIA_BUS_FMT_BGR888_3X8:
220b754d470SYu YongZhen 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S888;
221c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
222b754d470SYu YongZhen 		break;
223b7b383ebSDamon Ding 	case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
224b7b383ebSDamon Ding 	case MEDIA_BUS_FMT_BGR888_DUMMY_4X8:
2254ec7b4d4SSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S888_DUMMY;
226c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
2274ec7b4d4SSandy Huang 		break;
228c55d261eSSandy Huang 	case MEDIA_BUS_FMT_YUYV8_2X8:
229c55d261eSSandy Huang 	case MEDIA_BUS_FMT_YVYU8_2X8:
230c55d261eSSandy Huang 	case MEDIA_BUS_FMT_UYVY8_2X8:
231c55d261eSSandy Huang 	case MEDIA_BUS_FMT_VYUY8_2X8:
232c55d261eSSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_BT656;
233c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_BT656;
234df0a5c43SDamon Ding 		conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
235df0a5c43SDamon Ding 		conn_state->color_encoding = DRM_COLOR_YCBCR_BT601;
236c55d261eSSandy Huang 		break;
237c55d261eSSandy Huang 	case MEDIA_BUS_FMT_YUYV8_1X16:
238c55d261eSSandy Huang 	case MEDIA_BUS_FMT_YVYU8_1X16:
239c55d261eSSandy Huang 	case MEDIA_BUS_FMT_UYVY8_1X16:
240c55d261eSSandy Huang 	case MEDIA_BUS_FMT_VYUY8_1X16:
241c55d261eSSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_BT1120;
242c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_BT1120;
243df0a5c43SDamon Ding 		conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
244d30e58a8SDamon Ding 		break;
2456b93bf2bSWyon Bi 	case MEDIA_BUS_FMT_RGB888_1X24:
2466b93bf2bSWyon Bi 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
2476b93bf2bSWyon Bi 	default:
2489e02a86eSWyon Bi 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
249c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
2506b93bf2bSWyon Bi 		break;
2516b93bf2bSWyon Bi 	}
2529e02a86eSWyon Bi 
2539e02a86eSWyon Bi 	return 0;
2549e02a86eSWyon Bi }
2559e02a86eSWyon Bi 
2564ed82c15SDamon Ding static int rockchip_rgb_connector_mode_valid(struct rockchip_connector *conn,
2574ed82c15SDamon Ding 					     struct display_state *state)
2584ed82c15SDamon Ding {
2594ed82c15SDamon Ding 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
2604ed82c15SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
2614ed82c15SDamon Ding 	struct crtc_state *crtc_state = &state->crtc_state;
2624ed82c15SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
2634ed82c15SDamon Ding 	u32 request_clock = mode->clock;
2644ed82c15SDamon Ding 	u32 max_clock = rgb->max_dclk_rate;
2654ed82c15SDamon Ding 
2664ed82c15SDamon Ding 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
2674ed82c15SDamon Ding 		request_clock *= 2;
2684ed82c15SDamon Ding 
2694ed82c15SDamon Ding 	if (rgb->data_sync_bypass)
2704ed82c15SDamon Ding 		request_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format) *
2714ed82c15SDamon Ding 				 (crtc_state->mcu_timing.mcu_pix_total + 1);
2724ed82c15SDamon Ding 
2734ed82c15SDamon Ding 	if (max_clock != 0 && request_clock > max_clock) {
2744ed82c15SDamon Ding 		printf("mode [%dx%d] clock %d is higher than max_clock %d\n",
2754ed82c15SDamon Ding 		       mode->hdisplay, mode->vdisplay, request_clock, max_clock);
2764ed82c15SDamon Ding 		return -EINVAL;
2774ed82c15SDamon Ding 	}
2784ed82c15SDamon Ding 
2794ed82c15SDamon Ding 	return 0;
2804ed82c15SDamon Ding }
2814ed82c15SDamon Ding 
2826b9c0415SSandy Huang static const struct rockchip_connector_funcs rockchip_rgb_connector_funcs = {
2836b9c0415SSandy Huang 	.init = rockchip_rgb_connector_init,
2844ec7b4d4SSandy Huang 	.prepare = rockchip_rgb_connector_prepare,
2854ec7b4d4SSandy Huang 	.unprepare = rockchip_rgb_connector_unprepare,
2864ed82c15SDamon Ding 	.mode_valid = rockchip_rgb_connector_mode_valid,
2879e02a86eSWyon Bi };
2889e02a86eSWyon Bi 
289b5dbb15aSDamon Ding static int rockchip_mcu_panel_send_cmds(struct display_state *state,
290b5dbb15aSDamon Ding 					struct mcu_cmd_seq *cmds)
291b5dbb15aSDamon Ding {
292b5dbb15aSDamon Ding 	int i;
293b5dbb15aSDamon Ding 
294b5dbb15aSDamon Ding 	if (!cmds)
295b5dbb15aSDamon Ding 		return -EINVAL;
296b5dbb15aSDamon Ding 
297b5dbb15aSDamon Ding 	display_send_mcu_cmd(state, MCU_SETBYPASS, 1);
298b5dbb15aSDamon Ding 	for (i = 0; i < cmds->cmd_cnt; i++) {
299b5dbb15aSDamon Ding 		struct mcu_cmd_desc *desc = &cmds->cmds[i];
300b5dbb15aSDamon Ding 		int value = 0;
301b5dbb15aSDamon Ding 
302b5dbb15aSDamon Ding 		value = desc->payload[0];
303b5dbb15aSDamon Ding 		display_send_mcu_cmd(state, desc->header.data_type, value);
304b5dbb15aSDamon Ding 
305b5dbb15aSDamon Ding 		if (desc->header.delay)
306b5dbb15aSDamon Ding 			mdelay(desc->header.delay);
307b5dbb15aSDamon Ding 	}
308b5dbb15aSDamon Ding 	display_send_mcu_cmd(state, MCU_SETBYPASS, 0);
309b5dbb15aSDamon Ding 
310b5dbb15aSDamon Ding 	return 0;
311b5dbb15aSDamon Ding }
312b5dbb15aSDamon Ding 
313b5dbb15aSDamon Ding static void rockchip_mcu_panel_prepare(struct rockchip_panel *panel)
314b5dbb15aSDamon Ding {
315b5dbb15aSDamon Ding 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
316b5dbb15aSDamon Ding 	int ret;
317b5dbb15aSDamon Ding 
318b5dbb15aSDamon Ding 	if (mcu_panel->prepared)
319b5dbb15aSDamon Ding 		return;
320b5dbb15aSDamon Ding 
321b5dbb15aSDamon Ding 	if (dm_gpio_is_valid(&mcu_panel->enable_gpio))
322b5dbb15aSDamon Ding 		dm_gpio_set_value(&mcu_panel->enable_gpio, 1);
323b5dbb15aSDamon Ding 
324b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.prepare)
325b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.prepare);
326b5dbb15aSDamon Ding 
327b5dbb15aSDamon Ding 	if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
328b5dbb15aSDamon Ding 		dm_gpio_set_value(&mcu_panel->reset_gpio, 1);
329b5dbb15aSDamon Ding 
330b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.reset)
331b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.reset);
332b5dbb15aSDamon Ding 
333b5dbb15aSDamon Ding 	if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
334b5dbb15aSDamon Ding 		dm_gpio_set_value(&mcu_panel->reset_gpio, 0);
335b5dbb15aSDamon Ding 
336b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.init)
337b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.init);
338b5dbb15aSDamon Ding 
339b5dbb15aSDamon Ding 	if (mcu_panel->desc->init_seq) {
340b5dbb15aSDamon Ding 		ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->init_seq);
341b5dbb15aSDamon Ding 		if (ret)
342b5dbb15aSDamon Ding 			printf("failed to send mcu panel init cmds: %d\n", ret);
343b5dbb15aSDamon Ding 	}
344b5dbb15aSDamon Ding 
345b5dbb15aSDamon Ding 	mcu_panel->prepared = true;
346b5dbb15aSDamon Ding }
347b5dbb15aSDamon Ding 
348b5dbb15aSDamon Ding static void rockchip_mcu_panel_unprepare(struct rockchip_panel *panel)
349b5dbb15aSDamon Ding {
350b5dbb15aSDamon Ding 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
351b5dbb15aSDamon Ding 	int ret;
352b5dbb15aSDamon Ding 
353b5dbb15aSDamon Ding 	if (!mcu_panel->prepared)
354b5dbb15aSDamon Ding 		return;
355b5dbb15aSDamon Ding 
356b5dbb15aSDamon Ding 	if (mcu_panel->desc->exit_seq) {
357b5dbb15aSDamon Ding 		ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->exit_seq);
358b5dbb15aSDamon Ding 		if (ret)
359b5dbb15aSDamon Ding 			printf("failed to send mcu panel exit cmds: %d\n", ret);
360b5dbb15aSDamon Ding 	}
361b5dbb15aSDamon Ding 
362b5dbb15aSDamon Ding 	if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
363b5dbb15aSDamon Ding 		dm_gpio_set_value(&mcu_panel->reset_gpio, 1);
364b5dbb15aSDamon Ding 
365b5dbb15aSDamon Ding 	if (dm_gpio_is_valid(&mcu_panel->enable_gpio))
366b5dbb15aSDamon Ding 		dm_gpio_set_value(&mcu_panel->enable_gpio, 0);
367b5dbb15aSDamon Ding 
368b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.unprepare)
369b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.unprepare);
370b5dbb15aSDamon Ding 
371b5dbb15aSDamon Ding 	mcu_panel->prepared = false;
372b5dbb15aSDamon Ding }
373b5dbb15aSDamon Ding 
374b5dbb15aSDamon Ding static void rockchip_mcu_panel_enable(struct rockchip_panel *panel)
375b5dbb15aSDamon Ding {
376b5dbb15aSDamon Ding 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
377b5dbb15aSDamon Ding 
378b5dbb15aSDamon Ding 	if (mcu_panel->enabled)
379b5dbb15aSDamon Ding 		return;
380b5dbb15aSDamon Ding 
381b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.enable)
382b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.enable);
383b5dbb15aSDamon Ding 
384b5dbb15aSDamon Ding 	if (mcu_panel->backlight)
385b5dbb15aSDamon Ding 		backlight_enable(mcu_panel->backlight);
386b5dbb15aSDamon Ding 
387b5dbb15aSDamon Ding 	mcu_panel->enabled = true;
388b5dbb15aSDamon Ding }
389b5dbb15aSDamon Ding 
390b5dbb15aSDamon Ding static void rockchip_mcu_panel_disable(struct rockchip_panel *panel)
391b5dbb15aSDamon Ding {
392b5dbb15aSDamon Ding 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
393b5dbb15aSDamon Ding 
394b5dbb15aSDamon Ding 	if (!mcu_panel->enabled)
395b5dbb15aSDamon Ding 		return;
396b5dbb15aSDamon Ding 
397b5dbb15aSDamon Ding 	if (mcu_panel->backlight)
398b5dbb15aSDamon Ding 		backlight_disable(mcu_panel->backlight);
399b5dbb15aSDamon Ding 
400b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.disable)
401b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.disable);
402b5dbb15aSDamon Ding 
403b5dbb15aSDamon Ding 	mcu_panel->enabled = false;
404b5dbb15aSDamon Ding }
405b5dbb15aSDamon Ding 
406b5dbb15aSDamon Ding static const struct rockchip_panel_funcs rockchip_mcu_panel_funcs = {
407b5dbb15aSDamon Ding 	.prepare = rockchip_mcu_panel_prepare,
408b5dbb15aSDamon Ding 	.unprepare = rockchip_mcu_panel_unprepare,
409b5dbb15aSDamon Ding 	.enable = rockchip_mcu_panel_enable,
410b5dbb15aSDamon Ding 	.disable = rockchip_mcu_panel_disable,
411b5dbb15aSDamon Ding };
412b5dbb15aSDamon Ding 
413b5dbb15aSDamon Ding static int rockchip_mcu_panel_parse_cmds(const u8 *data, int length,
414b5dbb15aSDamon Ding 					 struct mcu_cmd_seq *pcmds)
415b5dbb15aSDamon Ding {
416b5dbb15aSDamon Ding 	int len;
417b5dbb15aSDamon Ding 	const u8 *buf;
418b5dbb15aSDamon Ding 	const struct mcu_cmd_header *header;
419b5dbb15aSDamon Ding 	int i, cnt = 0;
420b5dbb15aSDamon Ding 
421b5dbb15aSDamon Ding 	/* scan commands */
422b5dbb15aSDamon Ding 	cnt = 0;
423b5dbb15aSDamon Ding 	buf = data;
424b5dbb15aSDamon Ding 	len = length;
425b5dbb15aSDamon Ding 	while (len > sizeof(*header)) {
426b5dbb15aSDamon Ding 		header = (const struct mcu_cmd_header *)buf;
427b5dbb15aSDamon Ding 		buf += sizeof(*header) + header->payload_length;
428b5dbb15aSDamon Ding 		len -= sizeof(*header) + header->payload_length;
429b5dbb15aSDamon Ding 		cnt++;
430b5dbb15aSDamon Ding 	}
431b5dbb15aSDamon Ding 
432b5dbb15aSDamon Ding 	pcmds->cmds = calloc(cnt, sizeof(struct mcu_cmd_desc));
433b5dbb15aSDamon Ding 	if (!pcmds->cmds)
434b5dbb15aSDamon Ding 		return -ENOMEM;
435b5dbb15aSDamon Ding 
436b5dbb15aSDamon Ding 	pcmds->cmd_cnt = cnt;
437b5dbb15aSDamon Ding 
438b5dbb15aSDamon Ding 	buf = data;
439b5dbb15aSDamon Ding 	len = length;
440b5dbb15aSDamon Ding 	for (i = 0; i < cnt; i++) {
441b5dbb15aSDamon Ding 		struct mcu_cmd_desc *desc = &pcmds->cmds[i];
442b5dbb15aSDamon Ding 
443b5dbb15aSDamon Ding 		header = (const struct mcu_cmd_header *)buf;
444b5dbb15aSDamon Ding 		length -= sizeof(*header);
445b5dbb15aSDamon Ding 		buf += sizeof(*header);
446b5dbb15aSDamon Ding 		desc->header.data_type = header->data_type;
447b5dbb15aSDamon Ding 		desc->header.delay = header->delay;
448b5dbb15aSDamon Ding 		desc->header.payload_length = header->payload_length;
449b5dbb15aSDamon Ding 		desc->payload = buf;
450b5dbb15aSDamon Ding 		buf += header->payload_length;
451b5dbb15aSDamon Ding 		length -= header->payload_length;
452b5dbb15aSDamon Ding 	}
453b5dbb15aSDamon Ding 
454b5dbb15aSDamon Ding 	return 0;
455b5dbb15aSDamon Ding }
456b5dbb15aSDamon Ding 
457b5dbb15aSDamon Ding static int rockchip_mcu_panel_init(struct rockchip_mcu_panel *mcu_panel, ofnode mcu_panel_node)
458b5dbb15aSDamon Ding {
459b5dbb15aSDamon Ding 	const void *data;
460b5dbb15aSDamon Ding 	int len;
461b5dbb15aSDamon Ding 	int ret;
462b5dbb15aSDamon Ding 
463b5dbb15aSDamon Ding 	ret = gpio_request_by_name_nodev(mcu_panel_node, "enable-gpios", 0,
464b5dbb15aSDamon Ding 					 &mcu_panel->enable_gpio, GPIOD_IS_OUT);
465b5dbb15aSDamon Ding 	if (ret && ret != -ENOENT) {
466b5dbb15aSDamon Ding 		printf("%s: Cannot get mcu panel enable GPIO: %d\n", __func__, ret);
467b5dbb15aSDamon Ding 		return ret;
468b5dbb15aSDamon Ding 	}
469b5dbb15aSDamon Ding 
470b5dbb15aSDamon Ding 	ret = gpio_request_by_name_nodev(mcu_panel_node, "reset-gpios", 0,
471b5dbb15aSDamon Ding 					 &mcu_panel->reset_gpio, GPIOD_IS_OUT);
472b5dbb15aSDamon Ding 	if (ret && ret != -ENOENT) {
473b5dbb15aSDamon Ding 		printf("%s: Cannot get mcu panel reset GPIO: %d\n", __func__, ret);
474b5dbb15aSDamon Ding 		return ret;
475b5dbb15aSDamon Ding 	}
476b5dbb15aSDamon Ding 
477b5dbb15aSDamon Ding 	mcu_panel->desc = malloc(sizeof(struct rockchip_mcu_panel_desc));
478b5dbb15aSDamon Ding 	if (!mcu_panel->desc)
479b5dbb15aSDamon Ding 		return -ENOMEM;
480b5dbb15aSDamon Ding 
481b5dbb15aSDamon Ding 	mcu_panel->desc->power_invert = ofnode_read_bool(mcu_panel_node, "power-invert");
482b5dbb15aSDamon Ding 
483b5dbb15aSDamon Ding 	mcu_panel->desc->delay.prepare = ofnode_read_u32_default(mcu_panel_node, "prepare-delay-ms", 0);
484b5dbb15aSDamon Ding 	mcu_panel->desc->delay.unprepare = ofnode_read_u32_default(mcu_panel_node, "unprepare-delay-ms", 0);
485b5dbb15aSDamon Ding 	mcu_panel->desc->delay.enable = ofnode_read_u32_default(mcu_panel_node, "enable-delay-ms", 0);
486b5dbb15aSDamon Ding 	mcu_panel->desc->delay.disable = ofnode_read_u32_default(mcu_panel_node, "disable-delay-ms", 0);
487b5dbb15aSDamon Ding 	mcu_panel->desc->delay.init = ofnode_read_u32_default(mcu_panel_node, "init-delay-ms", 0);
488b5dbb15aSDamon Ding 	mcu_panel->desc->delay.reset = ofnode_read_u32_default(mcu_panel_node, "reset-delay-ms", 0);
489b5dbb15aSDamon Ding 
490b5dbb15aSDamon Ding 	mcu_panel->desc->bus_format = ofnode_read_u32_default(mcu_panel_node, "bus-format",
491b5dbb15aSDamon Ding 							      MEDIA_BUS_FMT_RBG888_1X24);
492b5dbb15aSDamon Ding 	mcu_panel->desc->bpc = ofnode_read_u32_default(mcu_panel_node, "bpc", 8);
493b5dbb15aSDamon Ding 
494b5dbb15aSDamon Ding 	data = ofnode_get_property(mcu_panel_node, "panel-init-sequence", &len);
495b5dbb15aSDamon Ding 	if (data) {
496b5dbb15aSDamon Ding 		mcu_panel->desc->init_seq = calloc(1, sizeof(*mcu_panel->desc->init_seq));
497b5dbb15aSDamon Ding 		if (!mcu_panel->desc->init_seq)
498b5dbb15aSDamon Ding 			return -ENOMEM;
499b5dbb15aSDamon Ding 
500b5dbb15aSDamon Ding 		ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->init_seq);
501b5dbb15aSDamon Ding 		if (ret) {
502b5dbb15aSDamon Ding 			printf("failed to parse panel init sequence\n");
503b5dbb15aSDamon Ding 			goto free_on_cmds;
504b5dbb15aSDamon Ding 		}
505b5dbb15aSDamon Ding 	}
506b5dbb15aSDamon Ding 
507b5dbb15aSDamon Ding 	data = ofnode_get_property(mcu_panel_node, "panel-exit-sequence", &len);
508b5dbb15aSDamon Ding 	if (data) {
509b5dbb15aSDamon Ding 		mcu_panel->desc->exit_seq = calloc(1, sizeof(*mcu_panel->desc->exit_seq));
510b5dbb15aSDamon Ding 		if (!mcu_panel->desc->exit_seq) {
511b5dbb15aSDamon Ding 			ret = -ENOMEM;
512b5dbb15aSDamon Ding 			goto free_on_cmds;
513b5dbb15aSDamon Ding 		}
514b5dbb15aSDamon Ding 
515b5dbb15aSDamon Ding 		ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->exit_seq);
516b5dbb15aSDamon Ding 		if (ret) {
517b5dbb15aSDamon Ding 			printf("failed to parse panel exit sequence\n");
518b5dbb15aSDamon Ding 			goto free_cmds;
519b5dbb15aSDamon Ding 		}
520b5dbb15aSDamon Ding 	}
521b5dbb15aSDamon Ding 
522b5dbb15aSDamon Ding 	return 0;
523b5dbb15aSDamon Ding 
524b5dbb15aSDamon Ding free_cmds:
525b5dbb15aSDamon Ding 	free(mcu_panel->desc->exit_seq);
526b5dbb15aSDamon Ding free_on_cmds:
527b5dbb15aSDamon Ding 	free(mcu_panel->desc->init_seq);
528b5dbb15aSDamon Ding 	return ret;
529b5dbb15aSDamon Ding }
530b5dbb15aSDamon Ding 
5319e02a86eSWyon Bi static int rockchip_rgb_probe(struct udevice *dev)
5329e02a86eSWyon Bi {
5336b9c0415SSandy Huang 	struct rockchip_rgb *rgb = dev_get_priv(dev);
5344ed82c15SDamon Ding 	const struct rockchip_rgb_data *rgb_data;
535b5dbb15aSDamon Ding 	ofnode mcu_panel_node;
536b5dbb15aSDamon Ding 	int phandle;
537b5dbb15aSDamon Ding 	int ret;
5389e02a86eSWyon Bi 
539406bb09aSAndy Yan 	rgb->data_sync_bypass = dev_read_bool(dev, "rockchip,data-sync-bypass");
5404ed82c15SDamon Ding 	rgb_data = (const struct rockchip_rgb_data *)dev_get_driver_data(dev);
5414ed82c15SDamon Ding 	if (rgb_data) {
5424ed82c15SDamon Ding 		rgb->funcs = rgb_data->funcs;
5434ed82c15SDamon Ding 		if (rgb->data_sync_bypass)
5444ed82c15SDamon Ding 			rgb->max_dclk_rate = rgb_data->mcu_max_dclk_rate;
5454ed82c15SDamon Ding 		else
5464ed82c15SDamon Ding 			rgb->max_dclk_rate = rgb_data->rgb_max_dclk_rate;
547*0fd9ded2SDamon Ding 		rgb->dclk_delayline = rgb_data->dclk_delayline;
5484ed82c15SDamon Ding 	}
5494ed82c15SDamon Ding 	rgb->dev = dev;
5504ed82c15SDamon Ding 	rgb->grf = syscon_get_regmap(dev_get_parent(dev));
551cb17ca6cSSandy Huang 	rgb->id = of_alias_get_id(ofnode_to_np(dev->node), "rgb");
552cb17ca6cSSandy Huang 	if (rgb->id < 0)
553cb17ca6cSSandy Huang 		rgb->id = 0;
5549e02a86eSWyon Bi 
555b5dbb15aSDamon Ding 	mcu_panel_node = dev_read_subnode(dev, "mcu-panel");
556b5dbb15aSDamon Ding 	if (ofnode_valid(mcu_panel_node) && ofnode_is_available(mcu_panel_node)) {
557b5dbb15aSDamon Ding 		struct rockchip_mcu_panel *mcu_panel;
558b5dbb15aSDamon Ding 
559b5dbb15aSDamon Ding 		mcu_panel = malloc(sizeof(struct rockchip_mcu_panel));
560b5dbb15aSDamon Ding 		if (!mcu_panel) {
561b5dbb15aSDamon Ding 			printf("failed to alloc mcu_panel data\n");
562b5dbb15aSDamon Ding 			return -ENOMEM;
563b5dbb15aSDamon Ding 		}
564b5dbb15aSDamon Ding 
565b5dbb15aSDamon Ding 		ret = rockchip_mcu_panel_init(mcu_panel, mcu_panel_node);
566b5dbb15aSDamon Ding 		if (ret < 0) {
567b5dbb15aSDamon Ding 			printf("failed to init mcu_panel: %d\n", ret);
568b5dbb15aSDamon Ding 			return ret;
569b5dbb15aSDamon Ding 		}
570b5dbb15aSDamon Ding 
571b5dbb15aSDamon Ding 		phandle = ofnode_read_u32_default(mcu_panel_node, "backlight", -1);
572b5dbb15aSDamon Ding 		if (phandle < 0) {
573b5dbb15aSDamon Ding 			printf("failed to find backlight phandle\n");
574b5dbb15aSDamon Ding 			return -EINVAL;
575b5dbb15aSDamon Ding 		}
576b5dbb15aSDamon Ding 
577b5dbb15aSDamon Ding 		ret = uclass_get_device_by_phandle_id(UCLASS_PANEL_BACKLIGHT, phandle,
578b5dbb15aSDamon Ding 						      &mcu_panel->backlight);
579b5dbb15aSDamon Ding 		if (ret && ret != -ENOENT) {
580b5dbb15aSDamon Ding 			printf("%s: failed to get backlight device: %d\n", __func__, ret);
581b5dbb15aSDamon Ding 			return ret;
582b5dbb15aSDamon Ding 		}
583b5dbb15aSDamon Ding 
584b5dbb15aSDamon Ding 		mcu_panel->base.dev = dev;
585b5dbb15aSDamon Ding 		mcu_panel->base.bus_format = mcu_panel->desc->bus_format;
586b5dbb15aSDamon Ding 		mcu_panel->base.bpc = mcu_panel->desc->bpc;
587b5dbb15aSDamon Ding 		mcu_panel->base.funcs = &rockchip_mcu_panel_funcs;
588a42af2e5SDamon Ding 		mcu_panel->enabled = false;
589a42af2e5SDamon Ding 		mcu_panel->prepared = false;
590b5dbb15aSDamon Ding 
591b5dbb15aSDamon Ding 		rgb->connector.panel = &mcu_panel->base;
592b5dbb15aSDamon Ding 	}
593b5dbb15aSDamon Ding 
5940594ce39SZhang Yubing 	rockchip_connector_bind(&rgb->connector, dev, rgb->id, &rockchip_rgb_connector_funcs,
5950594ce39SZhang Yubing 				NULL, DRM_MODE_CONNECTOR_LVDS);
5960594ce39SZhang Yubing 
5979e02a86eSWyon Bi 	return 0;
5989e02a86eSWyon Bi }
5999e02a86eSWyon Bi 
600e8dd2b64SDamon Ding static void rv1106_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
601e8dd2b64SDamon Ding {
602e8dd2b64SDamon Ding 	regmap_write(rgb->grf, RV1106_VENC_GRF_VOP_IO_WRAPPER,
603e8dd2b64SDamon Ding 		     RV1106_IO_BYPASS_SEL(rgb->data_sync_bypass ? 0x3 : 0x0));
604e8dd2b64SDamon Ding 	regmap_write(rgb->grf, RV1106_VOGRF_VOP_PIPE_BYPASS,
605e8dd2b64SDamon Ding 		     RV1106_VOP_PIPE_BYPASS(rgb->data_sync_bypass ? 0x3 : 0x0));
606e8dd2b64SDamon Ding }
607e8dd2b64SDamon Ding 
608e8dd2b64SDamon Ding static const struct rockchip_rgb_funcs rv1106_rgb_funcs = {
609e8dd2b64SDamon Ding 	.prepare = rv1106_rgb_prepare,
610e8dd2b64SDamon Ding };
611e8dd2b64SDamon Ding 
6124ed82c15SDamon Ding static const struct rockchip_rgb_data rv1106_rgb = {
6134ed82c15SDamon Ding 	.rgb_max_dclk_rate = 74250,
6144ed82c15SDamon Ding 	.mcu_max_dclk_rate = 150000,
6154ed82c15SDamon Ding 	.funcs = &rv1106_rgb_funcs,
6164ed82c15SDamon Ding };
6174ed82c15SDamon Ding 
618406bb09aSAndy Yan static void rv1126_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
619406bb09aSAndy Yan {
620406bb09aSAndy Yan 	regmap_write(rgb->grf, RV1126_GRF_IOFUNC_CON3,
621406bb09aSAndy Yan 		     RV1126_LCDC_IO_BYPASS(rgb->data_sync_bypass));
622406bb09aSAndy Yan }
623406bb09aSAndy Yan 
624406bb09aSAndy Yan static const struct rockchip_rgb_funcs rv1126_rgb_funcs = {
625406bb09aSAndy Yan 	.prepare = rv1126_rgb_prepare,
626406bb09aSAndy Yan };
627406bb09aSAndy Yan 
6284ed82c15SDamon Ding static const struct rockchip_rgb_data rv1126_rgb = {
6294ed82c15SDamon Ding 	.funcs = &rv1126_rgb_funcs,
6304ed82c15SDamon Ding };
6314ed82c15SDamon Ding 
6324ec7b4d4SSandy Huang static void px30_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
6336b9c0415SSandy Huang {
634a4878ddaSWyon Bi 	regmap_write(rgb->grf, PX30_GRF_PD_VO_CON1, PX30_RGB_VOP_SEL(pipe) |
635406bb09aSAndy Yan 		     PX30_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass));
6366b9c0415SSandy Huang }
6376b9c0415SSandy Huang 
6386b9c0415SSandy Huang static const struct rockchip_rgb_funcs px30_rgb_funcs = {
6394ec7b4d4SSandy Huang 	.prepare = px30_rgb_prepare,
6406b9c0415SSandy Huang };
6416b9c0415SSandy Huang 
6424ed82c15SDamon Ding static const struct rockchip_rgb_data px30_rgb = {
6434ed82c15SDamon Ding 	.funcs = &px30_rgb_funcs,
6444ed82c15SDamon Ding };
6454ed82c15SDamon Ding 
6464ec7b4d4SSandy Huang static void rk1808_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
6476b9c0415SSandy Huang {
6486b9c0415SSandy Huang 	regmap_write(rgb->grf, RK1808_GRF_PD_VO_CON1,
649406bb09aSAndy Yan 		     RK1808_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass));
6506b9c0415SSandy Huang }
6516b9c0415SSandy Huang 
6526b9c0415SSandy Huang static const struct rockchip_rgb_funcs rk1808_rgb_funcs = {
6534ec7b4d4SSandy Huang 	.prepare = rk1808_rgb_prepare,
6546b9c0415SSandy Huang };
6556b9c0415SSandy Huang 
6564ed82c15SDamon Ding static const struct rockchip_rgb_data rk1808_rgb = {
6574ed82c15SDamon Ding 	.funcs = &rk1808_rgb_funcs,
6584ed82c15SDamon Ding };
6594ed82c15SDamon Ding 
6604ec7b4d4SSandy Huang static void rk3288_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
66149627130SWyon Bi {
66249627130SWyon Bi 	regmap_write(rgb->grf, RK3288_GRF_SOC_CON6, RK3288_LVDS_LCDC_SEL(pipe));
66349627130SWyon Bi 	regmap_write(rgb->grf, RK3288_GRF_SOC_CON7,
66449627130SWyon Bi 		     RK3288_LVDS_PWRDWN(0) | RK3288_LVDS_CON_ENABLE_2(1) |
66549627130SWyon Bi 		     RK3288_LVDS_CON_ENABLE_1(1) | RK3288_LVDS_CON_CLKINV(0) |
66649627130SWyon Bi 		     RK3288_LVDS_CON_TTL_EN(1));
66749627130SWyon Bi }
66849627130SWyon Bi 
6694ec7b4d4SSandy Huang static void rk3288_rgb_unprepare(struct rockchip_rgb *rgb)
67049627130SWyon Bi {
67149627130SWyon Bi 	regmap_write(rgb->grf, RK3288_GRF_SOC_CON7,
67249627130SWyon Bi 		     RK3288_LVDS_PWRDWN(1) | RK3288_LVDS_CON_ENABLE_2(0) |
67349627130SWyon Bi 		     RK3288_LVDS_CON_ENABLE_1(0) | RK3288_LVDS_CON_TTL_EN(0));
67449627130SWyon Bi }
67549627130SWyon Bi 
67649627130SWyon Bi static const struct rockchip_rgb_funcs rk3288_rgb_funcs = {
6774ec7b4d4SSandy Huang 	.prepare = rk3288_rgb_prepare,
6784ec7b4d4SSandy Huang 	.unprepare = rk3288_rgb_unprepare,
67949627130SWyon Bi };
68049627130SWyon Bi 
6814ed82c15SDamon Ding static const struct rockchip_rgb_data rk3288_rgb = {
6824ed82c15SDamon Ding 	.funcs = &rk3288_rgb_funcs,
6834ed82c15SDamon Ding };
6844ed82c15SDamon Ding 
6854ec7b4d4SSandy Huang static void rk3368_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
6866383df2bSSandy Huang {
6876383df2bSSandy Huang 	regmap_write(rgb->grf, RK3368_GRF_SOC_CON15, RK3368_FORCE_JETAG(0));
6886383df2bSSandy Huang }
6896383df2bSSandy Huang 
6906383df2bSSandy Huang static const struct rockchip_rgb_funcs rk3368_rgb_funcs = {
6914ec7b4d4SSandy Huang 	.prepare = rk3368_rgb_prepare,
6926383df2bSSandy Huang };
6936383df2bSSandy Huang 
6944ed82c15SDamon Ding static const struct rockchip_rgb_data rk3368_rgb = {
6954ed82c15SDamon Ding 	.funcs = &rk3368_rgb_funcs,
6964ed82c15SDamon Ding };
6974ed82c15SDamon Ding 
698078f1c2cSDamon Ding static void rk3562_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
699078f1c2cSDamon Ding {
700078f1c2cSDamon Ding 	regmap_write(rgb->grf, RK3562_GRF_IOC_VO_IO_CON,
701078f1c2cSDamon Ding 		     RK3562_RGB_DATA_BYPASS(rgb->data_sync_bypass));
702078f1c2cSDamon Ding }
703078f1c2cSDamon Ding 
704078f1c2cSDamon Ding static const struct rockchip_rgb_funcs rk3562_rgb_funcs = {
705078f1c2cSDamon Ding 	.prepare = rk3562_rgb_prepare,
706078f1c2cSDamon Ding };
707078f1c2cSDamon Ding 
7084ed82c15SDamon Ding static const struct rockchip_rgb_data rk3562_rgb = {
7094ed82c15SDamon Ding 	.funcs = &rk3562_rgb_funcs,
7104ed82c15SDamon Ding };
7114ed82c15SDamon Ding 
712c55d261eSSandy Huang static void rk3568_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
713c55d261eSSandy Huang {
714963b371cSSandy Huang 	regmap_write(rgb->grf, RK3568_GRF_VO_CON1, RK3568_RGB_DATA_BYPASS(rgb->data_sync_bypass));
715c55d261eSSandy Huang }
716c55d261eSSandy Huang 
717c55d261eSSandy Huang static const struct rockchip_rgb_funcs rk3568_rgb_funcs = {
718c55d261eSSandy Huang 	.prepare = rk3568_rgb_prepare,
719c55d261eSSandy Huang };
720c55d261eSSandy Huang 
7214ed82c15SDamon Ding static const struct rockchip_rgb_data rk3568_rgb = {
7224ed82c15SDamon Ding 	.funcs = &rk3568_rgb_funcs,
7234ed82c15SDamon Ding };
7244ed82c15SDamon Ding 
725181a4463SDamon Ding static void rk3576_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
726181a4463SDamon Ding {
727181a4463SDamon Ding 	regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8,
728181a4463SDamon Ding 		     RK3576_VOP_MCU_SEL(rgb->data_sync_bypass));
729*0fd9ded2SDamon Ding 	regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8,
730*0fd9ded2SDamon Ding 		     RK3576_VOP_DLL_SEL(true));
731*0fd9ded2SDamon Ding 	regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8,
732*0fd9ded2SDamon Ding 		     RK3576_VOP_DCLK_DELAYLINE(rgb->dclk_delayline));
733181a4463SDamon Ding }
734181a4463SDamon Ding 
735181a4463SDamon Ding static const struct rockchip_rgb_funcs rk3576_rgb_funcs = {
736181a4463SDamon Ding 	.prepare = rk3576_rgb_prepare,
737181a4463SDamon Ding };
738181a4463SDamon Ding 
7394ed82c15SDamon Ding static const struct rockchip_rgb_data rk3576_rgb = {
740*0fd9ded2SDamon Ding 	.dclk_delayline = 5,
7414ed82c15SDamon Ding 	.funcs = &rk3576_rgb_funcs,
7424ed82c15SDamon Ding };
7434ed82c15SDamon Ding 
7449e02a86eSWyon Bi static const struct udevice_id rockchip_rgb_ids[] = {
7459e02a86eSWyon Bi 	{
7469e02a86eSWyon Bi 		.compatible = "rockchip,px30-rgb",
7474ed82c15SDamon Ding 		.data = (ulong)&px30_rgb,
7486b9c0415SSandy Huang 	},
7496b9c0415SSandy Huang 	{
7506b9c0415SSandy Huang 		.compatible = "rockchip,rk1808-rgb",
7514ed82c15SDamon Ding 		.data = (ulong)&rk1808_rgb,
7529e02a86eSWyon Bi 	},
7539e02a86eSWyon Bi 	{
7549e02a86eSWyon Bi 		.compatible = "rockchip,rk3066-rgb",
7559e02a86eSWyon Bi 	},
7569e02a86eSWyon Bi 	{
75749627130SWyon Bi 		.compatible = "rockchip,rk3128-rgb",
75849627130SWyon Bi 	},
75949627130SWyon Bi 	{
76049627130SWyon Bi 		.compatible = "rockchip,rk3288-rgb",
7614ed82c15SDamon Ding 		.data = (ulong)&rk3288_rgb,
76249627130SWyon Bi 	},
76349627130SWyon Bi 	{
7649e02a86eSWyon Bi 		.compatible = "rockchip,rk3308-rgb",
7659e02a86eSWyon Bi 	},
7669e02a86eSWyon Bi 	{
76749627130SWyon Bi 		.compatible = "rockchip,rk3368-rgb",
7684ed82c15SDamon Ding 		.data = (ulong)&rk3368_rgb,
76949627130SWyon Bi 	},
77049627130SWyon Bi 	{
771078f1c2cSDamon Ding 		.compatible = "rockchip,rk3562-rgb",
7724ed82c15SDamon Ding 		.data = (ulong)&rk3562_rgb,
773078f1c2cSDamon Ding 	},
774078f1c2cSDamon Ding 	{
775c55d261eSSandy Huang 		.compatible = "rockchip,rk3568-rgb",
7764ed82c15SDamon Ding 		.data = (ulong)&rk3568_rgb,
777c55d261eSSandy Huang 	},
778c55d261eSSandy Huang 	{
779181a4463SDamon Ding 		.compatible = "rockchip,rk3576-rgb",
7804ed82c15SDamon Ding 		.data = (ulong)&rk3576_rgb,
781181a4463SDamon Ding 	},
782181a4463SDamon Ding 	{
7839f3137bcSDamon Ding 		.compatible = "rockchip,rk3588-rgb",
7849f3137bcSDamon Ding 	},
7859f3137bcSDamon Ding 	{
786e8dd2b64SDamon Ding 		.compatible = "rockchip,rv1106-rgb",
7874ed82c15SDamon Ding 		.data = (ulong)&rv1106_rgb,
788e8dd2b64SDamon Ding 	},
789e8dd2b64SDamon Ding 	{
7909e02a86eSWyon Bi 		.compatible = "rockchip,rv1108-rgb",
7919e02a86eSWyon Bi 	},
792406bb09aSAndy Yan 	{
793406bb09aSAndy Yan 		.compatible = "rockchip,rv1126-rgb",
7944ed82c15SDamon Ding 		.data = (ulong)&rv1126_rgb,
795406bb09aSAndy Yan 	},
7969e02a86eSWyon Bi 	{}
7979e02a86eSWyon Bi };
7989e02a86eSWyon Bi 
7999e02a86eSWyon Bi U_BOOT_DRIVER(rockchip_rgb) = {
8009e02a86eSWyon Bi 	.name = "rockchip_rgb",
8019e02a86eSWyon Bi 	.id = UCLASS_DISPLAY,
8029e02a86eSWyon Bi 	.of_match = rockchip_rgb_ids,
8039e02a86eSWyon Bi 	.probe = rockchip_rgb_probe,
8046b9c0415SSandy Huang 	.priv_auto_alloc_size = sizeof(struct rockchip_rgb),
8059e02a86eSWyon Bi };
806