xref: /OK3568_Linux_fs/u-boot/drivers/video/drm/rockchip_lvds.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <config.h>
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <errno.h>
10*4882a593Smuzhiyun #include <dm/device.h>
11*4882a593Smuzhiyun #include <dm/read.h>
12*4882a593Smuzhiyun #include <dm/ofnode.h>
13*4882a593Smuzhiyun #include <dm/of_access.h>
14*4882a593Smuzhiyun #include <syscon.h>
15*4882a593Smuzhiyun #include <regmap.h>
16*4882a593Smuzhiyun #include <dm/device.h>
17*4882a593Smuzhiyun #include <dm/read.h>
18*4882a593Smuzhiyun #include <linux/media-bus-format.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include "rockchip_display.h"
21*4882a593Smuzhiyun #include "rockchip_connector.h"
22*4882a593Smuzhiyun #include "rockchip_phy.h"
23*4882a593Smuzhiyun #include "rockchip_panel.h"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define HIWORD_UPDATE(v, h, l)		(((v) << (l)) | (GENMASK(h, l) << 16))
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define PX30_GRF_PD_VO_CON1		0x0438
28*4882a593Smuzhiyun #define PX30_LVDS_SELECT(x)		HIWORD_UPDATE(x, 14, 13)
29*4882a593Smuzhiyun #define PX30_LVDS_MODE_EN(x)		HIWORD_UPDATE(x, 12, 12)
30*4882a593Smuzhiyun #define PX30_LVDS_MSBSEL(x)		HIWORD_UPDATE(x, 11, 11)
31*4882a593Smuzhiyun #define PX30_LVDS_P2S_EN(x)		HIWORD_UPDATE(x,  6,  6)
32*4882a593Smuzhiyun #define PX30_LVDS_VOP_SEL(x)		HIWORD_UPDATE(x,  1,  1)
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define RK3126_GRF_LVDS_CON0		0x0150
35*4882a593Smuzhiyun #define RK3126_LVDS_P2S_EN(x)		HIWORD_UPDATE(x,  9,  9)
36*4882a593Smuzhiyun #define RK3126_LVDS_MODE_EN(x)		HIWORD_UPDATE(x,  6,  6)
37*4882a593Smuzhiyun #define RK3126_LVDS_MSBSEL(x)		HIWORD_UPDATE(x,  3,  3)
38*4882a593Smuzhiyun #define RK3126_LVDS_SELECT(x)		HIWORD_UPDATE(x,  2,  1)
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #define RK3288_GRF_SOC_CON6		0x025c
41*4882a593Smuzhiyun #define RK3288_LVDS_LCDC_SEL(x)		HIWORD_UPDATE(x,  3,  3)
42*4882a593Smuzhiyun #define RK3288_GRF_SOC_CON7		0x0260
43*4882a593Smuzhiyun #define RK3288_LVDS_PWRDWN(x)		HIWORD_UPDATE(x, 15, 15)
44*4882a593Smuzhiyun #define RK3288_LVDS_CON_ENABLE_2(x)	HIWORD_UPDATE(x, 12, 12)
45*4882a593Smuzhiyun #define RK3288_LVDS_CON_ENABLE_1(x)	HIWORD_UPDATE(x, 11, 11)
46*4882a593Smuzhiyun #define RK3288_LVDS_CON_DEN_POL(x)	HIWORD_UPDATE(x, 10, 10)
47*4882a593Smuzhiyun #define RK3288_LVDS_CON_HS_POL(x)	HIWORD_UPDATE(x,  9,  9)
48*4882a593Smuzhiyun #define RK3288_LVDS_CON_CLKINV(x)	HIWORD_UPDATE(x,  8,  8)
49*4882a593Smuzhiyun #define RK3288_LVDS_CON_STARTPHASE(x)	HIWORD_UPDATE(x,  7,  7)
50*4882a593Smuzhiyun #define RK3288_LVDS_CON_TTL_EN(x)	HIWORD_UPDATE(x,  6,  6)
51*4882a593Smuzhiyun #define RK3288_LVDS_CON_STARTSEL(x)	HIWORD_UPDATE(x,  5,  5)
52*4882a593Smuzhiyun #define RK3288_LVDS_CON_CHASEL(x)	HIWORD_UPDATE(x,  4,  4)
53*4882a593Smuzhiyun #define RK3288_LVDS_CON_MSBSEL(x)	HIWORD_UPDATE(x,  3,  3)
54*4882a593Smuzhiyun #define RK3288_LVDS_CON_SELECT(x)	HIWORD_UPDATE(x,  2,  0)
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define RK3368_GRF_SOC_CON7		0x041c
57*4882a593Smuzhiyun #define RK3368_LVDS_SELECT(x)		HIWORD_UPDATE(x, 14, 13)
58*4882a593Smuzhiyun #define RK3368_LVDS_MODE_EN(x)		HIWORD_UPDATE(x, 12, 12)
59*4882a593Smuzhiyun #define RK3368_LVDS_MSBSEL(x)		HIWORD_UPDATE(x, 11, 11)
60*4882a593Smuzhiyun #define RK3368_LVDS_P2S_EN(x)		HIWORD_UPDATE(x,  6,  6)
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #define RK3562_GRF_VO_CON0		0x05d0
63*4882a593Smuzhiyun #define RK3562_GRF_VO_CON1		0x05d4
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define RK3568_GRF_VO_CON0		0x0360
66*4882a593Smuzhiyun #define RK3568_LVDS1_SELECT(x)		HIWORD_UPDATE(x, 13, 12)
67*4882a593Smuzhiyun #define RK3568_LVDS1_MSBSEL(x)		HIWORD_UPDATE(x, 11, 11)
68*4882a593Smuzhiyun #define RK3568_LVDS0_SELECT(x)		HIWORD_UPDATE(x,  5,  4)
69*4882a593Smuzhiyun #define RK3568_LVDS0_MSBSEL(x)		HIWORD_UPDATE(x,  3,  3)
70*4882a593Smuzhiyun #define RK3568_GRF_VO_CON2		0x0368
71*4882a593Smuzhiyun #define RK3568_LVDS0_DCLK_INV_SEL(x)	HIWORD_UPDATE(x,  9,  9)
72*4882a593Smuzhiyun #define RK3568_LVDS0_DCLK_DIV2_SEL(x)	HIWORD_UPDATE(x,  8,  8)
73*4882a593Smuzhiyun #define RK3568_LVDS0_MODE_EN(x)		HIWORD_UPDATE(x,  1,  1)
74*4882a593Smuzhiyun #define RK3568_LVDS0_P2S_EN(x)		HIWORD_UPDATE(x,  0,  0)
75*4882a593Smuzhiyun #define RK3568_GRF_VO_CON3		0x036c
76*4882a593Smuzhiyun #define RK3568_LVDS1_DCLK_INV_SEL(x)	HIWORD_UPDATE(x,  9,  9)
77*4882a593Smuzhiyun #define RK3568_LVDS1_DCLK_DIV2_SEL(x)	HIWORD_UPDATE(x,  8,  8)
78*4882a593Smuzhiyun #define RK3568_LVDS1_MODE_EN(x)		HIWORD_UPDATE(x,  1,  1)
79*4882a593Smuzhiyun #define RK3568_LVDS1_P2S_EN(x)		HIWORD_UPDATE(x,  0,  0)
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun enum lvds_format {
82*4882a593Smuzhiyun 	LVDS_8BIT_MODE_FORMAT_1,
83*4882a593Smuzhiyun 	LVDS_8BIT_MODE_FORMAT_2,
84*4882a593Smuzhiyun 	LVDS_8BIT_MODE_FORMAT_3,
85*4882a593Smuzhiyun 	LVDS_6BIT_MODE,
86*4882a593Smuzhiyun 	LVDS_10BIT_MODE_FORMAT_1,
87*4882a593Smuzhiyun 	LVDS_10BIT_MODE_FORMAT_2,
88*4882a593Smuzhiyun };
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun struct rockchip_lvds;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun struct rockchip_lvds_funcs {
93*4882a593Smuzhiyun 	void (*enable)(struct rockchip_lvds *lvds, int pipe);
94*4882a593Smuzhiyun 	void (*disable)(struct rockchip_lvds *lvds);
95*4882a593Smuzhiyun };
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun struct rockchip_lvds {
98*4882a593Smuzhiyun 	struct rockchip_connector connector;
99*4882a593Smuzhiyun 	int id;
100*4882a593Smuzhiyun 	struct udevice *dev;
101*4882a593Smuzhiyun 	struct regmap *grf;
102*4882a593Smuzhiyun 	struct rockchip_phy *phy;
103*4882a593Smuzhiyun 	const struct drm_display_mode *mode;
104*4882a593Smuzhiyun 	const struct rockchip_lvds_funcs *funcs;
105*4882a593Smuzhiyun 	enum lvds_format format;
106*4882a593Smuzhiyun 	bool data_swap;
107*4882a593Smuzhiyun 	bool dual_channel;
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun 
rockchip_lvds_connector_init(struct rockchip_connector * conn,struct display_state * state)110*4882a593Smuzhiyun static int rockchip_lvds_connector_init(struct rockchip_connector *conn,
111*4882a593Smuzhiyun 					struct display_state *state)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun 	struct rockchip_lvds *lvds = dev_get_priv(conn->dev);
114*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
115*4882a593Smuzhiyun 	struct rockchip_panel *panel = conn->panel;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	lvds->mode = &conn_state->mode;
118*4882a593Smuzhiyun 	lvds->phy = conn->phy;
119*4882a593Smuzhiyun 	conn_state->disp_info  = rockchip_get_disp_info(conn_state->type, lvds->id);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	switch (panel->bus_format) {
122*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:	/* jeida-18 */
123*4882a593Smuzhiyun 		lvds->format = LVDS_6BIT_MODE;
124*4882a593Smuzhiyun 		break;
125*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:	/* jeida-24 */
126*4882a593Smuzhiyun 		lvds->format = LVDS_8BIT_MODE_FORMAT_2;
127*4882a593Smuzhiyun 		break;
128*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA: /* jeida-30 */
129*4882a593Smuzhiyun 		lvds->format = LVDS_10BIT_MODE_FORMAT_1;
130*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:	/* vesa-18 */
131*4882a593Smuzhiyun 		lvds->format = LVDS_8BIT_MODE_FORMAT_3;
132*4882a593Smuzhiyun 		break;
133*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG: /* vesa-30 */
134*4882a593Smuzhiyun 		lvds->format = LVDS_10BIT_MODE_FORMAT_2;
135*4882a593Smuzhiyun 		break;
136*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:	/* vesa-24 */
137*4882a593Smuzhiyun 	default:
138*4882a593Smuzhiyun 		lvds->format = LVDS_8BIT_MODE_FORMAT_1;
139*4882a593Smuzhiyun 		break;
140*4882a593Smuzhiyun 	}
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	if ((lvds->format == LVDS_10BIT_MODE_FORMAT_1) ||
145*4882a593Smuzhiyun 		(lvds->format == LVDS_10BIT_MODE_FORMAT_2))
146*4882a593Smuzhiyun 		conn_state->output_mode = ROCKCHIP_OUT_MODE_AAAA;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	conn_state->color_space = V4L2_COLORSPACE_DEFAULT;
149*4882a593Smuzhiyun 	conn_state->output_if = VOP_OUTPUT_IF_LVDS0;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	return 0;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
rockchip_lvds_connector_enable(struct rockchip_connector * conn,struct display_state * state)154*4882a593Smuzhiyun static int rockchip_lvds_connector_enable(struct rockchip_connector *conn,
155*4882a593Smuzhiyun 					  struct display_state *state)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun 	struct rockchip_lvds *lvds = dev_get_priv(conn->dev);
158*4882a593Smuzhiyun 	struct crtc_state *crtc_state = &state->crtc_state;
159*4882a593Smuzhiyun 	int pipe = crtc_state->crtc_id;
160*4882a593Smuzhiyun 	int ret;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	if (lvds->funcs->enable)
163*4882a593Smuzhiyun 		lvds->funcs->enable(lvds, pipe);
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	ret = rockchip_phy_set_mode(lvds->phy, PHY_MODE_VIDEO_LVDS);
166*4882a593Smuzhiyun 	if (ret) {
167*4882a593Smuzhiyun 		dev_err(lvds->dev, "failed to set phy mode: %d\n", ret);
168*4882a593Smuzhiyun 		return ret;
169*4882a593Smuzhiyun 	}
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	rockchip_phy_power_on(lvds->phy);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	return 0;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
rockchip_lvds_connector_disable(struct rockchip_connector * conn,struct display_state * state)176*4882a593Smuzhiyun static int rockchip_lvds_connector_disable(struct rockchip_connector *conn,
177*4882a593Smuzhiyun 					   struct display_state *state)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	struct rockchip_lvds *lvds = dev_get_priv(conn->dev);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	rockchip_phy_power_off(lvds->phy);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	if (lvds->funcs->disable)
184*4882a593Smuzhiyun 		lvds->funcs->disable(lvds);
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	return 0;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun static const struct rockchip_connector_funcs rockchip_lvds_connector_funcs = {
190*4882a593Smuzhiyun 	.init = rockchip_lvds_connector_init,
191*4882a593Smuzhiyun 	.enable = rockchip_lvds_connector_enable,
192*4882a593Smuzhiyun 	.disable = rockchip_lvds_connector_disable,
193*4882a593Smuzhiyun };
194*4882a593Smuzhiyun 
rockchip_lvds_probe(struct udevice * dev)195*4882a593Smuzhiyun static int rockchip_lvds_probe(struct udevice *dev)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun 	struct rockchip_lvds *lvds = dev_get_priv(dev);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	lvds->dev = dev;
200*4882a593Smuzhiyun 	lvds->funcs = (const struct rockchip_lvds_funcs *)dev_get_driver_data(dev);
201*4882a593Smuzhiyun 	lvds->grf = syscon_get_regmap(dev_get_parent(dev));
202*4882a593Smuzhiyun 	lvds->dual_channel = dev_read_bool(dev, "dual-channel");
203*4882a593Smuzhiyun 	lvds->data_swap = dev_read_bool(dev, "rockchip,data-swap");
204*4882a593Smuzhiyun 	lvds->id = of_alias_get_id(ofnode_to_np(dev->node), "lvds");
205*4882a593Smuzhiyun 	if (lvds->id < 0)
206*4882a593Smuzhiyun 		lvds->id = 0;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	rockchip_connector_bind(&lvds->connector, dev, lvds->id, &rockchip_lvds_connector_funcs,
209*4882a593Smuzhiyun 				NULL, DRM_MODE_CONNECTOR_LVDS);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	return 0;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun 
px30_lvds_enable(struct rockchip_lvds * lvds,int pipe)214*4882a593Smuzhiyun static void px30_lvds_enable(struct rockchip_lvds *lvds, int pipe)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun 	regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1,
217*4882a593Smuzhiyun 		     PX30_LVDS_SELECT(lvds->format) |
218*4882a593Smuzhiyun 		     PX30_LVDS_MODE_EN(1) | PX30_LVDS_MSBSEL(1) |
219*4882a593Smuzhiyun 		     PX30_LVDS_P2S_EN(1) | PX30_LVDS_VOP_SEL(pipe));
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
px30_lvds_disable(struct rockchip_lvds * lvds)222*4882a593Smuzhiyun static void px30_lvds_disable(struct rockchip_lvds *lvds)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	regmap_write(lvds->grf, PX30_GRF_PD_VO_CON1,
225*4882a593Smuzhiyun 		     PX30_LVDS_MODE_EN(0) | PX30_LVDS_P2S_EN(0));
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun static const struct rockchip_lvds_funcs px30_lvds_funcs = {
229*4882a593Smuzhiyun 	.enable = px30_lvds_enable,
230*4882a593Smuzhiyun 	.disable = px30_lvds_disable,
231*4882a593Smuzhiyun };
232*4882a593Smuzhiyun 
rk3126_lvds_enable(struct rockchip_lvds * lvds,int pipe)233*4882a593Smuzhiyun static void rk3126_lvds_enable(struct rockchip_lvds *lvds, int pipe)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3126_GRF_LVDS_CON0,
236*4882a593Smuzhiyun 		     RK3126_LVDS_P2S_EN(1) | RK3126_LVDS_MODE_EN(1) |
237*4882a593Smuzhiyun 		     RK3126_LVDS_MSBSEL(1) | RK3126_LVDS_SELECT(lvds->format));
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
rk3126_lvds_disable(struct rockchip_lvds * lvds)240*4882a593Smuzhiyun static void rk3126_lvds_disable(struct rockchip_lvds *lvds)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3126_GRF_LVDS_CON0,
243*4882a593Smuzhiyun 		     RK3126_LVDS_P2S_EN(0) | RK3126_LVDS_MODE_EN(0));
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun static const struct rockchip_lvds_funcs rk3126_lvds_funcs = {
247*4882a593Smuzhiyun 	.enable = rk3126_lvds_enable,
248*4882a593Smuzhiyun 	.disable = rk3126_lvds_disable,
249*4882a593Smuzhiyun };
250*4882a593Smuzhiyun 
rk3288_lvds_enable(struct rockchip_lvds * lvds,int pipe)251*4882a593Smuzhiyun static void rk3288_lvds_enable(struct rockchip_lvds *lvds, int pipe)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	const struct drm_display_mode *mode = lvds->mode;
254*4882a593Smuzhiyun 	u32 val;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3288_GRF_SOC_CON6,
257*4882a593Smuzhiyun 		     RK3288_LVDS_LCDC_SEL(pipe));
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	val = RK3288_LVDS_PWRDWN(0) | RK3288_LVDS_CON_CLKINV(0) |
260*4882a593Smuzhiyun 	      RK3288_LVDS_CON_CHASEL(lvds->dual_channel) |
261*4882a593Smuzhiyun 	      RK3288_LVDS_CON_SELECT(lvds->format);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	if (lvds->dual_channel) {
264*4882a593Smuzhiyun 		u32 h_bp = mode->htotal - mode->hsync_start;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 		val |= RK3288_LVDS_CON_ENABLE_2(1) |
267*4882a593Smuzhiyun 		       RK3288_LVDS_CON_ENABLE_1(1) |
268*4882a593Smuzhiyun 		       RK3288_LVDS_CON_STARTSEL(lvds->data_swap);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 		if (h_bp % 2)
271*4882a593Smuzhiyun 			val |= RK3288_LVDS_CON_STARTPHASE(1);
272*4882a593Smuzhiyun 		else
273*4882a593Smuzhiyun 			val |= RK3288_LVDS_CON_STARTPHASE(0);
274*4882a593Smuzhiyun 	} else {
275*4882a593Smuzhiyun 		val |= RK3288_LVDS_CON_ENABLE_2(0) |
276*4882a593Smuzhiyun 		       RK3288_LVDS_CON_ENABLE_1(1);
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3288_GRF_SOC_CON7, val);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	rockchip_phy_set_bus_width(lvds->phy, lvds->dual_channel ? 2 : 1);
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun 
rk3288_lvds_disable(struct rockchip_lvds * lvds)284*4882a593Smuzhiyun static void rk3288_lvds_disable(struct rockchip_lvds *lvds)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3288_GRF_SOC_CON7, RK3288_LVDS_PWRDWN(1));
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun static const struct rockchip_lvds_funcs rk3288_lvds_funcs = {
290*4882a593Smuzhiyun 	.enable = rk3288_lvds_enable,
291*4882a593Smuzhiyun 	.disable = rk3288_lvds_disable,
292*4882a593Smuzhiyun };
293*4882a593Smuzhiyun 
rk3368_lvds_enable(struct rockchip_lvds * lvds,int pipe)294*4882a593Smuzhiyun static void rk3368_lvds_enable(struct rockchip_lvds *lvds, int pipe)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3368_GRF_SOC_CON7,
297*4882a593Smuzhiyun 		     RK3368_LVDS_SELECT(lvds->format) |
298*4882a593Smuzhiyun 		     RK3368_LVDS_MODE_EN(1) | RK3368_LVDS_MSBSEL(1) |
299*4882a593Smuzhiyun 		     RK3368_LVDS_P2S_EN(1));
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun 
rk3368_lvds_disable(struct rockchip_lvds * lvds)302*4882a593Smuzhiyun static void rk3368_lvds_disable(struct rockchip_lvds *lvds)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3368_GRF_SOC_CON7,
305*4882a593Smuzhiyun 		     RK3368_LVDS_MODE_EN(0) | RK3368_LVDS_P2S_EN(0));
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun static const struct rockchip_lvds_funcs rk3368_lvds_funcs = {
309*4882a593Smuzhiyun 	.enable = rk3368_lvds_enable,
310*4882a593Smuzhiyun 	.disable = rk3368_lvds_disable,
311*4882a593Smuzhiyun };
312*4882a593Smuzhiyun 
rk3562_lvds_enable(struct rockchip_lvds * lvds,int pipe)313*4882a593Smuzhiyun static void rk3562_lvds_enable(struct rockchip_lvds *lvds, int pipe)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3562_GRF_VO_CON1,
316*4882a593Smuzhiyun 		     RK3568_LVDS0_MODE_EN(1) | RK3568_LVDS0_P2S_EN(1) |
317*4882a593Smuzhiyun 		     RK3568_LVDS0_DCLK_INV_SEL(1));
318*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3562_GRF_VO_CON0,
319*4882a593Smuzhiyun 		     RK3568_LVDS0_SELECT(lvds->format) | RK3568_LVDS0_MSBSEL(1));
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun 
rk3562_lvds_disable(struct rockchip_lvds * lvds)322*4882a593Smuzhiyun static void rk3562_lvds_disable(struct rockchip_lvds *lvds)
323*4882a593Smuzhiyun {
324*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3562_GRF_VO_CON1, RK3568_LVDS0_MODE_EN(0));
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun static const struct rockchip_lvds_funcs rk3562_lvds_funcs = {
328*4882a593Smuzhiyun 	.enable = rk3562_lvds_enable,
329*4882a593Smuzhiyun 	.disable = rk3562_lvds_disable,
330*4882a593Smuzhiyun };
331*4882a593Smuzhiyun 
rk3568_lvds_enable(struct rockchip_lvds * lvds,int pipe)332*4882a593Smuzhiyun static void rk3568_lvds_enable(struct rockchip_lvds *lvds, int pipe)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3568_GRF_VO_CON2,
335*4882a593Smuzhiyun 		     RK3568_LVDS0_MODE_EN(1) | RK3568_LVDS0_P2S_EN(1) |
336*4882a593Smuzhiyun 		     RK3568_LVDS0_DCLK_INV_SEL(1));
337*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3568_GRF_VO_CON0,
338*4882a593Smuzhiyun 		     RK3568_LVDS0_SELECT(lvds->format) | RK3568_LVDS0_MSBSEL(1));
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun 
rk3568_lvds_disable(struct rockchip_lvds * lvds)341*4882a593Smuzhiyun static void rk3568_lvds_disable(struct rockchip_lvds *lvds)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun 	regmap_write(lvds->grf, RK3568_GRF_VO_CON2, RK3568_LVDS0_MODE_EN(0));
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun static const struct rockchip_lvds_funcs rk3568_lvds_funcs = {
347*4882a593Smuzhiyun 	.enable = rk3568_lvds_enable,
348*4882a593Smuzhiyun 	.disable = rk3568_lvds_disable,
349*4882a593Smuzhiyun };
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun static const struct udevice_id rockchip_lvds_ids[] = {
352*4882a593Smuzhiyun 	{
353*4882a593Smuzhiyun 		.compatible = "rockchip,px30-lvds",
354*4882a593Smuzhiyun 		.data = (ulong)&px30_lvds_funcs,
355*4882a593Smuzhiyun 	},
356*4882a593Smuzhiyun 	{
357*4882a593Smuzhiyun 		.compatible = "rockchip,rk3126-lvds",
358*4882a593Smuzhiyun 		.data = (ulong)&rk3126_lvds_funcs,
359*4882a593Smuzhiyun 	},
360*4882a593Smuzhiyun 	{
361*4882a593Smuzhiyun 		.compatible = "rockchip,rk3288-lvds",
362*4882a593Smuzhiyun 		.data = (ulong)&rk3288_lvds_funcs,
363*4882a593Smuzhiyun 	},
364*4882a593Smuzhiyun 	{
365*4882a593Smuzhiyun 		.compatible = "rockchip,rk3368-lvds",
366*4882a593Smuzhiyun 		.data = (ulong)&rk3368_lvds_funcs,
367*4882a593Smuzhiyun 	},
368*4882a593Smuzhiyun 	{
369*4882a593Smuzhiyun 		.compatible = "rockchip,rk3562-lvds",
370*4882a593Smuzhiyun 		.data = (ulong)&rk3562_lvds_funcs,
371*4882a593Smuzhiyun 	},
372*4882a593Smuzhiyun 	{
373*4882a593Smuzhiyun 		.compatible = "rockchip,rk3568-lvds",
374*4882a593Smuzhiyun 		.data = (ulong)&rk3568_lvds_funcs,
375*4882a593Smuzhiyun 	},
376*4882a593Smuzhiyun 	{}
377*4882a593Smuzhiyun };
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun U_BOOT_DRIVER(rockchip_lvds) = {
380*4882a593Smuzhiyun 	.name = "rockchip_lvds",
381*4882a593Smuzhiyun 	.id = UCLASS_DISPLAY,
382*4882a593Smuzhiyun 	.of_match = rockchip_lvds_ids,
383*4882a593Smuzhiyun 	.probe = rockchip_lvds_probe,
384*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct rockchip_lvds),
385*4882a593Smuzhiyun };
386