xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_lvds.c (revision cb17ca6c52fc044e0a9c628bc67dae1f1d83d6f4)
1186f8572SMark Yao /*
2186f8572SMark Yao  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
3186f8572SMark Yao  *
4186f8572SMark Yao  * SPDX-License-Identifier:	GPL-2.0+
5186f8572SMark Yao  */
6186f8572SMark Yao 
7186f8572SMark Yao #include <config.h>
8186f8572SMark Yao #include <common.h>
9186f8572SMark Yao #include <errno.h>
10186f8572SMark Yao #include <dm/device.h>
119aa59efbSKever Yang #include <dm/read.h>
129aa59efbSKever Yang #include <dm/ofnode.h>
13*cb17ca6cSSandy Huang #include <dm/of_access.h>
14186f8572SMark Yao #include <syscon.h>
15b69d3ed4SWyon Bi #include <regmap.h>
16b69d3ed4SWyon Bi #include <dm/device.h>
17b69d3ed4SWyon Bi #include <dm/read.h>
18b69d3ed4SWyon Bi #include <linux/media-bus-format.h>
19186f8572SMark Yao 
20186f8572SMark Yao #include "rockchip_display.h"
21186f8572SMark Yao #include "rockchip_connector.h"
22b69d3ed4SWyon Bi #include "rockchip_phy.h"
231a8d717cSWyon Bi #include "rockchip_panel.h"
241953e619SWyon Bi 
251953e619SWyon Bi #define HIWORD_UPDATE(v, h, l)		(((v) << (l)) | (GENMASK(h, l) << 16))
26186f8572SMark Yao 
27b69d3ed4SWyon Bi #define PX30_GRF_PD_VO_CON1		0x0438
28b69d3ed4SWyon Bi #define PX30_LVDS_SELECT(x)		HIWORD_UPDATE(x, 14, 13)
29b69d3ed4SWyon Bi #define PX30_LVDS_MODE_EN(x)		HIWORD_UPDATE(x, 12, 12)
30b69d3ed4SWyon Bi #define PX30_LVDS_MSBSEL(x)		HIWORD_UPDATE(x, 11, 11)
3131018a86SWyon Bi #define PX30_LVDS_P2S_EN(x)		HIWORD_UPDATE(x,  6,  6)
32b69d3ed4SWyon Bi #define PX30_LVDS_VOP_SEL(x)		HIWORD_UPDATE(x,  1,  1)
33b69d3ed4SWyon Bi 
34b69d3ed4SWyon Bi #define RK3126_GRF_LVDS_CON0		0x0150
35b69d3ed4SWyon Bi #define RK3126_LVDS_P2S_EN(x)		HIWORD_UPDATE(x,  9,  9)
36b69d3ed4SWyon Bi #define RK3126_LVDS_MODE_EN(x)		HIWORD_UPDATE(x,  6,  6)
37b69d3ed4SWyon Bi #define RK3126_LVDS_MSBSEL(x)		HIWORD_UPDATE(x,  3,  3)
38b69d3ed4SWyon Bi #define RK3126_LVDS_SELECT(x)		HIWORD_UPDATE(x,  2,  1)
39b69d3ed4SWyon Bi 
40b69d3ed4SWyon Bi #define RK3288_GRF_SOC_CON6		0x025c
41b69d3ed4SWyon Bi #define RK3288_LVDS_LCDC_SEL(x)		HIWORD_UPDATE(x,  3,  3)
42b69d3ed4SWyon Bi #define RK3288_GRF_SOC_CON7		0x0260
43b69d3ed4SWyon Bi #define RK3288_LVDS_PWRDWN(x)		HIWORD_UPDATE(x, 15, 15)
44b69d3ed4SWyon Bi #define RK3288_LVDS_CON_ENABLE_2(x)	HIWORD_UPDATE(x, 12, 12)
45b69d3ed4SWyon Bi #define RK3288_LVDS_CON_ENABLE_1(x)	HIWORD_UPDATE(x, 11, 11)
46b69d3ed4SWyon Bi #define RK3288_LVDS_CON_DEN_POL(x)	HIWORD_UPDATE(x, 10, 10)
47b69d3ed4SWyon Bi #define RK3288_LVDS_CON_HS_POL(x)	HIWORD_UPDATE(x,  9,  9)
48b69d3ed4SWyon Bi #define RK3288_LVDS_CON_CLKINV(x)	HIWORD_UPDATE(x,  8,  8)
49b69d3ed4SWyon Bi #define RK3288_LVDS_CON_STARTPHASE(x)	HIWORD_UPDATE(x,  7,  7)
50b69d3ed4SWyon Bi #define RK3288_LVDS_CON_TTL_EN(x)	HIWORD_UPDATE(x,  6,  6)
51b69d3ed4SWyon Bi #define RK3288_LVDS_CON_STARTSEL(x)	HIWORD_UPDATE(x,  5,  5)
52b69d3ed4SWyon Bi #define RK3288_LVDS_CON_CHASEL(x)	HIWORD_UPDATE(x,  4,  4)
53b69d3ed4SWyon Bi #define RK3288_LVDS_CON_MSBSEL(x)	HIWORD_UPDATE(x,  3,  3)
54b69d3ed4SWyon Bi #define RK3288_LVDS_CON_SELECT(x)	HIWORD_UPDATE(x,  2,  0)
55b69d3ed4SWyon Bi 
56b69d3ed4SWyon Bi #define RK3368_GRF_SOC_CON7		0x041c
57b69d3ed4SWyon Bi #define RK3368_LVDS_SELECT(x)		HIWORD_UPDATE(x, 14, 13)
58b69d3ed4SWyon Bi #define RK3368_LVDS_MODE_EN(x)		HIWORD_UPDATE(x, 12, 12)
59b69d3ed4SWyon Bi #define RK3368_LVDS_MSBSEL(x)		HIWORD_UPDATE(x, 11, 11)
60b69d3ed4SWyon Bi #define RK3368_LVDS_P2S_EN(x)		HIWORD_UPDATE(x,  6,  6)
61b69d3ed4SWyon Bi 
62aeb5dd22SSandy Huang #define RK3568_GRF_VO_CON0		0x0360
63aeb5dd22SSandy Huang #define RK3568_LVDS1_SELECT(x)		HIWORD_UPDATE(x, 13, 12)
64aeb5dd22SSandy Huang #define RK3568_LVDS1_MSBSEL(x)		HIWORD_UPDATE(x, 11, 11)
65aeb5dd22SSandy Huang #define RK3568_LVDS0_SELECT(x)		HIWORD_UPDATE(x,  5,  4)
66aeb5dd22SSandy Huang #define RK3568_LVDS0_MSBSEL(x)		HIWORD_UPDATE(x,  3,  3)
67aeb5dd22SSandy Huang #define RK3568_GRF_VO_CON2		0x0368
68aeb5dd22SSandy Huang #define RK3568_LVDS0_DCLK_INV_SEL(x)	HIWORD_UPDATE(x,  9,  9)
69aeb5dd22SSandy Huang #define RK3568_LVDS0_DCLK_DIV2_SEL(x)	HIWORD_UPDATE(x,  8,  8)
70aeb5dd22SSandy Huang #define RK3568_LVDS0_MODE_EN(x)		HIWORD_UPDATE(x,  1,  1)
71aeb5dd22SSandy Huang #define RK3568_LVDS0_P2S_EN(x)		HIWORD_UPDATE(x,  0,  0)
72aeb5dd22SSandy Huang #define RK3568_GRF_VO_CON3		0x036c
73aeb5dd22SSandy Huang #define RK3568_LVDS1_DCLK_INV_SEL(x)	HIWORD_UPDATE(x,  9,  9)
74aeb5dd22SSandy Huang #define RK3568_LVDS1_DCLK_DIV2_SEL(x)	HIWORD_UPDATE(x,  8,  8)
75aeb5dd22SSandy Huang #define RK3568_LVDS1_MODE_EN(x)		HIWORD_UPDATE(x,  1,  1)
76aeb5dd22SSandy Huang #define RK3568_LVDS1_P2S_EN(x)		HIWORD_UPDATE(x,  0,  0)
77aeb5dd22SSandy Huang 
78b69d3ed4SWyon Bi enum lvds_format {
79b69d3ed4SWyon Bi 	LVDS_8BIT_MODE_FORMAT_1,
80b69d3ed4SWyon Bi 	LVDS_8BIT_MODE_FORMAT_2,
81b69d3ed4SWyon Bi 	LVDS_8BIT_MODE_FORMAT_3,
82b69d3ed4SWyon Bi 	LVDS_6BIT_MODE,
83e2721f29SGuochun Huang 	LVDS_10BIT_MODE_FORMAT_1,
84e2721f29SGuochun Huang 	LVDS_10BIT_MODE_FORMAT_2,
85186f8572SMark Yao };
86186f8572SMark Yao 
87b69d3ed4SWyon Bi struct rockchip_lvds;
88b69d3ed4SWyon Bi 
89b69d3ed4SWyon Bi struct rockchip_lvds_funcs {
90b69d3ed4SWyon Bi 	void (*enable)(struct rockchip_lvds *lvds, int pipe);
91b69d3ed4SWyon Bi 	void (*disable)(struct rockchip_lvds *lvds);
92186f8572SMark Yao };
93186f8572SMark Yao 
94b69d3ed4SWyon Bi struct rockchip_lvds {
95*cb17ca6cSSandy Huang 	int id;
96b69d3ed4SWyon Bi 	struct udevice *dev;
97b69d3ed4SWyon Bi 	struct regmap *grf;
98b69d3ed4SWyon Bi 	struct rockchip_phy *phy;
99b69d3ed4SWyon Bi 	const struct drm_display_mode *mode;
100b69d3ed4SWyon Bi 	const struct rockchip_lvds_funcs *funcs;
101b69d3ed4SWyon Bi 	enum lvds_format format;
102b69d3ed4SWyon Bi 	bool data_swap;
103b69d3ed4SWyon Bi 	bool dual_channel;
104186f8572SMark Yao };
105186f8572SMark Yao 
106b69d3ed4SWyon Bi static inline struct rockchip_lvds *state_to_lvds(struct display_state *state)
107186f8572SMark Yao {
108186f8572SMark Yao 	struct connector_state *conn_state = &state->conn_state;
109186f8572SMark Yao 
110b69d3ed4SWyon Bi 	return dev_get_priv(conn_state->dev);
111186f8572SMark Yao }
112186f8572SMark Yao 
11358c17f51SSandy Huang static int rockchip_lvds_connector_pre_init(struct display_state *state)
11458c17f51SSandy Huang {
11558c17f51SSandy Huang 	struct connector_state *conn_state = &state->conn_state;
11658c17f51SSandy Huang 
11758c17f51SSandy Huang 	conn_state->type = DRM_MODE_CONNECTOR_LVDS;
11858c17f51SSandy Huang 
11958c17f51SSandy Huang 	return 0;
12058c17f51SSandy Huang }
12158c17f51SSandy Huang 
122b69d3ed4SWyon Bi static int rockchip_lvds_connector_init(struct display_state *state)
123186f8572SMark Yao {
124b69d3ed4SWyon Bi 	struct rockchip_lvds *lvds = state_to_lvds(state);
125186f8572SMark Yao 	struct connector_state *conn_state = &state->conn_state;
1261a8d717cSWyon Bi 	struct rockchip_panel *panel = state_get_panel(state);
127186f8572SMark Yao 
128b69d3ed4SWyon Bi 	lvds->mode = &conn_state->mode;
129b69d3ed4SWyon Bi 	lvds->phy = conn_state->phy;
130*cb17ca6cSSandy Huang 	conn_state->disp_info  = rockchip_get_disp_info(conn_state->type, lvds->id);
131186f8572SMark Yao 
132b69d3ed4SWyon Bi 	switch (panel->bus_format) {
1334888f8a4SWyon Bi 	case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:	/* jeida-18 */
134b69d3ed4SWyon Bi 		lvds->format = LVDS_6BIT_MODE;
135b69d3ed4SWyon Bi 		break;
136b69d3ed4SWyon Bi 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:	/* jeida-24 */
137b69d3ed4SWyon Bi 		lvds->format = LVDS_8BIT_MODE_FORMAT_2;
138b69d3ed4SWyon Bi 		break;
139e2721f29SGuochun Huang 	case MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA: /* jeida-30 */
140e2721f29SGuochun Huang 		lvds->format = LVDS_10BIT_MODE_FORMAT_1;
1414888f8a4SWyon Bi 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:	/* vesa-18 */
1424888f8a4SWyon Bi 		lvds->format = LVDS_8BIT_MODE_FORMAT_3;
1434888f8a4SWyon Bi 		break;
144e2721f29SGuochun Huang 	case MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG: /* vesa-30 */
145e2721f29SGuochun Huang 		lvds->format = LVDS_10BIT_MODE_FORMAT_2;
146e2721f29SGuochun Huang 		break;
147b69d3ed4SWyon Bi 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:	/* vesa-24 */
148b69d3ed4SWyon Bi 	default:
149b69d3ed4SWyon Bi 		lvds->format = LVDS_8BIT_MODE_FORMAT_1;
150b69d3ed4SWyon Bi 		break;
151186f8572SMark Yao 	}
152186f8572SMark Yao 
153186f8572SMark Yao 	conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
154e2721f29SGuochun Huang 
155e2721f29SGuochun Huang 	if ((lvds->format == LVDS_10BIT_MODE_FORMAT_1) ||
156e2721f29SGuochun Huang 		(lvds->format == LVDS_10BIT_MODE_FORMAT_2))
157e2721f29SGuochun Huang 		conn_state->output_mode = ROCKCHIP_OUT_MODE_AAAA;
158e2721f29SGuochun Huang 
15979feefb1SSandy Huang 	conn_state->color_space = V4L2_COLORSPACE_DEFAULT;
160aeb5dd22SSandy Huang 	conn_state->output_if = VOP_OUTPUT_IF_LVDS0;
161186f8572SMark Yao 
162186f8572SMark Yao 	return 0;
163186f8572SMark Yao }
164186f8572SMark Yao 
165b69d3ed4SWyon Bi static int rockchip_lvds_connector_enable(struct display_state *state)
166186f8572SMark Yao {
167b69d3ed4SWyon Bi 	struct rockchip_lvds *lvds = state_to_lvds(state);
168b69d3ed4SWyon Bi 	struct crtc_state *crtc_state = &state->crtc_state;
169b69d3ed4SWyon Bi 	int pipe = crtc_state->crtc_id;
170b69d3ed4SWyon Bi 	int ret;
171186f8572SMark Yao 
172b69d3ed4SWyon Bi 	if (lvds->funcs->enable)
173b69d3ed4SWyon Bi 		lvds->funcs->enable(lvds, pipe);
174b69d3ed4SWyon Bi 
175b69d3ed4SWyon Bi 	ret = rockchip_phy_set_mode(lvds->phy, PHY_MODE_VIDEO_LVDS);
176b69d3ed4SWyon Bi 	if (ret) {
177b69d3ed4SWyon Bi 		dev_err(lvds->dev, "failed to set phy mode: %d\n", ret);
178b69d3ed4SWyon Bi 		return ret;
179186f8572SMark Yao 	}
180186f8572SMark Yao 
181b69d3ed4SWyon Bi 	rockchip_phy_power_on(lvds->phy);
182186f8572SMark Yao 
183186f8572SMark Yao 	return 0;
184186f8572SMark Yao }
185186f8572SMark Yao 
186b69d3ed4SWyon Bi static int rockchip_lvds_connector_disable(struct display_state *state)
187186f8572SMark Yao {
188b69d3ed4SWyon Bi 	struct rockchip_lvds *lvds = state_to_lvds(state);
189b69d3ed4SWyon Bi 
190b69d3ed4SWyon Bi 	rockchip_phy_power_off(lvds->phy);
191b69d3ed4SWyon Bi 
192b69d3ed4SWyon Bi 	if (lvds->funcs->disable)
193b69d3ed4SWyon Bi 		lvds->funcs->disable(lvds);
194b69d3ed4SWyon Bi 
195b69d3ed4SWyon Bi 	return 0;
196b69d3ed4SWyon Bi }
197b69d3ed4SWyon Bi 
198b69d3ed4SWyon Bi static const struct rockchip_connector_funcs rockchip_lvds_connector_funcs = {
19958c17f51SSandy Huang 	.pre_init = rockchip_lvds_connector_pre_init,
200b69d3ed4SWyon Bi 	.init = rockchip_lvds_connector_init,
201b69d3ed4SWyon Bi 	.enable = rockchip_lvds_connector_enable,
202b69d3ed4SWyon Bi 	.disable = rockchip_lvds_connector_disable,
203b69d3ed4SWyon Bi };
204b69d3ed4SWyon Bi 
205b69d3ed4SWyon Bi static int rockchip_lvds_probe(struct udevice *dev)
206b69d3ed4SWyon Bi {
207b69d3ed4SWyon Bi 	struct rockchip_lvds *lvds = dev_get_priv(dev);
208b69d3ed4SWyon Bi 	const struct rockchip_connector *connector =
209b69d3ed4SWyon Bi 		(const struct rockchip_connector *)dev_get_driver_data(dev);
210b69d3ed4SWyon Bi 
211b69d3ed4SWyon Bi 	lvds->dev = dev;
212b69d3ed4SWyon Bi 	lvds->funcs = connector->data;
213b69d3ed4SWyon Bi 	lvds->grf = syscon_get_regmap(dev_get_parent(dev));
214b69d3ed4SWyon Bi 	lvds->dual_channel = dev_read_bool(dev, "dual-channel");
215b69d3ed4SWyon Bi 	lvds->data_swap = dev_read_bool(dev, "rockchip,data-swap");
216*cb17ca6cSSandy Huang 	lvds->id = of_alias_get_id(ofnode_to_np(dev->node), "lvds");
217*cb17ca6cSSandy Huang 	if (lvds->id < 0)
218*cb17ca6cSSandy Huang 		lvds->id = 0;
219b69d3ed4SWyon Bi 
220b69d3ed4SWyon Bi 	return 0;
221b69d3ed4SWyon Bi }
222b69d3ed4SWyon Bi 
223b69d3ed4SWyon Bi static void px30_lvds_enable(struct rockchip_lvds *lvds, int pipe)
224b69d3ed4SWyon Bi {
225b69d3ed4SWyon Bi 	regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1,
226b69d3ed4SWyon Bi 		     PX30_LVDS_SELECT(lvds->format) |
227b69d3ed4SWyon Bi 		     PX30_LVDS_MODE_EN(1) | PX30_LVDS_MSBSEL(1) |
228b69d3ed4SWyon Bi 		     PX30_LVDS_P2S_EN(1) | PX30_LVDS_VOP_SEL(pipe));
229b69d3ed4SWyon Bi }
230b69d3ed4SWyon Bi 
231b69d3ed4SWyon Bi static void px30_lvds_disable(struct rockchip_lvds *lvds)
232b69d3ed4SWyon Bi {
233b69d3ed4SWyon Bi 	regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1,
234b69d3ed4SWyon Bi 		     PX30_LVDS_MODE_EN(0) | PX30_LVDS_P2S_EN(0));
235b69d3ed4SWyon Bi }
236b69d3ed4SWyon Bi 
237b69d3ed4SWyon Bi static const struct rockchip_lvds_funcs px30_lvds_funcs = {
238b69d3ed4SWyon Bi 	.enable = px30_lvds_enable,
239b69d3ed4SWyon Bi 	.disable = px30_lvds_disable,
240b69d3ed4SWyon Bi };
241b69d3ed4SWyon Bi 
242b69d3ed4SWyon Bi static const struct rockchip_connector px30_lvds_driver_data = {
243b69d3ed4SWyon Bi 	 .funcs = &rockchip_lvds_connector_funcs,
244b69d3ed4SWyon Bi 	 .data = &px30_lvds_funcs,
245b69d3ed4SWyon Bi };
246b69d3ed4SWyon Bi 
247b69d3ed4SWyon Bi static void rk3126_lvds_enable(struct rockchip_lvds *lvds, int pipe)
248b69d3ed4SWyon Bi {
249b69d3ed4SWyon Bi 	regmap_write(lvds->grf, RK3126_GRF_LVDS_CON0,
250b69d3ed4SWyon Bi 		     RK3126_LVDS_P2S_EN(1) | RK3126_LVDS_MODE_EN(1) |
251b69d3ed4SWyon Bi 		     RK3126_LVDS_MSBSEL(1) | RK3126_LVDS_SELECT(lvds->format));
252b69d3ed4SWyon Bi }
253b69d3ed4SWyon Bi 
254b69d3ed4SWyon Bi static void rk3126_lvds_disable(struct rockchip_lvds *lvds)
255b69d3ed4SWyon Bi {
256b69d3ed4SWyon Bi 	regmap_write(lvds->grf, RK3126_GRF_LVDS_CON0,
257b69d3ed4SWyon Bi 		     RK3126_LVDS_P2S_EN(0) | RK3126_LVDS_MODE_EN(0));
258b69d3ed4SWyon Bi }
259b69d3ed4SWyon Bi 
260b69d3ed4SWyon Bi static const struct rockchip_lvds_funcs rk3126_lvds_funcs = {
261b69d3ed4SWyon Bi 	.enable = rk3126_lvds_enable,
262b69d3ed4SWyon Bi 	.disable = rk3126_lvds_disable,
263b69d3ed4SWyon Bi };
264b69d3ed4SWyon Bi 
265b69d3ed4SWyon Bi static const struct rockchip_connector rk3126_lvds_driver_data = {
266b69d3ed4SWyon Bi 	 .funcs = &rockchip_lvds_connector_funcs,
267b69d3ed4SWyon Bi 	 .data = &rk3126_lvds_funcs,
268b69d3ed4SWyon Bi };
269b69d3ed4SWyon Bi 
270b69d3ed4SWyon Bi static void rk3288_lvds_enable(struct rockchip_lvds *lvds, int pipe)
271b69d3ed4SWyon Bi {
272b69d3ed4SWyon Bi 	const struct drm_display_mode *mode = lvds->mode;
273186f8572SMark Yao 	u32 val;
274186f8572SMark Yao 
275b69d3ed4SWyon Bi 	regmap_write(lvds->grf, RK3288_GRF_SOC_CON6,
276b69d3ed4SWyon Bi 		     RK3288_LVDS_LCDC_SEL(pipe));
277b69d3ed4SWyon Bi 
278b69d3ed4SWyon Bi 	val = RK3288_LVDS_PWRDWN(0) | RK3288_LVDS_CON_CLKINV(0) |
279b69d3ed4SWyon Bi 	      RK3288_LVDS_CON_CHASEL(lvds->dual_channel) |
280b69d3ed4SWyon Bi 	      RK3288_LVDS_CON_SELECT(lvds->format);
281b69d3ed4SWyon Bi 
282b69d3ed4SWyon Bi 	if (lvds->dual_channel) {
283b69d3ed4SWyon Bi 		u32 h_bp = mode->htotal - mode->hsync_start;
284b69d3ed4SWyon Bi 
285b69d3ed4SWyon Bi 		val |= RK3288_LVDS_CON_ENABLE_2(1) |
286b69d3ed4SWyon Bi 		       RK3288_LVDS_CON_ENABLE_1(1) |
287b69d3ed4SWyon Bi 		       RK3288_LVDS_CON_STARTSEL(lvds->data_swap);
288b69d3ed4SWyon Bi 
289b69d3ed4SWyon Bi 		if (h_bp % 2)
290b69d3ed4SWyon Bi 			val |= RK3288_LVDS_CON_STARTPHASE(1);
291186f8572SMark Yao 		else
292b69d3ed4SWyon Bi 			val |= RK3288_LVDS_CON_STARTPHASE(0);
293186f8572SMark Yao 	} else {
294b69d3ed4SWyon Bi 		val |= RK3288_LVDS_CON_ENABLE_2(0) |
295b69d3ed4SWyon Bi 		       RK3288_LVDS_CON_ENABLE_1(1);
296186f8572SMark Yao 	}
297186f8572SMark Yao 
298b69d3ed4SWyon Bi 	regmap_write(lvds->grf, RK3288_GRF_SOC_CON7, val);
299b69d3ed4SWyon Bi 
300b69d3ed4SWyon Bi 	rockchip_phy_set_bus_width(lvds->phy, lvds->dual_channel ? 2 : 1);
301186f8572SMark Yao }
302186f8572SMark Yao 
303b69d3ed4SWyon Bi static void rk3288_lvds_disable(struct rockchip_lvds *lvds)
304186f8572SMark Yao {
305b69d3ed4SWyon Bi 	regmap_write(lvds->grf, RK3288_GRF_SOC_CON7, RK3288_LVDS_PWRDWN(1));
306186f8572SMark Yao }
307186f8572SMark Yao 
308b69d3ed4SWyon Bi static const struct rockchip_lvds_funcs rk3288_lvds_funcs = {
309b69d3ed4SWyon Bi 	.enable = rk3288_lvds_enable,
310b69d3ed4SWyon Bi 	.disable = rk3288_lvds_disable,
311186f8572SMark Yao };
312186f8572SMark Yao 
313b69d3ed4SWyon Bi static const struct rockchip_connector rk3288_lvds_driver_data = {
314b69d3ed4SWyon Bi 	 .funcs = &rockchip_lvds_connector_funcs,
315b69d3ed4SWyon Bi 	 .data = &rk3288_lvds_funcs,
316186f8572SMark Yao };
317186f8572SMark Yao 
318b69d3ed4SWyon Bi static void rk3368_lvds_enable(struct rockchip_lvds *lvds, int pipe)
319b69d3ed4SWyon Bi {
320b69d3ed4SWyon Bi 	regmap_write(lvds->grf, RK3368_GRF_SOC_CON7,
321b69d3ed4SWyon Bi 		     RK3368_LVDS_SELECT(lvds->format) |
322b69d3ed4SWyon Bi 		     RK3368_LVDS_MODE_EN(1) | RK3368_LVDS_MSBSEL(1) |
323b69d3ed4SWyon Bi 		     RK3368_LVDS_P2S_EN(1));
324b69d3ed4SWyon Bi }
325b69d3ed4SWyon Bi 
326b69d3ed4SWyon Bi static void rk3368_lvds_disable(struct rockchip_lvds *lvds)
327b69d3ed4SWyon Bi {
328b69d3ed4SWyon Bi 	regmap_write(lvds->grf, RK3368_GRF_SOC_CON7,
329b69d3ed4SWyon Bi 		     RK3368_LVDS_MODE_EN(0) | RK3368_LVDS_P2S_EN(0));
330b69d3ed4SWyon Bi }
331b69d3ed4SWyon Bi 
332b69d3ed4SWyon Bi static const struct rockchip_lvds_funcs rk3368_lvds_funcs = {
333b69d3ed4SWyon Bi 	.enable = rk3368_lvds_enable,
334b69d3ed4SWyon Bi 	.disable = rk3368_lvds_disable,
33530d6d433SWyon Bi };
33630d6d433SWyon Bi 
337b69d3ed4SWyon Bi static const struct rockchip_connector rk3368_lvds_driver_data = {
338b69d3ed4SWyon Bi 	 .funcs = &rockchip_lvds_connector_funcs,
339b69d3ed4SWyon Bi 	 .data = &rk3368_lvds_funcs,
34030d6d433SWyon Bi };
34130d6d433SWyon Bi 
342aeb5dd22SSandy Huang static void rk3568_lvds_enable(struct rockchip_lvds *lvds, int pipe)
343aeb5dd22SSandy Huang {
344aeb5dd22SSandy Huang 	regmap_write(lvds->grf, RK3568_GRF_VO_CON2,
345aeb5dd22SSandy Huang 		     RK3568_LVDS0_MODE_EN(1) | RK3568_LVDS0_P2S_EN(1) |
346aeb5dd22SSandy Huang 		     RK3568_LVDS0_DCLK_INV_SEL(1));
347aeb5dd22SSandy Huang 	regmap_write(lvds->grf, RK3568_GRF_VO_CON0,
348aeb5dd22SSandy Huang 		     RK3568_LVDS0_SELECT(lvds->format) | RK3568_LVDS0_MSBSEL(1));
349aeb5dd22SSandy Huang }
350aeb5dd22SSandy Huang 
351aeb5dd22SSandy Huang static void rk3568_lvds_disable(struct rockchip_lvds *lvds)
352aeb5dd22SSandy Huang {
353aeb5dd22SSandy Huang 	regmap_write(lvds->grf, RK3568_GRF_VO_CON2, RK3568_LVDS0_MODE_EN(0));
354aeb5dd22SSandy Huang }
355aeb5dd22SSandy Huang 
356aeb5dd22SSandy Huang static const struct rockchip_lvds_funcs rk3568_lvds_funcs = {
357aeb5dd22SSandy Huang 	.enable = rk3568_lvds_enable,
358aeb5dd22SSandy Huang 	.disable = rk3568_lvds_disable,
359aeb5dd22SSandy Huang };
360aeb5dd22SSandy Huang 
361aeb5dd22SSandy Huang static const struct rockchip_connector rk3568_lvds_driver_data = {
362aeb5dd22SSandy Huang 	.funcs = &rockchip_lvds_connector_funcs,
363aeb5dd22SSandy Huang 	.data = &rk3568_lvds_funcs,
364aeb5dd22SSandy Huang };
365aeb5dd22SSandy Huang 
366186f8572SMark Yao static const struct udevice_id rockchip_lvds_ids[] = {
367186f8572SMark Yao 	{
36830d6d433SWyon Bi 		.compatible = "rockchip,px30-lvds",
369b69d3ed4SWyon Bi 		.data = (ulong)&px30_lvds_driver_data,
37030d6d433SWyon Bi 	},
37130d6d433SWyon Bi 	{
37230d6d433SWyon Bi 		.compatible = "rockchip,rk3126-lvds",
373b69d3ed4SWyon Bi 		.data = (ulong)&rk3126_lvds_driver_data,
37430d6d433SWyon Bi 	},
37530d6d433SWyon Bi 	{
37630d6d433SWyon Bi 		.compatible = "rockchip,rk3288-lvds",
377b69d3ed4SWyon Bi 		.data = (ulong)&rk3288_lvds_driver_data,
37830d6d433SWyon Bi 	},
37930d6d433SWyon Bi 	{
380186f8572SMark Yao 		.compatible = "rockchip,rk3368-lvds",
381b69d3ed4SWyon Bi 		.data = (ulong)&rk3368_lvds_driver_data,
38230d6d433SWyon Bi 	},
383aeb5dd22SSandy Huang 	{
384aeb5dd22SSandy Huang 		.compatible = "rockchip,rk3568-lvds",
385aeb5dd22SSandy Huang 		.data = (ulong)&rk3568_lvds_driver_data,
386aeb5dd22SSandy Huang 	},
38730d6d433SWyon Bi 	{}
388186f8572SMark Yao };
389186f8572SMark Yao 
390186f8572SMark Yao U_BOOT_DRIVER(rockchip_lvds) = {
391186f8572SMark Yao 	.name = "rockchip_lvds",
392186f8572SMark Yao 	.id = UCLASS_DISPLAY,
393186f8572SMark Yao 	.of_match = rockchip_lvds_ids,
394b69d3ed4SWyon Bi 	.probe = rockchip_lvds_probe,
395b69d3ed4SWyon Bi 	.priv_auto_alloc_size = sizeof(struct rockchip_lvds),
396186f8572SMark Yao };
397