xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_rgb.c (revision bf2d0e5799ef55070017325d7d6459f2262ee682)
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 
2540534675SDamon Ding #define HIWORD_UPDATE(v, l, h)		(((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 
42*bf2d0e57SChaoyi Chen #define RV1126B_GRF_VOP_LCDC_CON	0x30b9c
43*bf2d0e57SChaoyi Chen #define RV1126B_VOP_MCU_SEL(v)		HIWORD_UPDATE(v, 15, 15)
44*bf2d0e57SChaoyi Chen 
4549627130SWyon Bi #define RK3288_GRF_SOC_CON6		0x025c
4649627130SWyon Bi #define RK3288_LVDS_LCDC_SEL(v)		HIWORD_UPDATE(v,  3,  3)
4749627130SWyon Bi #define RK3288_GRF_SOC_CON7		0x0260
4849627130SWyon Bi #define RK3288_LVDS_PWRDWN(v)		HIWORD_UPDATE(v, 15, 15)
4949627130SWyon Bi #define RK3288_LVDS_CON_ENABLE_2(v)	HIWORD_UPDATE(v, 12, 12)
5049627130SWyon Bi #define RK3288_LVDS_CON_ENABLE_1(v)	HIWORD_UPDATE(v, 11, 11)
5149627130SWyon Bi #define RK3288_LVDS_CON_CLKINV(v)	HIWORD_UPDATE(v,  8,  8)
5249627130SWyon Bi #define RK3288_LVDS_CON_TTL_EN(v)	HIWORD_UPDATE(v,  6,  6)
5349627130SWyon Bi 
546383df2bSSandy Huang #define RK3368_GRF_SOC_CON15		0x043c
556383df2bSSandy Huang #define RK3368_FORCE_JETAG(v)		HIWORD_UPDATE(v,  13,  13)
566383df2bSSandy Huang 
5722bf29adSDamon Ding #define RK3506_GRF_SOC_CON2		0x0008
5822bf29adSDamon Ding #define RK3506_GRF_VOP_DATA_BYPASS(v)	HIWORD_UPDATE(v, 1, 2)
5922bf29adSDamon Ding 
60078f1c2cSDamon Ding #define RK3562_GRF_IOC_VO_IO_CON	0x10500
61078f1c2cSDamon Ding #define RK3562_RGB_DATA_BYPASS(v)	HIWORD_UPDATE(v, 6, 6)
62078f1c2cSDamon Ding 
63c55d261eSSandy Huang #define RK3568_GRF_VO_CON1		0X0364
64c55d261eSSandy Huang #define RK3568_RGB_DATA_BYPASS(v)	HIWORD_UPDATE(v, 6, 6)
65c55d261eSSandy Huang 
66181a4463SDamon Ding #define RK3576_VCCIO_IOC_MISC_CON8	0x6420
67181a4463SDamon Ding #define RK3576_VOP_MCU_SEL(v)		HIWORD_UPDATE(v, 10, 10)
680fd9ded2SDamon Ding #define RK3576_VOP_DLL_SEL(v)		HIWORD_UPDATE(v, 8, 8)
690fd9ded2SDamon Ding #define RK3576_VOP_DCLK_DELAYLINE(v)	HIWORD_UPDATE(v, 0, 6)
70181a4463SDamon Ding 
716b9c0415SSandy Huang struct rockchip_rgb;
726b9c0415SSandy Huang 
736b9c0415SSandy Huang struct rockchip_rgb_funcs {
744ec7b4d4SSandy Huang 	void (*prepare)(struct rockchip_rgb *rgb, int pipe);
754ec7b4d4SSandy Huang 	void (*unprepare)(struct rockchip_rgb *rgb);
769e02a86eSWyon Bi };
779e02a86eSWyon Bi 
784ed82c15SDamon Ding struct rockchip_rgb_data {
794ed82c15SDamon Ding 	u32 rgb_max_dclk_rate;
804ed82c15SDamon Ding 	u32 mcu_max_dclk_rate;
810fd9ded2SDamon Ding 	u32 dclk_delayline;
824ed82c15SDamon Ding 	const struct rockchip_rgb_funcs *funcs;
834ed82c15SDamon Ding };
844ed82c15SDamon Ding 
856b9c0415SSandy Huang struct rockchip_rgb {
860594ce39SZhang Yubing 	struct rockchip_connector connector;
87cb17ca6cSSandy Huang 	int id;
8849627130SWyon Bi 	struct udevice *dev;
896b9c0415SSandy Huang 	struct regmap *grf;
90406bb09aSAndy Yan 	bool data_sync_bypass;
9149627130SWyon Bi 	struct rockchip_phy *phy;
926b9c0415SSandy Huang 	const struct rockchip_rgb_funcs *funcs;
934ed82c15SDamon Ding 	u32 max_dclk_rate;
940fd9ded2SDamon Ding 	u32 dclk_delayline;
956b9c0415SSandy Huang };
966b9c0415SSandy Huang 
97b5dbb15aSDamon Ding struct mcu_cmd_header {
98b5dbb15aSDamon Ding 	u8 data_type;
99b5dbb15aSDamon Ding 	u8 delay;
100b5dbb15aSDamon Ding 	u8 payload_length;
101b5dbb15aSDamon Ding } __packed;
102b5dbb15aSDamon Ding 
103b5dbb15aSDamon Ding struct mcu_cmd_desc {
104b5dbb15aSDamon Ding 	struct mcu_cmd_header header;
105b5dbb15aSDamon Ding 	const u8 *payload;
106b5dbb15aSDamon Ding };
107b5dbb15aSDamon Ding 
108b5dbb15aSDamon Ding struct mcu_cmd_seq {
109b5dbb15aSDamon Ding 	struct mcu_cmd_desc *cmds;
110b5dbb15aSDamon Ding 	unsigned int cmd_cnt;
111b5dbb15aSDamon Ding };
112b5dbb15aSDamon Ding 
113b5dbb15aSDamon Ding struct rockchip_mcu_panel_desc {
114b5dbb15aSDamon Ding 	struct mcu_cmd_seq *init_seq;
115b5dbb15aSDamon Ding 	struct mcu_cmd_seq *exit_seq;
116b5dbb15aSDamon Ding 
117b5dbb15aSDamon Ding 	struct {
118b5dbb15aSDamon Ding 		unsigned int width;
119b5dbb15aSDamon Ding 		unsigned int height;
120b5dbb15aSDamon Ding 	} size;
121b5dbb15aSDamon Ding 
122b5dbb15aSDamon Ding 	struct {
123b5dbb15aSDamon Ding 		unsigned int prepare;
124b5dbb15aSDamon Ding 		unsigned int enable;
125b5dbb15aSDamon Ding 		unsigned int disable;
126b5dbb15aSDamon Ding 		unsigned int unprepare;
127b5dbb15aSDamon Ding 		unsigned int reset;
128b5dbb15aSDamon Ding 		unsigned int init;
129b5dbb15aSDamon Ding 	} delay;
130b5dbb15aSDamon Ding 
131b5dbb15aSDamon Ding 	unsigned int bpc;
132b5dbb15aSDamon Ding 	u32 bus_format;
133b5dbb15aSDamon Ding 	u32 bus_flags;
134b5dbb15aSDamon Ding 	bool power_invert;
135b5dbb15aSDamon Ding };
136b5dbb15aSDamon Ding 
137b5dbb15aSDamon Ding struct rockchip_mcu_panel {
138b5dbb15aSDamon Ding 	struct rockchip_panel base;
139b5dbb15aSDamon Ding 	struct rockchip_mcu_panel_desc *desc;
140b5dbb15aSDamon Ding 	struct udevice *power_supply;
141b5dbb15aSDamon Ding 	struct udevice *backlight;
142b5dbb15aSDamon Ding 
143b5dbb15aSDamon Ding 	struct gpio_desc enable_gpio;
144b5dbb15aSDamon Ding 	struct gpio_desc reset_gpio;
145b5dbb15aSDamon Ding 
146b5dbb15aSDamon Ding 	bool prepared;
147b5dbb15aSDamon Ding 	bool enabled;
148b5dbb15aSDamon Ding };
149b5dbb15aSDamon Ding 
to_rockchip_mcu_panel(struct rockchip_panel * panel)150b5dbb15aSDamon Ding static inline struct rockchip_mcu_panel *to_rockchip_mcu_panel(struct rockchip_panel *panel)
151b5dbb15aSDamon Ding {
152b5dbb15aSDamon Ding 	return container_of(panel, struct rockchip_mcu_panel, base);
153b5dbb15aSDamon Ding }
154b5dbb15aSDamon Ding 
rockchip_rgb_connector_prepare(struct rockchip_connector * conn,struct display_state * state)1550594ce39SZhang Yubing static int rockchip_rgb_connector_prepare(struct rockchip_connector *conn,
1560594ce39SZhang Yubing 					  struct display_state *state)
1579e02a86eSWyon Bi {
1580594ce39SZhang Yubing 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
1599e02a86eSWyon Bi 	struct crtc_state *crtc_state = &state->crtc_state;
1609e02a86eSWyon Bi 	int pipe = crtc_state->crtc_id;
1619e3ffb10SGuochun Huang 	int ret;
1629e02a86eSWyon Bi 
163350f6a18SWyon Bi 	pinctrl_select_state(rgb->dev, "default");
164350f6a18SWyon Bi 
1654ec7b4d4SSandy Huang 	if (rgb->funcs && rgb->funcs->prepare)
1664ec7b4d4SSandy Huang 		rgb->funcs->prepare(rgb, pipe);
1679e02a86eSWyon Bi 
1689e3ffb10SGuochun Huang 	if (rgb->phy) {
1699e3ffb10SGuochun Huang 		ret = rockchip_phy_set_mode(rgb->phy, PHY_MODE_VIDEO_TTL);
1709e3ffb10SGuochun Huang 		if (ret) {
1719e3ffb10SGuochun Huang 			dev_err(rgb->dev, "failed to set phy mode: %d\n", ret);
1729e3ffb10SGuochun Huang 			return ret;
1739e3ffb10SGuochun Huang 		}
1745a7ad828SGuochun Huang 
1759e3ffb10SGuochun Huang 		rockchip_phy_power_on(rgb->phy);
1769e3ffb10SGuochun Huang 	}
17749627130SWyon Bi 
1789e02a86eSWyon Bi 	return 0;
1799e02a86eSWyon Bi }
1809e02a86eSWyon Bi 
rockchip_rgb_connector_unprepare(struct rockchip_connector * conn,struct display_state * state)1810594ce39SZhang Yubing static void rockchip_rgb_connector_unprepare(struct rockchip_connector *conn,
1820594ce39SZhang Yubing 					     struct display_state *state)
1839e02a86eSWyon Bi {
1840594ce39SZhang Yubing 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
1856b9c0415SSandy Huang 
18649627130SWyon Bi 	if (rgb->phy)
18749627130SWyon Bi 		rockchip_phy_power_off(rgb->phy);
18849627130SWyon Bi 
1894ec7b4d4SSandy Huang 	if (rgb->funcs && rgb->funcs->unprepare)
1904ec7b4d4SSandy Huang 		rgb->funcs->unprepare(rgb);
1916b9c0415SSandy Huang 
192350f6a18SWyon Bi 	pinctrl_select_state(rgb->dev, "sleep");
1939e02a86eSWyon Bi }
1949e02a86eSWyon Bi 
rockchip_rgb_connector_init(struct rockchip_connector * conn,struct display_state * state)1950594ce39SZhang Yubing static int rockchip_rgb_connector_init(struct rockchip_connector *conn, struct display_state *state)
19658c17f51SSandy Huang {
1970594ce39SZhang Yubing 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
19858c17f51SSandy Huang 	struct connector_state *conn_state = &state->conn_state;
19958c17f51SSandy Huang 
2000594ce39SZhang Yubing 	rgb->phy = conn->phy;
20149627130SWyon Bi 
202df0a5c43SDamon Ding 	conn_state->color_range = DRM_COLOR_YCBCR_FULL_RANGE;
203df0a5c43SDamon Ding 	conn_state->color_encoding = DRM_COLOR_YCBCR_BT709;
204cb17ca6cSSandy Huang 	conn_state->disp_info  = rockchip_get_disp_info(conn_state->type, rgb->id);
2059e02a86eSWyon Bi 
2066b93bf2bSWyon Bi 	switch (conn_state->bus_format) {
2076b93bf2bSWyon Bi 	case MEDIA_BUS_FMT_RGB666_1X18:
2086b93bf2bSWyon Bi 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P666;
209c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
2106b93bf2bSWyon Bi 		break;
2116b93bf2bSWyon Bi 	case MEDIA_BUS_FMT_RGB565_1X16:
2126b93bf2bSWyon Bi 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P565;
213c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
2146b93bf2bSWyon Bi 		break;
21501c3fe29SDamon Ding 	case MEDIA_BUS_FMT_RGB565_2X8_LE:
21601c3fe29SDamon Ding 	case MEDIA_BUS_FMT_BGR565_2X8_LE:
21701c3fe29SDamon Ding 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S565;
21801c3fe29SDamon Ding 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
21901c3fe29SDamon Ding 		break;
22001c3fe29SDamon Ding 	case MEDIA_BUS_FMT_RGB666_3X6:
22101c3fe29SDamon Ding 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S666;
22201c3fe29SDamon Ding 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
22301c3fe29SDamon Ding 		break;
224b7b383ebSDamon Ding 	case MEDIA_BUS_FMT_RGB888_3X8:
225b7b383ebSDamon Ding 	case MEDIA_BUS_FMT_BGR888_3X8:
226b754d470SYu YongZhen 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S888;
227c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
228b754d470SYu YongZhen 		break;
229b7b383ebSDamon Ding 	case MEDIA_BUS_FMT_RGB888_DUMMY_4X8:
230b7b383ebSDamon Ding 	case MEDIA_BUS_FMT_BGR888_DUMMY_4X8:
2314ec7b4d4SSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_S888_DUMMY;
232c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
2334ec7b4d4SSandy Huang 		break;
234c55d261eSSandy Huang 	case MEDIA_BUS_FMT_YUYV8_2X8:
235c55d261eSSandy Huang 	case MEDIA_BUS_FMT_YVYU8_2X8:
236c55d261eSSandy Huang 	case MEDIA_BUS_FMT_UYVY8_2X8:
237c55d261eSSandy Huang 	case MEDIA_BUS_FMT_VYUY8_2X8:
238c55d261eSSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_BT656;
239c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_BT656;
240df0a5c43SDamon Ding 		conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
241df0a5c43SDamon Ding 		conn_state->color_encoding = DRM_COLOR_YCBCR_BT601;
242c55d261eSSandy Huang 		break;
243c55d261eSSandy Huang 	case MEDIA_BUS_FMT_YUYV8_1X16:
244c55d261eSSandy Huang 	case MEDIA_BUS_FMT_YVYU8_1X16:
245c55d261eSSandy Huang 	case MEDIA_BUS_FMT_UYVY8_1X16:
246c55d261eSSandy Huang 	case MEDIA_BUS_FMT_VYUY8_1X16:
247c55d261eSSandy Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_BT1120;
248c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_BT1120;
249df0a5c43SDamon Ding 		conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
250d30e58a8SDamon Ding 		break;
2516b93bf2bSWyon Bi 	case MEDIA_BUS_FMT_RGB888_1X24:
2526b93bf2bSWyon Bi 	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
2536b93bf2bSWyon Bi 	default:
2549e02a86eSWyon Bi 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
255c55d261eSSandy Huang 		conn_state->output_if = VOP_OUTPUT_IF_RGB;
2566b93bf2bSWyon Bi 		break;
2576b93bf2bSWyon Bi 	}
2589e02a86eSWyon Bi 
2599e02a86eSWyon Bi 	return 0;
2609e02a86eSWyon Bi }
2619e02a86eSWyon Bi 
rockchip_rgb_connector_mode_valid(struct rockchip_connector * conn,struct display_state * state)2624ed82c15SDamon Ding static int rockchip_rgb_connector_mode_valid(struct rockchip_connector *conn,
2634ed82c15SDamon Ding 					     struct display_state *state)
2644ed82c15SDamon Ding {
2654ed82c15SDamon Ding 	struct rockchip_rgb *rgb = dev_get_priv(conn->dev);
2664ed82c15SDamon Ding 	struct connector_state *conn_state = &state->conn_state;
2674ed82c15SDamon Ding 	struct crtc_state *crtc_state = &state->crtc_state;
2684ed82c15SDamon Ding 	struct drm_display_mode *mode = &conn_state->mode;
2694ed82c15SDamon Ding 	u32 request_clock = mode->clock;
2704ed82c15SDamon Ding 	u32 max_clock = rgb->max_dclk_rate;
2714ed82c15SDamon Ding 
2724ed82c15SDamon Ding 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
2734ed82c15SDamon Ding 		request_clock *= 2;
2744ed82c15SDamon Ding 
2754ed82c15SDamon Ding 	if (rgb->data_sync_bypass)
2764ed82c15SDamon Ding 		request_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format) *
2774ed82c15SDamon Ding 				 (crtc_state->mcu_timing.mcu_pix_total + 1);
2784ed82c15SDamon Ding 
2794ed82c15SDamon Ding 	if (max_clock != 0 && request_clock > max_clock) {
2804ed82c15SDamon Ding 		printf("mode [%dx%d] clock %d is higher than max_clock %d\n",
2814ed82c15SDamon Ding 		       mode->hdisplay, mode->vdisplay, request_clock, max_clock);
2824ed82c15SDamon Ding 		return -EINVAL;
2834ed82c15SDamon Ding 	}
2844ed82c15SDamon Ding 
2854ed82c15SDamon Ding 	return 0;
2864ed82c15SDamon Ding }
2874ed82c15SDamon Ding 
2886b9c0415SSandy Huang static const struct rockchip_connector_funcs rockchip_rgb_connector_funcs = {
2896b9c0415SSandy Huang 	.init = rockchip_rgb_connector_init,
2904ec7b4d4SSandy Huang 	.prepare = rockchip_rgb_connector_prepare,
2914ec7b4d4SSandy Huang 	.unprepare = rockchip_rgb_connector_unprepare,
2924ed82c15SDamon Ding 	.mode_valid = rockchip_rgb_connector_mode_valid,
2939e02a86eSWyon Bi };
2949e02a86eSWyon Bi 
rockchip_mcu_panel_send_cmds(struct display_state * state,struct mcu_cmd_seq * cmds)295b5dbb15aSDamon Ding static int rockchip_mcu_panel_send_cmds(struct display_state *state,
296b5dbb15aSDamon Ding 					struct mcu_cmd_seq *cmds)
297b5dbb15aSDamon Ding {
298b5dbb15aSDamon Ding 	int i;
299b5dbb15aSDamon Ding 
300b5dbb15aSDamon Ding 	if (!cmds)
301b5dbb15aSDamon Ding 		return -EINVAL;
302b5dbb15aSDamon Ding 
303b5dbb15aSDamon Ding 	display_send_mcu_cmd(state, MCU_SETBYPASS, 1);
304b5dbb15aSDamon Ding 	for (i = 0; i < cmds->cmd_cnt; i++) {
305b5dbb15aSDamon Ding 		struct mcu_cmd_desc *desc = &cmds->cmds[i];
306b5dbb15aSDamon Ding 		int value = 0;
307b5dbb15aSDamon Ding 
308b5dbb15aSDamon Ding 		value = desc->payload[0];
309b5dbb15aSDamon Ding 		display_send_mcu_cmd(state, desc->header.data_type, value);
310b5dbb15aSDamon Ding 
311b5dbb15aSDamon Ding 		if (desc->header.delay)
312b5dbb15aSDamon Ding 			mdelay(desc->header.delay);
313b5dbb15aSDamon Ding 	}
314b5dbb15aSDamon Ding 	display_send_mcu_cmd(state, MCU_SETBYPASS, 0);
315b5dbb15aSDamon Ding 
316b5dbb15aSDamon Ding 	return 0;
317b5dbb15aSDamon Ding }
318b5dbb15aSDamon Ding 
rockchip_mcu_panel_prepare(struct rockchip_panel * panel)319b5dbb15aSDamon Ding static void rockchip_mcu_panel_prepare(struct rockchip_panel *panel)
320b5dbb15aSDamon Ding {
321b5dbb15aSDamon Ding 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
322b5dbb15aSDamon Ding 	int ret;
323b5dbb15aSDamon Ding 
324b5dbb15aSDamon Ding 	if (mcu_panel->prepared)
325b5dbb15aSDamon Ding 		return;
326b5dbb15aSDamon Ding 
327b5dbb15aSDamon Ding 	if (dm_gpio_is_valid(&mcu_panel->enable_gpio))
328b5dbb15aSDamon Ding 		dm_gpio_set_value(&mcu_panel->enable_gpio, 1);
329b5dbb15aSDamon Ding 
330b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.prepare)
331b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.prepare);
332b5dbb15aSDamon Ding 
333b5dbb15aSDamon Ding 	if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
334b5dbb15aSDamon Ding 		dm_gpio_set_value(&mcu_panel->reset_gpio, 1);
335b5dbb15aSDamon Ding 
336b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.reset)
337b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.reset);
338b5dbb15aSDamon Ding 
339b5dbb15aSDamon Ding 	if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
340b5dbb15aSDamon Ding 		dm_gpio_set_value(&mcu_panel->reset_gpio, 0);
341b5dbb15aSDamon Ding 
342b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.init)
343b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.init);
344b5dbb15aSDamon Ding 
345b5dbb15aSDamon Ding 	if (mcu_panel->desc->init_seq) {
346b5dbb15aSDamon Ding 		ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->init_seq);
347b5dbb15aSDamon Ding 		if (ret)
348b5dbb15aSDamon Ding 			printf("failed to send mcu panel init cmds: %d\n", ret);
349b5dbb15aSDamon Ding 	}
350b5dbb15aSDamon Ding 
351b5dbb15aSDamon Ding 	mcu_panel->prepared = true;
352b5dbb15aSDamon Ding }
353b5dbb15aSDamon Ding 
rockchip_mcu_panel_unprepare(struct rockchip_panel * panel)354b5dbb15aSDamon Ding static void rockchip_mcu_panel_unprepare(struct rockchip_panel *panel)
355b5dbb15aSDamon Ding {
356b5dbb15aSDamon Ding 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
357b5dbb15aSDamon Ding 	int ret;
358b5dbb15aSDamon Ding 
359b5dbb15aSDamon Ding 	if (!mcu_panel->prepared)
360b5dbb15aSDamon Ding 		return;
361b5dbb15aSDamon Ding 
362b5dbb15aSDamon Ding 	if (mcu_panel->desc->exit_seq) {
363b5dbb15aSDamon Ding 		ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->exit_seq);
364b5dbb15aSDamon Ding 		if (ret)
365b5dbb15aSDamon Ding 			printf("failed to send mcu panel exit cmds: %d\n", ret);
366b5dbb15aSDamon Ding 	}
367b5dbb15aSDamon Ding 
368b5dbb15aSDamon Ding 	if (dm_gpio_is_valid(&mcu_panel->reset_gpio))
369b5dbb15aSDamon Ding 		dm_gpio_set_value(&mcu_panel->reset_gpio, 1);
370b5dbb15aSDamon Ding 
371b5dbb15aSDamon Ding 	if (dm_gpio_is_valid(&mcu_panel->enable_gpio))
372b5dbb15aSDamon Ding 		dm_gpio_set_value(&mcu_panel->enable_gpio, 0);
373b5dbb15aSDamon Ding 
374b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.unprepare)
375b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.unprepare);
376b5dbb15aSDamon Ding 
377b5dbb15aSDamon Ding 	mcu_panel->prepared = false;
378b5dbb15aSDamon Ding }
379b5dbb15aSDamon Ding 
rockchip_mcu_panel_enable(struct rockchip_panel * panel)380b5dbb15aSDamon Ding static void rockchip_mcu_panel_enable(struct rockchip_panel *panel)
381b5dbb15aSDamon Ding {
382b5dbb15aSDamon Ding 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
383b5dbb15aSDamon Ding 
384b5dbb15aSDamon Ding 	if (mcu_panel->enabled)
385b5dbb15aSDamon Ding 		return;
386b5dbb15aSDamon Ding 
387b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.enable)
388b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.enable);
389b5dbb15aSDamon Ding 
390b5dbb15aSDamon Ding 	if (mcu_panel->backlight)
391b5dbb15aSDamon Ding 		backlight_enable(mcu_panel->backlight);
392b5dbb15aSDamon Ding 
393b5dbb15aSDamon Ding 	mcu_panel->enabled = true;
394b5dbb15aSDamon Ding }
395b5dbb15aSDamon Ding 
rockchip_mcu_panel_disable(struct rockchip_panel * panel)396b5dbb15aSDamon Ding static void rockchip_mcu_panel_disable(struct rockchip_panel *panel)
397b5dbb15aSDamon Ding {
398b5dbb15aSDamon Ding 	struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel);
399b5dbb15aSDamon Ding 
400b5dbb15aSDamon Ding 	if (!mcu_panel->enabled)
401b5dbb15aSDamon Ding 		return;
402b5dbb15aSDamon Ding 
403b5dbb15aSDamon Ding 	if (mcu_panel->backlight)
404b5dbb15aSDamon Ding 		backlight_disable(mcu_panel->backlight);
405b5dbb15aSDamon Ding 
406b5dbb15aSDamon Ding 	if (mcu_panel->desc->delay.disable)
407b5dbb15aSDamon Ding 		mdelay(mcu_panel->desc->delay.disable);
408b5dbb15aSDamon Ding 
409b5dbb15aSDamon Ding 	mcu_panel->enabled = false;
410b5dbb15aSDamon Ding }
411b5dbb15aSDamon Ding 
412b5dbb15aSDamon Ding static const struct rockchip_panel_funcs rockchip_mcu_panel_funcs = {
413b5dbb15aSDamon Ding 	.prepare = rockchip_mcu_panel_prepare,
414b5dbb15aSDamon Ding 	.unprepare = rockchip_mcu_panel_unprepare,
415b5dbb15aSDamon Ding 	.enable = rockchip_mcu_panel_enable,
416b5dbb15aSDamon Ding 	.disable = rockchip_mcu_panel_disable,
417b5dbb15aSDamon Ding };
418b5dbb15aSDamon Ding 
rockchip_mcu_panel_parse_cmds(const u8 * data,int length,struct mcu_cmd_seq * pcmds)419b5dbb15aSDamon Ding static int rockchip_mcu_panel_parse_cmds(const u8 *data, int length,
420b5dbb15aSDamon Ding 					 struct mcu_cmd_seq *pcmds)
421b5dbb15aSDamon Ding {
422b5dbb15aSDamon Ding 	int len;
423b5dbb15aSDamon Ding 	const u8 *buf;
424b5dbb15aSDamon Ding 	const struct mcu_cmd_header *header;
425b5dbb15aSDamon Ding 	int i, cnt = 0;
426b5dbb15aSDamon Ding 
427b5dbb15aSDamon Ding 	/* scan commands */
428b5dbb15aSDamon Ding 	cnt = 0;
429b5dbb15aSDamon Ding 	buf = data;
430b5dbb15aSDamon Ding 	len = length;
431b5dbb15aSDamon Ding 	while (len > sizeof(*header)) {
432b5dbb15aSDamon Ding 		header = (const struct mcu_cmd_header *)buf;
433b5dbb15aSDamon Ding 		buf += sizeof(*header) + header->payload_length;
434b5dbb15aSDamon Ding 		len -= sizeof(*header) + header->payload_length;
435b5dbb15aSDamon Ding 		cnt++;
436b5dbb15aSDamon Ding 	}
437b5dbb15aSDamon Ding 
438b5dbb15aSDamon Ding 	pcmds->cmds = calloc(cnt, sizeof(struct mcu_cmd_desc));
439b5dbb15aSDamon Ding 	if (!pcmds->cmds)
440b5dbb15aSDamon Ding 		return -ENOMEM;
441b5dbb15aSDamon Ding 
442b5dbb15aSDamon Ding 	pcmds->cmd_cnt = cnt;
443b5dbb15aSDamon Ding 
444b5dbb15aSDamon Ding 	buf = data;
445b5dbb15aSDamon Ding 	len = length;
446b5dbb15aSDamon Ding 	for (i = 0; i < cnt; i++) {
447b5dbb15aSDamon Ding 		struct mcu_cmd_desc *desc = &pcmds->cmds[i];
448b5dbb15aSDamon Ding 
449b5dbb15aSDamon Ding 		header = (const struct mcu_cmd_header *)buf;
450b5dbb15aSDamon Ding 		length -= sizeof(*header);
451b5dbb15aSDamon Ding 		buf += sizeof(*header);
452b5dbb15aSDamon Ding 		desc->header.data_type = header->data_type;
453b5dbb15aSDamon Ding 		desc->header.delay = header->delay;
454b5dbb15aSDamon Ding 		desc->header.payload_length = header->payload_length;
455b5dbb15aSDamon Ding 		desc->payload = buf;
456b5dbb15aSDamon Ding 		buf += header->payload_length;
457b5dbb15aSDamon Ding 		length -= header->payload_length;
458b5dbb15aSDamon Ding 	}
459b5dbb15aSDamon Ding 
460b5dbb15aSDamon Ding 	return 0;
461b5dbb15aSDamon Ding }
462b5dbb15aSDamon Ding 
rockchip_mcu_panel_init(struct rockchip_mcu_panel * mcu_panel,ofnode mcu_panel_node)463b5dbb15aSDamon Ding static int rockchip_mcu_panel_init(struct rockchip_mcu_panel *mcu_panel, ofnode mcu_panel_node)
464b5dbb15aSDamon Ding {
465b5dbb15aSDamon Ding 	const void *data;
466b5dbb15aSDamon Ding 	int len;
467b5dbb15aSDamon Ding 	int ret;
468b5dbb15aSDamon Ding 
469b5dbb15aSDamon Ding 	ret = gpio_request_by_name_nodev(mcu_panel_node, "enable-gpios", 0,
470b5dbb15aSDamon Ding 					 &mcu_panel->enable_gpio, GPIOD_IS_OUT);
471b5dbb15aSDamon Ding 	if (ret && ret != -ENOENT) {
472b5dbb15aSDamon Ding 		printf("%s: Cannot get mcu panel enable GPIO: %d\n", __func__, ret);
473b5dbb15aSDamon Ding 		return ret;
474b5dbb15aSDamon Ding 	}
475b5dbb15aSDamon Ding 
476b5dbb15aSDamon Ding 	ret = gpio_request_by_name_nodev(mcu_panel_node, "reset-gpios", 0,
477b5dbb15aSDamon Ding 					 &mcu_panel->reset_gpio, GPIOD_IS_OUT);
478b5dbb15aSDamon Ding 	if (ret && ret != -ENOENT) {
479b5dbb15aSDamon Ding 		printf("%s: Cannot get mcu panel reset GPIO: %d\n", __func__, ret);
480b5dbb15aSDamon Ding 		return ret;
481b5dbb15aSDamon Ding 	}
482b5dbb15aSDamon Ding 
483b5dbb15aSDamon Ding 	mcu_panel->desc = malloc(sizeof(struct rockchip_mcu_panel_desc));
484b5dbb15aSDamon Ding 	if (!mcu_panel->desc)
485b5dbb15aSDamon Ding 		return -ENOMEM;
486b5dbb15aSDamon Ding 
487b5dbb15aSDamon Ding 	mcu_panel->desc->power_invert = ofnode_read_bool(mcu_panel_node, "power-invert");
488b5dbb15aSDamon Ding 
489b5dbb15aSDamon Ding 	mcu_panel->desc->delay.prepare = ofnode_read_u32_default(mcu_panel_node, "prepare-delay-ms", 0);
490b5dbb15aSDamon Ding 	mcu_panel->desc->delay.unprepare = ofnode_read_u32_default(mcu_panel_node, "unprepare-delay-ms", 0);
491b5dbb15aSDamon Ding 	mcu_panel->desc->delay.enable = ofnode_read_u32_default(mcu_panel_node, "enable-delay-ms", 0);
492b5dbb15aSDamon Ding 	mcu_panel->desc->delay.disable = ofnode_read_u32_default(mcu_panel_node, "disable-delay-ms", 0);
493b5dbb15aSDamon Ding 	mcu_panel->desc->delay.init = ofnode_read_u32_default(mcu_panel_node, "init-delay-ms", 0);
494b5dbb15aSDamon Ding 	mcu_panel->desc->delay.reset = ofnode_read_u32_default(mcu_panel_node, "reset-delay-ms", 0);
495b5dbb15aSDamon Ding 
496b5dbb15aSDamon Ding 	mcu_panel->desc->bus_format = ofnode_read_u32_default(mcu_panel_node, "bus-format",
497b5dbb15aSDamon Ding 							      MEDIA_BUS_FMT_RBG888_1X24);
498b5dbb15aSDamon Ding 	mcu_panel->desc->bpc = ofnode_read_u32_default(mcu_panel_node, "bpc", 8);
499b5dbb15aSDamon Ding 
500b5dbb15aSDamon Ding 	data = ofnode_get_property(mcu_panel_node, "panel-init-sequence", &len);
501b5dbb15aSDamon Ding 	if (data) {
502b5dbb15aSDamon Ding 		mcu_panel->desc->init_seq = calloc(1, sizeof(*mcu_panel->desc->init_seq));
503b5dbb15aSDamon Ding 		if (!mcu_panel->desc->init_seq)
504b5dbb15aSDamon Ding 			return -ENOMEM;
505b5dbb15aSDamon Ding 
506b5dbb15aSDamon Ding 		ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->init_seq);
507b5dbb15aSDamon Ding 		if (ret) {
508b5dbb15aSDamon Ding 			printf("failed to parse panel init sequence\n");
509b5dbb15aSDamon Ding 			goto free_on_cmds;
510b5dbb15aSDamon Ding 		}
511b5dbb15aSDamon Ding 	}
512b5dbb15aSDamon Ding 
513b5dbb15aSDamon Ding 	data = ofnode_get_property(mcu_panel_node, "panel-exit-sequence", &len);
514b5dbb15aSDamon Ding 	if (data) {
515b5dbb15aSDamon Ding 		mcu_panel->desc->exit_seq = calloc(1, sizeof(*mcu_panel->desc->exit_seq));
516b5dbb15aSDamon Ding 		if (!mcu_panel->desc->exit_seq) {
517b5dbb15aSDamon Ding 			ret = -ENOMEM;
518b5dbb15aSDamon Ding 			goto free_on_cmds;
519b5dbb15aSDamon Ding 		}
520b5dbb15aSDamon Ding 
521b5dbb15aSDamon Ding 		ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->exit_seq);
522b5dbb15aSDamon Ding 		if (ret) {
523b5dbb15aSDamon Ding 			printf("failed to parse panel exit sequence\n");
524b5dbb15aSDamon Ding 			goto free_cmds;
525b5dbb15aSDamon Ding 		}
526b5dbb15aSDamon Ding 	}
527b5dbb15aSDamon Ding 
528b5dbb15aSDamon Ding 	return 0;
529b5dbb15aSDamon Ding 
530b5dbb15aSDamon Ding free_cmds:
531b5dbb15aSDamon Ding 	free(mcu_panel->desc->exit_seq);
532b5dbb15aSDamon Ding free_on_cmds:
533b5dbb15aSDamon Ding 	free(mcu_panel->desc->init_seq);
534b5dbb15aSDamon Ding 	return ret;
535b5dbb15aSDamon Ding }
536b5dbb15aSDamon Ding 
rockchip_rgb_probe(struct udevice * dev)5379e02a86eSWyon Bi static int rockchip_rgb_probe(struct udevice *dev)
5389e02a86eSWyon Bi {
5396b9c0415SSandy Huang 	struct rockchip_rgb *rgb = dev_get_priv(dev);
5404ed82c15SDamon Ding 	const struct rockchip_rgb_data *rgb_data;
541b5dbb15aSDamon Ding 	ofnode mcu_panel_node;
542b5dbb15aSDamon Ding 	int phandle;
543b5dbb15aSDamon Ding 	int ret;
5449e02a86eSWyon Bi 
545406bb09aSAndy Yan 	rgb->data_sync_bypass = dev_read_bool(dev, "rockchip,data-sync-bypass");
5464ed82c15SDamon Ding 	rgb_data = (const struct rockchip_rgb_data *)dev_get_driver_data(dev);
5474ed82c15SDamon Ding 	if (rgb_data) {
5484ed82c15SDamon Ding 		rgb->funcs = rgb_data->funcs;
5494ed82c15SDamon Ding 		if (rgb->data_sync_bypass)
5504ed82c15SDamon Ding 			rgb->max_dclk_rate = rgb_data->mcu_max_dclk_rate;
5514ed82c15SDamon Ding 		else
5524ed82c15SDamon Ding 			rgb->max_dclk_rate = rgb_data->rgb_max_dclk_rate;
5530fd9ded2SDamon Ding 		rgb->dclk_delayline = rgb_data->dclk_delayline;
5544ed82c15SDamon Ding 	}
5554ed82c15SDamon Ding 	rgb->dev = dev;
5564ed82c15SDamon Ding 	rgb->grf = syscon_get_regmap(dev_get_parent(dev));
557cb17ca6cSSandy Huang 	rgb->id = of_alias_get_id(ofnode_to_np(dev->node), "rgb");
558cb17ca6cSSandy Huang 	if (rgb->id < 0)
559cb17ca6cSSandy Huang 		rgb->id = 0;
5609e02a86eSWyon Bi 
561b5dbb15aSDamon Ding 	mcu_panel_node = dev_read_subnode(dev, "mcu-panel");
562b5dbb15aSDamon Ding 	if (ofnode_valid(mcu_panel_node) && ofnode_is_available(mcu_panel_node)) {
563b5dbb15aSDamon Ding 		struct rockchip_mcu_panel *mcu_panel;
564b5dbb15aSDamon Ding 
565b5dbb15aSDamon Ding 		mcu_panel = malloc(sizeof(struct rockchip_mcu_panel));
566b5dbb15aSDamon Ding 		if (!mcu_panel) {
567b5dbb15aSDamon Ding 			printf("failed to alloc mcu_panel data\n");
568b5dbb15aSDamon Ding 			return -ENOMEM;
569b5dbb15aSDamon Ding 		}
570b5dbb15aSDamon Ding 
571b5dbb15aSDamon Ding 		ret = rockchip_mcu_panel_init(mcu_panel, mcu_panel_node);
572b5dbb15aSDamon Ding 		if (ret < 0) {
573b5dbb15aSDamon Ding 			printf("failed to init mcu_panel: %d\n", ret);
574b5dbb15aSDamon Ding 			return ret;
575b5dbb15aSDamon Ding 		}
576b5dbb15aSDamon Ding 
577b5dbb15aSDamon Ding 		phandle = ofnode_read_u32_default(mcu_panel_node, "backlight", -1);
578b5dbb15aSDamon Ding 		if (phandle < 0) {
579b5dbb15aSDamon Ding 			printf("failed to find backlight phandle\n");
580b5dbb15aSDamon Ding 			return -EINVAL;
581b5dbb15aSDamon Ding 		}
582b5dbb15aSDamon Ding 
583b5dbb15aSDamon Ding 		ret = uclass_get_device_by_phandle_id(UCLASS_PANEL_BACKLIGHT, phandle,
584b5dbb15aSDamon Ding 						      &mcu_panel->backlight);
585b5dbb15aSDamon Ding 		if (ret && ret != -ENOENT) {
586b5dbb15aSDamon Ding 			printf("%s: failed to get backlight device: %d\n", __func__, ret);
587b5dbb15aSDamon Ding 			return ret;
588b5dbb15aSDamon Ding 		}
589b5dbb15aSDamon Ding 
590b5dbb15aSDamon Ding 		mcu_panel->base.dev = dev;
591b5dbb15aSDamon Ding 		mcu_panel->base.bus_format = mcu_panel->desc->bus_format;
592b5dbb15aSDamon Ding 		mcu_panel->base.bpc = mcu_panel->desc->bpc;
593b5dbb15aSDamon Ding 		mcu_panel->base.funcs = &rockchip_mcu_panel_funcs;
594a42af2e5SDamon Ding 		mcu_panel->enabled = false;
595a42af2e5SDamon Ding 		mcu_panel->prepared = false;
596b5dbb15aSDamon Ding 
597b5dbb15aSDamon Ding 		rgb->connector.panel = &mcu_panel->base;
598b5dbb15aSDamon Ding 	}
599b5dbb15aSDamon Ding 
6000594ce39SZhang Yubing 	rockchip_connector_bind(&rgb->connector, dev, rgb->id, &rockchip_rgb_connector_funcs,
6010594ce39SZhang Yubing 				NULL, DRM_MODE_CONNECTOR_LVDS);
6020594ce39SZhang Yubing 
6039e02a86eSWyon Bi 	return 0;
6049e02a86eSWyon Bi }
6059e02a86eSWyon Bi 
rv1106_rgb_prepare(struct rockchip_rgb * rgb,int pipe)606e8dd2b64SDamon Ding static void rv1106_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
607e8dd2b64SDamon Ding {
608e8dd2b64SDamon Ding 	regmap_write(rgb->grf, RV1106_VENC_GRF_VOP_IO_WRAPPER,
609e8dd2b64SDamon Ding 		     RV1106_IO_BYPASS_SEL(rgb->data_sync_bypass ? 0x3 : 0x0));
610e8dd2b64SDamon Ding 	regmap_write(rgb->grf, RV1106_VOGRF_VOP_PIPE_BYPASS,
611e8dd2b64SDamon Ding 		     RV1106_VOP_PIPE_BYPASS(rgb->data_sync_bypass ? 0x3 : 0x0));
612e8dd2b64SDamon Ding }
613e8dd2b64SDamon Ding 
614e8dd2b64SDamon Ding static const struct rockchip_rgb_funcs rv1106_rgb_funcs = {
615e8dd2b64SDamon Ding 	.prepare = rv1106_rgb_prepare,
616e8dd2b64SDamon Ding };
617e8dd2b64SDamon Ding 
6184ed82c15SDamon Ding static const struct rockchip_rgb_data rv1106_rgb = {
6194ed82c15SDamon Ding 	.rgb_max_dclk_rate = 74250,
6204ed82c15SDamon Ding 	.mcu_max_dclk_rate = 150000,
6214ed82c15SDamon Ding 	.funcs = &rv1106_rgb_funcs,
6224ed82c15SDamon Ding };
6234ed82c15SDamon Ding 
rv1126_rgb_prepare(struct rockchip_rgb * rgb,int pipe)624406bb09aSAndy Yan static void rv1126_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
625406bb09aSAndy Yan {
626406bb09aSAndy Yan 	regmap_write(rgb->grf, RV1126_GRF_IOFUNC_CON3,
627406bb09aSAndy Yan 		     RV1126_LCDC_IO_BYPASS(rgb->data_sync_bypass));
628406bb09aSAndy Yan }
629406bb09aSAndy Yan 
630406bb09aSAndy Yan static const struct rockchip_rgb_funcs rv1126_rgb_funcs = {
631406bb09aSAndy Yan 	.prepare = rv1126_rgb_prepare,
632406bb09aSAndy Yan };
633406bb09aSAndy Yan 
6344ed82c15SDamon Ding static const struct rockchip_rgb_data rv1126_rgb = {
6354ed82c15SDamon Ding 	.funcs = &rv1126_rgb_funcs,
6364ed82c15SDamon Ding };
6374ed82c15SDamon Ding 
rv1126b_rgb_prepare(struct rockchip_rgb * rgb,int pipe)638*bf2d0e57SChaoyi Chen static void rv1126b_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
639*bf2d0e57SChaoyi Chen {
640*bf2d0e57SChaoyi Chen 	regmap_write(rgb->grf, RV1126B_GRF_VOP_LCDC_CON,
641*bf2d0e57SChaoyi Chen 		     RV1126B_VOP_MCU_SEL(rgb->data_sync_bypass));
642*bf2d0e57SChaoyi Chen }
643*bf2d0e57SChaoyi Chen 
644*bf2d0e57SChaoyi Chen static const struct rockchip_rgb_funcs rv1126b_rgb_funcs = {
645*bf2d0e57SChaoyi Chen 	.prepare = rv1126b_rgb_prepare,
646*bf2d0e57SChaoyi Chen };
647*bf2d0e57SChaoyi Chen 
648*bf2d0e57SChaoyi Chen static const struct rockchip_rgb_data rv1126b_rgb = {
649*bf2d0e57SChaoyi Chen 	.rgb_max_dclk_rate = 150000,
650*bf2d0e57SChaoyi Chen 	.mcu_max_dclk_rate = 150000,
651*bf2d0e57SChaoyi Chen 	.funcs = &rv1126b_rgb_funcs,
652*bf2d0e57SChaoyi Chen };
653*bf2d0e57SChaoyi Chen 
px30_rgb_prepare(struct rockchip_rgb * rgb,int pipe)6544ec7b4d4SSandy Huang static void px30_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
6556b9c0415SSandy Huang {
656a4878ddaSWyon Bi 	regmap_write(rgb->grf, PX30_GRF_PD_VO_CON1, PX30_RGB_VOP_SEL(pipe) |
657406bb09aSAndy Yan 		     PX30_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass));
6586b9c0415SSandy Huang }
6596b9c0415SSandy Huang 
6606b9c0415SSandy Huang static const struct rockchip_rgb_funcs px30_rgb_funcs = {
6614ec7b4d4SSandy Huang 	.prepare = px30_rgb_prepare,
6626b9c0415SSandy Huang };
6636b9c0415SSandy Huang 
6644ed82c15SDamon Ding static const struct rockchip_rgb_data px30_rgb = {
6654ed82c15SDamon Ding 	.funcs = &px30_rgb_funcs,
6664ed82c15SDamon Ding };
6674ed82c15SDamon Ding 
rk1808_rgb_prepare(struct rockchip_rgb * rgb,int pipe)6684ec7b4d4SSandy Huang static void rk1808_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
6696b9c0415SSandy Huang {
6706b9c0415SSandy Huang 	regmap_write(rgb->grf, RK1808_GRF_PD_VO_CON1,
671406bb09aSAndy Yan 		     RK1808_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass));
6726b9c0415SSandy Huang }
6736b9c0415SSandy Huang 
6746b9c0415SSandy Huang static const struct rockchip_rgb_funcs rk1808_rgb_funcs = {
6754ec7b4d4SSandy Huang 	.prepare = rk1808_rgb_prepare,
6766b9c0415SSandy Huang };
6776b9c0415SSandy Huang 
6784ed82c15SDamon Ding static const struct rockchip_rgb_data rk1808_rgb = {
6794ed82c15SDamon Ding 	.funcs = &rk1808_rgb_funcs,
6804ed82c15SDamon Ding };
6814ed82c15SDamon Ding 
rk3288_rgb_prepare(struct rockchip_rgb * rgb,int pipe)6824ec7b4d4SSandy Huang static void rk3288_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
68349627130SWyon Bi {
68449627130SWyon Bi 	regmap_write(rgb->grf, RK3288_GRF_SOC_CON6, RK3288_LVDS_LCDC_SEL(pipe));
68549627130SWyon Bi 	regmap_write(rgb->grf, RK3288_GRF_SOC_CON7,
68649627130SWyon Bi 		     RK3288_LVDS_PWRDWN(0) | RK3288_LVDS_CON_ENABLE_2(1) |
68749627130SWyon Bi 		     RK3288_LVDS_CON_ENABLE_1(1) | RK3288_LVDS_CON_CLKINV(0) |
68849627130SWyon Bi 		     RK3288_LVDS_CON_TTL_EN(1));
68949627130SWyon Bi }
69049627130SWyon Bi 
rk3288_rgb_unprepare(struct rockchip_rgb * rgb)6914ec7b4d4SSandy Huang static void rk3288_rgb_unprepare(struct rockchip_rgb *rgb)
69249627130SWyon Bi {
69349627130SWyon Bi 	regmap_write(rgb->grf, RK3288_GRF_SOC_CON7,
69449627130SWyon Bi 		     RK3288_LVDS_PWRDWN(1) | RK3288_LVDS_CON_ENABLE_2(0) |
69549627130SWyon Bi 		     RK3288_LVDS_CON_ENABLE_1(0) | RK3288_LVDS_CON_TTL_EN(0));
69649627130SWyon Bi }
69749627130SWyon Bi 
69849627130SWyon Bi static const struct rockchip_rgb_funcs rk3288_rgb_funcs = {
6994ec7b4d4SSandy Huang 	.prepare = rk3288_rgb_prepare,
7004ec7b4d4SSandy Huang 	.unprepare = rk3288_rgb_unprepare,
70149627130SWyon Bi };
70249627130SWyon Bi 
7034ed82c15SDamon Ding static const struct rockchip_rgb_data rk3288_rgb = {
7044ed82c15SDamon Ding 	.funcs = &rk3288_rgb_funcs,
7054ed82c15SDamon Ding };
7064ed82c15SDamon Ding 
rk3368_rgb_prepare(struct rockchip_rgb * rgb,int pipe)7074ec7b4d4SSandy Huang static void rk3368_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
7086383df2bSSandy Huang {
7096383df2bSSandy Huang 	regmap_write(rgb->grf, RK3368_GRF_SOC_CON15, RK3368_FORCE_JETAG(0));
7106383df2bSSandy Huang }
7116383df2bSSandy Huang 
7126383df2bSSandy Huang static const struct rockchip_rgb_funcs rk3368_rgb_funcs = {
7134ec7b4d4SSandy Huang 	.prepare = rk3368_rgb_prepare,
7146383df2bSSandy Huang };
7156383df2bSSandy Huang 
7164ed82c15SDamon Ding static const struct rockchip_rgb_data rk3368_rgb = {
7174ed82c15SDamon Ding 	.funcs = &rk3368_rgb_funcs,
7184ed82c15SDamon Ding };
7194ed82c15SDamon Ding 
rk3506_rgb_prepare(struct rockchip_rgb * rgb,int pipe)72022bf29adSDamon Ding static void rk3506_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
72122bf29adSDamon Ding {
72222bf29adSDamon Ding 	regmap_write(rgb->grf, RK3506_GRF_SOC_CON2,
72322bf29adSDamon Ding 		     RK3506_GRF_VOP_DATA_BYPASS(rgb->data_sync_bypass ? 0x3 : 0x0));
72422bf29adSDamon Ding }
72522bf29adSDamon Ding 
72622bf29adSDamon Ding static const struct rockchip_rgb_funcs rk3506_rgb_funcs = {
72722bf29adSDamon Ding 	.prepare = rk3506_rgb_prepare,
72822bf29adSDamon Ding };
72922bf29adSDamon Ding 
73022bf29adSDamon Ding static const struct rockchip_rgb_data rk3506_rgb = {
73122bf29adSDamon Ding 	.rgb_max_dclk_rate = 120000,
73222bf29adSDamon Ding 	.mcu_max_dclk_rate = 120000,
73322bf29adSDamon Ding 	.funcs = &rk3506_rgb_funcs,
73422bf29adSDamon Ding };
73522bf29adSDamon Ding 
rk3562_rgb_prepare(struct rockchip_rgb * rgb,int pipe)736078f1c2cSDamon Ding static void rk3562_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
737078f1c2cSDamon Ding {
738078f1c2cSDamon Ding 	regmap_write(rgb->grf, RK3562_GRF_IOC_VO_IO_CON,
739078f1c2cSDamon Ding 		     RK3562_RGB_DATA_BYPASS(rgb->data_sync_bypass));
740078f1c2cSDamon Ding }
741078f1c2cSDamon Ding 
742078f1c2cSDamon Ding static const struct rockchip_rgb_funcs rk3562_rgb_funcs = {
743078f1c2cSDamon Ding 	.prepare = rk3562_rgb_prepare,
744078f1c2cSDamon Ding };
745078f1c2cSDamon Ding 
7464ed82c15SDamon Ding static const struct rockchip_rgb_data rk3562_rgb = {
7474ed82c15SDamon Ding 	.funcs = &rk3562_rgb_funcs,
7484ed82c15SDamon Ding };
7494ed82c15SDamon Ding 
rk3568_rgb_prepare(struct rockchip_rgb * rgb,int pipe)750c55d261eSSandy Huang static void rk3568_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
751c55d261eSSandy Huang {
752963b371cSSandy Huang 	regmap_write(rgb->grf, RK3568_GRF_VO_CON1, RK3568_RGB_DATA_BYPASS(rgb->data_sync_bypass));
753c55d261eSSandy Huang }
754c55d261eSSandy Huang 
755c55d261eSSandy Huang static const struct rockchip_rgb_funcs rk3568_rgb_funcs = {
756c55d261eSSandy Huang 	.prepare = rk3568_rgb_prepare,
757c55d261eSSandy Huang };
758c55d261eSSandy Huang 
7594ed82c15SDamon Ding static const struct rockchip_rgb_data rk3568_rgb = {
7604ed82c15SDamon Ding 	.funcs = &rk3568_rgb_funcs,
7614ed82c15SDamon Ding };
7624ed82c15SDamon Ding 
rk3576_rgb_prepare(struct rockchip_rgb * rgb,int pipe)763181a4463SDamon Ding static void rk3576_rgb_prepare(struct rockchip_rgb *rgb, int pipe)
764181a4463SDamon Ding {
765181a4463SDamon Ding 	regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8,
766181a4463SDamon Ding 		     RK3576_VOP_MCU_SEL(rgb->data_sync_bypass));
7670fd9ded2SDamon Ding 	regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8,
7680fd9ded2SDamon Ding 		     RK3576_VOP_DLL_SEL(true));
7690fd9ded2SDamon Ding 	regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8,
7700fd9ded2SDamon Ding 		     RK3576_VOP_DCLK_DELAYLINE(rgb->dclk_delayline));
771181a4463SDamon Ding }
772181a4463SDamon Ding 
773181a4463SDamon Ding static const struct rockchip_rgb_funcs rk3576_rgb_funcs = {
774181a4463SDamon Ding 	.prepare = rk3576_rgb_prepare,
775181a4463SDamon Ding };
776181a4463SDamon Ding 
7774ed82c15SDamon Ding static const struct rockchip_rgb_data rk3576_rgb = {
7780fd9ded2SDamon Ding 	.dclk_delayline = 5,
7794ed82c15SDamon Ding 	.funcs = &rk3576_rgb_funcs,
7804ed82c15SDamon Ding };
7814ed82c15SDamon Ding 
7829e02a86eSWyon Bi static const struct udevice_id rockchip_rgb_ids[] = {
7839e02a86eSWyon Bi 	{
7849e02a86eSWyon Bi 		.compatible = "rockchip,px30-rgb",
7854ed82c15SDamon Ding 		.data = (ulong)&px30_rgb,
7866b9c0415SSandy Huang 	},
7876b9c0415SSandy Huang 	{
7886b9c0415SSandy Huang 		.compatible = "rockchip,rk1808-rgb",
7894ed82c15SDamon Ding 		.data = (ulong)&rk1808_rgb,
7909e02a86eSWyon Bi 	},
7919e02a86eSWyon Bi 	{
7929e02a86eSWyon Bi 		.compatible = "rockchip,rk3066-rgb",
7939e02a86eSWyon Bi 	},
7949e02a86eSWyon Bi 	{
79549627130SWyon Bi 		.compatible = "rockchip,rk3128-rgb",
79649627130SWyon Bi 	},
79749627130SWyon Bi 	{
79849627130SWyon Bi 		.compatible = "rockchip,rk3288-rgb",
7994ed82c15SDamon Ding 		.data = (ulong)&rk3288_rgb,
80049627130SWyon Bi 	},
80149627130SWyon Bi 	{
8029e02a86eSWyon Bi 		.compatible = "rockchip,rk3308-rgb",
8039e02a86eSWyon Bi 	},
8049e02a86eSWyon Bi 	{
80549627130SWyon Bi 		.compatible = "rockchip,rk3368-rgb",
8064ed82c15SDamon Ding 		.data = (ulong)&rk3368_rgb,
80749627130SWyon Bi 	},
80849627130SWyon Bi 	{
80922bf29adSDamon Ding 		.compatible = "rockchip,rk3506-rgb",
81022bf29adSDamon Ding 		.data = (ulong)&rk3506_rgb,
81122bf29adSDamon Ding 	},
81222bf29adSDamon Ding 	{
813078f1c2cSDamon Ding 		.compatible = "rockchip,rk3562-rgb",
8144ed82c15SDamon Ding 		.data = (ulong)&rk3562_rgb,
815078f1c2cSDamon Ding 	},
816078f1c2cSDamon Ding 	{
817c55d261eSSandy Huang 		.compatible = "rockchip,rk3568-rgb",
8184ed82c15SDamon Ding 		.data = (ulong)&rk3568_rgb,
819c55d261eSSandy Huang 	},
820c55d261eSSandy Huang 	{
821181a4463SDamon Ding 		.compatible = "rockchip,rk3576-rgb",
8224ed82c15SDamon Ding 		.data = (ulong)&rk3576_rgb,
823181a4463SDamon Ding 	},
824181a4463SDamon Ding 	{
8259f3137bcSDamon Ding 		.compatible = "rockchip,rk3588-rgb",
8269f3137bcSDamon Ding 	},
8279f3137bcSDamon Ding 	{
828e8dd2b64SDamon Ding 		.compatible = "rockchip,rv1106-rgb",
8294ed82c15SDamon Ding 		.data = (ulong)&rv1106_rgb,
830e8dd2b64SDamon Ding 	},
831e8dd2b64SDamon Ding 	{
8329e02a86eSWyon Bi 		.compatible = "rockchip,rv1108-rgb",
8339e02a86eSWyon Bi 	},
834406bb09aSAndy Yan 	{
835406bb09aSAndy Yan 		.compatible = "rockchip,rv1126-rgb",
8364ed82c15SDamon Ding 		.data = (ulong)&rv1126_rgb,
837406bb09aSAndy Yan 	},
838*bf2d0e57SChaoyi Chen 	{
839*bf2d0e57SChaoyi Chen 		.compatible = "rockchip,rv1126b-rgb",
840*bf2d0e57SChaoyi Chen 		.data = (ulong)&rv1126b_rgb,
841*bf2d0e57SChaoyi Chen 	},
8429e02a86eSWyon Bi 	{}
8439e02a86eSWyon Bi };
8449e02a86eSWyon Bi 
8459e02a86eSWyon Bi U_BOOT_DRIVER(rockchip_rgb) = {
8469e02a86eSWyon Bi 	.name = "rockchip_rgb",
8479e02a86eSWyon Bi 	.id = UCLASS_DISPLAY,
8489e02a86eSWyon Bi 	.of_match = rockchip_rgb_ids,
8499e02a86eSWyon Bi 	.probe = rockchip_rgb_probe,
8506b9c0415SSandy Huang 	.priv_auto_alloc_size = sizeof(struct rockchip_rgb),
8519e02a86eSWyon Bi };
852