xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip_lvds.c (revision e17ddcea32b2fa7b82fb079f37195855a55e39a2)
1 /*
2  * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <config.h>
8 #include <common.h>
9 #include <errno.h>
10 #include <malloc.h>
11 #include <asm/unaligned.h>
12 #include <linux/list.h>
13 #include <linux/ioport.h>
14 #include <asm/io.h>
15 #include <asm/hardware.h>
16 #include <dm/device.h>
17 #include <dm/read.h>
18 #include <dm/ofnode.h>
19 #include <syscon.h>
20 #include <asm/arch-rockchip/clock.h>
21 #include <asm/gpio.h>
22 
23 #include "rockchip_display.h"
24 #include "rockchip_crtc.h"
25 #include "rockchip_connector.h"
26 #include "rockchip_lvds.h"
27 
28 enum rockchip_lvds_sub_devtype {
29 	PX30_LVDS,
30 	RK3126_LVDS,
31 	RK3288_LVDS,
32 	RK3368_LVDS,
33 };
34 
35 struct rockchip_lvds_chip_data {
36 	u32	chip_type;
37 	bool	has_vop_sel;
38 	u32	grf_soc_con5;
39 	u32	grf_soc_con6;
40 	u32	grf_soc_con7;
41 	u32	grf_soc_con15;
42 	u32	grf_gpio1d_iomux;
43 };
44 
45 struct rockchip_lvds_device {
46 	void	*regbase;
47 	void	*grf;
48 	void	*ctrl_reg;
49 	u32	channel;
50 	u32	output;
51 	u32	format;
52 	struct drm_display_mode *mode;
53 	const struct rockchip_lvds_chip_data *pdata;
54 };
55 
56 static inline int lvds_name_to_format(const char *s)
57 {
58 	if (!s)
59 		return -EINVAL;
60 
61 	if (strncmp(s, "jeida", 6) == 0)
62 		return LVDS_FORMAT_JEIDA;
63 	else if (strncmp(s, "vesa", 5) == 0)
64 		return LVDS_FORMAT_VESA;
65 
66 	return -EINVAL;
67 }
68 
69 static inline int lvds_name_to_output(const char *s)
70 {
71 	if (!s)
72 		return -EINVAL;
73 
74 	if (strncmp(s, "rgb", 3) == 0)
75 		return DISPLAY_OUTPUT_RGB;
76 	else if (strncmp(s, "lvds", 4) == 0)
77 		return DISPLAY_OUTPUT_LVDS;
78 	else if (strncmp(s, "duallvds", 8) == 0)
79 		return DISPLAY_OUTPUT_DUAL_LVDS;
80 
81 	return -EINVAL;
82 }
83 
84 static inline void lvds_writel(struct rockchip_lvds_device *lvds,
85 			      u32 offset, u32 val)
86 {
87 	writel(val, lvds->regbase + offset);
88 
89 	if ((lvds->pdata->chip_type == RK3288_LVDS) &&
90 	    (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS))
91 		writel(val, lvds->regbase + offset + 0x100);
92 }
93 
94 static inline void lvds_msk_reg(struct rockchip_lvds_device *lvds, u32 offset,
95 			       u32 msk, u32 val)
96 {
97 	u32 temp;
98 
99 	temp = readl(lvds->regbase + offset) & (0xFF - (msk));
100 	writel(temp | ((val) & (msk)), lvds->regbase + offset);
101 }
102 
103 static inline u32 lvds_readl(struct rockchip_lvds_device *lvds, u32 offset)
104 {
105 	return readl(lvds->regbase + offset);
106 }
107 
108 static inline void lvds_ctrl_writel(struct rockchip_lvds_device *lvds,
109 				   u32 offset, u32 val)
110 {
111 	writel(val, lvds->ctrl_reg + offset);
112 }
113 
114 static inline u32 lvds_pmugrf_readl(u32 offset)
115 {
116 	return readl((void *)LVDS_PMUGRF_BASE + offset);
117 }
118 
119 static inline void lvds_pmugrf_writel(u32 offset, u32 val)
120 {
121 	writel(val, (void *)LVDS_PMUGRF_BASE + offset);
122 }
123 
124 static inline u32 lvds_phy_lock(struct rockchip_lvds_device *lvds)
125 {
126 	u32 val = 0;
127 	val = readl(lvds->ctrl_reg + MIPIC_PHY_STATUS);
128 	return (val & m_PHY_LOCK_STATUS) ? 1 : 0;
129 }
130 
131 static int rockchip_lvds_clk_enable(struct rockchip_lvds_device *lvds)
132 {
133 	return 0;
134 }
135 
136 static int rk336x_lvds_pwr_off(struct display_state *state)
137 {
138 	struct connector_state *conn_state = &state->conn_state;
139 	struct rockchip_lvds_device *lvds = conn_state->private;
140 
141 	/* disable lvds lane and power off pll */
142 	lvds_writel(lvds, MIPIPHY_REGEB,
143 		    v_LANE0_EN(0) | v_LANE1_EN(0) | v_LANE2_EN(0) |
144 		    v_LANE3_EN(0) | v_LANECLK_EN(0) | v_PLL_PWR_OFF(1));
145 
146 	/* power down lvds pll and bandgap */
147 	lvds_msk_reg(lvds, MIPIPHY_REG1,
148 		     m_SYNC_RST | m_LDO_PWR_DOWN | m_PLL_PWR_DOWN,
149 		     v_SYNC_RST(1) | v_LDO_PWR_DOWN(1) | v_PLL_PWR_DOWN(1));
150 
151 	/* disable lvds */
152 	lvds_msk_reg(lvds, MIPIPHY_REGE3, m_LVDS_EN | m_TTL_EN,
153 		     v_LVDS_EN(0) | v_TTL_EN(0));
154 
155 	return 0;
156 }
157 
158 static int rk3288_lvds_pwr_off(struct display_state *state)
159 {
160 	struct connector_state *conn_state = &state->conn_state;
161 	struct rockchip_lvds_device *lvds = conn_state->private;
162 
163 	lvds_writel(lvds, RK3288_LVDS_CFG_REG21, RK3288_LVDS_CFG_REG21_TX_DISABLE);
164 	lvds_writel(lvds, RK3288_LVDS_CFG_REGC, RK3288_LVDS_CFG_REGC_PLL_DISABLE);
165 
166 	writel(0xffff8000, lvds->grf + lvds->pdata->grf_soc_con7);
167 
168 	return 0;
169 }
170 
171 static int rk336x_lvds_pwr_on(struct display_state *state)
172 {
173 	struct connector_state *conn_state = &state->conn_state;
174 	struct rockchip_lvds_device *lvds = conn_state->private;
175 	u32 delay_times = 20;
176 
177 	if (lvds->output == DISPLAY_OUTPUT_LVDS) {
178 		/* set VOCM 900 mv and V-DIFF 350 mv */
179 		lvds_msk_reg(lvds, MIPIPHY_REGE4, m_VOCM | m_DIFF_V,
180 			     v_VOCM(0) | v_DIFF_V(2));
181 		/* power up lvds pll and ldo */
182 		lvds_msk_reg(lvds, MIPIPHY_REG1,
183 			     m_SYNC_RST | m_LDO_PWR_DOWN | m_PLL_PWR_DOWN,
184 			     v_SYNC_RST(0) | v_LDO_PWR_DOWN(0) |
185 			     v_PLL_PWR_DOWN(0));
186 		/* enable lvds lane and power on pll */
187 		lvds_writel(lvds, MIPIPHY_REGEB,
188 			    v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) |
189 			    v_LANE3_EN(1) | v_LANECLK_EN(1) | v_PLL_PWR_OFF(0));
190 
191 		/* enable lvds */
192 		lvds_msk_reg(lvds, MIPIPHY_REGE3,
193 			     m_MIPI_EN | m_LVDS_EN | m_TTL_EN,
194 			     v_MIPI_EN(0) | v_LVDS_EN(1) | v_TTL_EN(0));
195 	} else {
196 		lvds_msk_reg(lvds, MIPIPHY_REGE3,
197 			     m_MIPI_EN | m_LVDS_EN | m_TTL_EN,
198 			     v_MIPI_EN(0) | v_LVDS_EN(0) | v_TTL_EN(1));
199 	}
200 	/* delay for waitting pll lock on */
201 	while (delay_times--) {
202 		if (lvds_phy_lock(lvds))
203 			break;
204 		udelay(100);
205 	}
206 
207 	if (delay_times <= 0)
208 		printf("wait lvds phy lock failed, please check the hardware!\n");
209 
210 	return 0;
211 }
212 
213 static void px30_output_ttl(struct display_state *state)
214 {
215 	struct connector_state *conn_state = &state->conn_state;
216 	struct rockchip_lvds_device *lvds = conn_state->private;
217 	u32 val = 0;
218 	int ret;
219 
220 	ret = dev_read_stringlist_search(conn_state->dev, "pinctrl-names", "m0");
221 	if (ret < 0) {
222 		/* iomux to lcdcm1 */
223 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3A_IOMUX_L, 0x000f, 0x0001);
224 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3A_IOMUX_H, 0x0f0f, 0x0101);
225 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3B_IOMUX_L, 0xff00, 0x1100);
226 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3B_IOMUX_H, 0x00f0, 0x0010);
227 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3C_IOMUX_L, 0xffff, 0x1111);
228 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3C_IOMUX_H, 0xffff, 0x1111);
229 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3D_IOMUX_L, 0xffff, 0x1111);
230 	} else {
231 		/* iomux to lcdcm0 */
232 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3A_IOMUX_L, 0xffff, 0x1111);
233 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3A_IOMUX_H, 0xffff, 0x1111);
234 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3B_IOMUX_L, 0xffff, 0x1111);
235 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3B_IOMUX_H, 0xffff, 0x1111);
236 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3C_IOMUX_L, 0xffff, 0x1111);
237 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3C_IOMUX_H, 0xffff, 0x1111);
238 		rk_clrsetreg(lvds->grf + PX30_GRF_GPIO3D_IOMUX_L, 0xffff, 0x1111);
239 		return;
240 	}
241 
242 	/* enable lvds mode */
243 	val = PX30_LVDS_PHY_MODE(0) | PX30_DPHY_FORCERXMODE(1);
244 	writel(val, lvds->grf + PX30_GRF_PD_VO_CON1);
245 
246 	/* enable lane */
247 	lvds_writel(lvds, MIPIPHY_REG0, 0x7f);
248 	val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) | v_LANE3_EN(1) |
249 		v_LANECLK_EN(1) | v_PLL_PWR_OFF(1);
250 	lvds_writel(lvds, MIPIPHY_REGEB, val);
251 	/* set ttl mode and reset phy config */
252 	val = v_LVDS_MODE_EN(0) | v_TTL_MODE_EN(1) | v_MIPI_MODE_EN(0) |
253 		v_MSB_SEL(1) | v_DIG_INTER_RST(1);
254 	lvds_writel(lvds, MIPIPHY_REGE0, val);
255 	rk336x_lvds_pwr_on(state);
256 }
257 
258 static void rk3126_output_ttl(struct display_state *state)
259 {
260 	struct connector_state *conn_state = &state->conn_state;
261 	struct rockchip_lvds_device *lvds = conn_state->private;
262 	u32 val = 0;
263 
264 	/* iomux to lcdc */
265 	writel(0xffc35541, lvds->grf + RK3126_GRF_GPIO2B_IOMUX);
266 	writel(0xffff5555, lvds->grf + RK3126_GRF_GPIO2C_IOMUX);
267 	writel(0x700c1004, lvds->grf + RK3126_GRF_GPIO2D_IOMUX);
268 
269 	/* enable lvds mode */
270 	val = v_RK3126_LVDSMODE_EN(0) |
271 		v_RK3126_MIPIPHY_TTL_EN(1) |
272 		v_RK3126_MIPIPHY_LANE0_EN(1) |
273 		v_RK3126_MIPIDPI_FORCEX_EN(1);
274 	writel(val, lvds->grf + lvds->pdata->grf_soc_con7);
275 	val = v_RK3126_MIPITTL_CLK_EN(1) |
276 		v_RK3126_MIPITTL_LANE0_EN(1) |
277 		v_RK3126_MIPITTL_LANE1_EN(1) |
278 		v_RK3126_MIPITTL_LANE2_EN(1) |
279 		v_RK3126_MIPITTL_LANE3_EN(1);
280 	writel(val, lvds->grf + lvds->pdata->grf_soc_con15);
281 	/* enable lane */
282 	lvds_writel(lvds, MIPIPHY_REG0, 0x7f);
283 	val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) | v_LANE3_EN(1) |
284 		v_LANECLK_EN(1) | v_PLL_PWR_OFF(1);
285 	lvds_writel(lvds, MIPIPHY_REGEB, val);
286 	/* set ttl mode and reset phy config */
287 	val = v_LVDS_MODE_EN(0) | v_TTL_MODE_EN(1) | v_MIPI_MODE_EN(0) |
288 		v_MSB_SEL(1) | v_DIG_INTER_RST(1);
289 	lvds_writel(lvds, MIPIPHY_REGE0, val);
290 	rk336x_lvds_pwr_on(state);
291 }
292 
293 static void rk336x_output_ttl(struct display_state *state)
294 {
295 	struct connector_state *conn_state = &state->conn_state;
296 	struct rockchip_lvds_device *lvds = conn_state->private;
297 	u32 val = 0;
298 
299 	/* iomux to lcdc */
300 	if (lvds->pdata->chip_type == RK3368_LVDS) {
301 		/* lcdc data 11 10 */
302 		lvds_pmugrf_writel(0x04, 0xf0005000);
303 		/* lcdc data 12 13 14 15 16 17 18 19 */
304 		lvds_pmugrf_writel(0x08, 0xFFFF5555);
305 		/* lcdc data 20 21 22 23 HSYNC VSYNC DEN DCLK */
306 		lvds_pmugrf_writel(0x0c, 0xFFFF5555);
307 		/* set clock lane enable */
308 		lvds_ctrl_writel(lvds, 0x0, 0x4);
309 	} else {
310 		/* lcdc data 15 ... 10, vsync, hsync */
311 		lvds_pmugrf_writel(0x0c, 0xffff555a);
312 		/* lcdc data 23 ... 16 */
313 		lvds_pmugrf_writel(0x30, 0xffff5555);
314 		/* lcdc dclk, den */
315 		lvds_pmugrf_writel(0x34, 0x000f0005);
316 	}
317 
318 	/* enable lvds mode */
319 	val = v_RK336X_LVDSMODE_EN(0) | v_RK336X_MIPIPHY_TTL_EN(1) |
320 		v_RK336X_MIPIPHY_LANE0_EN(1) |
321 		v_RK336X_MIPIDPI_FORCEX_EN(1);
322 	writel(val, lvds->grf + lvds->pdata->grf_soc_con7);
323 	val = v_RK336X_FORCE_JETAG(0);
324 	writel(val, lvds->grf + lvds->pdata->grf_soc_con15);
325 
326 	/* enable lane */
327 	lvds_writel(lvds, MIPIPHY_REG0, 0x7f);
328 	val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) | v_LANE3_EN(1) |
329 		v_LANECLK_EN(1) | v_PLL_PWR_OFF(1);
330 	lvds_writel(lvds, MIPIPHY_REGEB, val);
331 
332 	/* set ttl mode and reset phy config */
333 	val = v_LVDS_MODE_EN(0) | v_TTL_MODE_EN(1) | v_MIPI_MODE_EN(0) |
334 		v_MSB_SEL(1) | v_DIG_INTER_RST(1);
335 	lvds_writel(lvds, MIPIPHY_REGE0, val);
336 
337 	rk336x_lvds_pwr_on(state);
338 }
339 
340 static void px30_output_lvds(struct display_state *state)
341 {
342 	struct connector_state *conn_state = &state->conn_state;
343 	struct rockchip_lvds_device *lvds = conn_state->private;
344 	u32 val = 0;
345 
346 	/* enable lvds mode */
347 	val = PX30_LVDS_PHY_MODE(1) | PX30_DPHY_FORCERXMODE(1);
348 	/* config lvds_format */
349 	val |= PX30_LVDS_OUTPUT_FORMAT(lvds->format);
350 	/* LSB receive mode */
351 	val |= PX30_LVDS_MSBSEL(LVDS_MSB_D7);
352 	writel(val, lvds->grf + PX30_GRF_PD_VO_CON1);
353 
354 	/* digital internal disable */
355 	lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(0));
356 
357 	/* set pll prediv and fbdiv */
358 	lvds_writel(lvds, MIPIPHY_REG3, v_PREDIV(2) | v_FBDIV_MSB(0));
359 	lvds_writel(lvds, MIPIPHY_REG4, v_FBDIV_LSB(28));
360 
361 	lvds_writel(lvds, MIPIPHY_REGE8, 0xfc);
362 
363 	/* set lvds mode and reset phy config */
364 	lvds_msk_reg(lvds, MIPIPHY_REGE0,
365 		     m_MSB_SEL | m_DIG_INTER_RST,
366 		     v_MSB_SEL(1) | v_DIG_INTER_RST(1));
367 
368 	rk336x_lvds_pwr_on(state);
369 	lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(1));
370 }
371 
372 static void rk3126_output_lvds(struct display_state *state)
373 {
374 	struct connector_state *conn_state = &state->conn_state;
375 	struct rockchip_lvds_device *lvds = conn_state->private;
376 	u32 val = 0;
377 
378 	/* enable lvds mode */
379 	val = v_RK3126_LVDSMODE_EN(1) |
380 	      v_RK3126_MIPIPHY_TTL_EN(0);
381 	/* config lvds_format */
382 	val |= v_RK3126_LVDS_OUTPUT_FORMAT(lvds->format);
383 	/* LSB receive mode */
384 	val |= v_RK3126_LVDS_MSBSEL(LVDS_MSB_D7);
385 	val |= v_RK3126_MIPIPHY_LANE0_EN(1) |
386 	       v_RK3126_MIPIDPI_FORCEX_EN(1);
387 	writel(val, lvds->grf + lvds->pdata->grf_soc_con7);
388 
389 	/* digital internal disable */
390 	lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(0));
391 
392 	/* set pll prediv and fbdiv */
393 	lvds_writel(lvds, MIPIPHY_REG3, v_PREDIV(2) | v_FBDIV_MSB(0));
394 	lvds_writel(lvds, MIPIPHY_REG4, v_FBDIV_LSB(28));
395 
396 	lvds_writel(lvds, MIPIPHY_REGE8, 0xfc);
397 
398 	/* set lvds mode and reset phy config */
399 	lvds_msk_reg(lvds, MIPIPHY_REGE0,
400 		     m_MSB_SEL | m_DIG_INTER_RST,
401 		     v_MSB_SEL(1) | v_DIG_INTER_RST(1));
402 
403 	rk336x_lvds_pwr_on(state);
404 	lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(1));
405 }
406 
407 static void rk336x_output_lvds(struct display_state *state)
408 {
409 	struct connector_state *conn_state = &state->conn_state;
410 	struct rockchip_lvds_device *lvds = conn_state->private;
411 	u32 val = 0;
412 
413 	/* enable lvds mode */
414 	val |= v_RK336X_LVDSMODE_EN(1) | v_RK336X_MIPIPHY_TTL_EN(0);
415 	/* config lvds_format */
416 	val |= v_RK336X_LVDS_OUTPUT_FORMAT(lvds->format);
417 	/* LSB receive mode */
418 	val |= v_RK336X_LVDS_MSBSEL(LVDS_MSB_D7);
419 	val |= v_RK336X_MIPIPHY_LANE0_EN(1) |
420 	       v_RK336X_MIPIDPI_FORCEX_EN(1);
421 	writel(val, lvds->grf + lvds->pdata->grf_soc_con7);
422 	/* digital internal disable */
423 	lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(0));
424 
425 	/* set pll prediv and fbdiv */
426 	lvds_writel(lvds, MIPIPHY_REG3, v_PREDIV(2) | v_FBDIV_MSB(0));
427 	lvds_writel(lvds, MIPIPHY_REG4, v_FBDIV_LSB(28));
428 
429 	lvds_writel(lvds, MIPIPHY_REGE8, 0xfc);
430 
431 	/* set lvds mode and reset phy config */
432 	lvds_msk_reg(lvds, MIPIPHY_REGE0,
433 		     m_MSB_SEL | m_DIG_INTER_RST,
434 		     v_MSB_SEL(1) | v_DIG_INTER_RST(1));
435 
436 	rk336x_lvds_pwr_on(state);
437 	lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(1));
438 }
439 
440 static int rk3288_lvds_pwr_on(struct display_state *state)
441 {
442 	struct connector_state *conn_state = &state->conn_state;
443 	struct rockchip_lvds_device *lvds = conn_state->private;
444 	struct drm_display_mode *mode = &conn_state->mode;
445 	u32 val;
446 	u32 h_bp = mode->htotal - mode->hsync_start;
447 	u8 pin_hsync = (mode->flags & DRM_MODE_FLAG_PHSYNC) ? 1 : 0;
448 	u8 pin_dclk = (mode->flags & DRM_MODE_FLAG_PCSYNC) ? 1 : 0;
449 
450 	val = lvds->format;
451 	if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS)
452 		val |= LVDS_DUAL | LVDS_CH0_EN | LVDS_CH1_EN;
453 	else if (lvds->output == DISPLAY_OUTPUT_LVDS)
454 		val |= LVDS_CH0_EN;
455 	else if (lvds->output == DISPLAY_OUTPUT_RGB)
456 		val |= LVDS_TTL_EN | LVDS_CH0_EN | LVDS_CH1_EN;
457 
458 	if (h_bp & 0x01)
459 		val |= LVDS_START_PHASE_RST_1;
460 
461 	val |= (pin_dclk << 8) | (pin_hsync << 9);
462 	val |= (0xffff << 16);
463 	writel(val, lvds->grf + lvds->pdata->grf_soc_con7);
464 
465 	return 0;
466 }
467 
468 static void rk3288_output_ttl(struct display_state *state)
469 {
470 	struct connector_state *conn_state = &state->conn_state;
471 	struct rockchip_lvds_device *lvds = conn_state->private;
472 
473 	rk3288_lvds_pwr_on(state);
474 	/* iomux: dclk den hsync vsync */
475 	writel(0x00550055, lvds->grf + lvds->pdata->grf_gpio1d_iomux);
476 	lvds_writel(lvds, RK3288_LVDS_CH0_REG0,
477 		    RK3288_LVDS_CH0_REG0_TTL_EN |
478 		    RK3288_LVDS_CH0_REG0_LANECK_EN |
479 		    RK3288_LVDS_CH0_REG0_LANE4_EN |
480 		    RK3288_LVDS_CH0_REG0_LANE3_EN |
481 		    RK3288_LVDS_CH0_REG0_LANE2_EN |
482 		    RK3288_LVDS_CH0_REG0_LANE1_EN |
483 		    RK3288_LVDS_CH0_REG0_LANE0_EN);
484 	lvds_writel(lvds, RK3288_LVDS_CH0_REG2,
485 		    RK3288_LVDS_PLL_FBDIV_REG2(0x46));
486 
487 	lvds_writel(lvds, RK3288_LVDS_CH0_REG3,
488 		    RK3288_LVDS_PLL_FBDIV_REG3(0x46));
489 	lvds_writel(lvds, RK3288_LVDS_CH0_REG4,
490 		    RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE |
491 		    RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE |
492 		    RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE |
493 		    RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE |
494 		    RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE |
495 		    RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE);
496 	lvds_writel(lvds, RK3288_LVDS_CH0_REG5,
497 		    RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA |
498 		    RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA |
499 		    RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA |
500 		    RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA |
501 		    RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA |
502 		    RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA);
503 	lvds_writel(lvds, RK3288_LVDS_CH0_REGD,
504 		    RK3288_LVDS_PLL_PREDIV_REGD(0x0a));
505 	lvds_writel(lvds, RK3288_LVDS_CH0_REG20,
506 		    RK3288_LVDS_CH0_REG20_LSB);
507 
508 	lvds_writel(lvds, RK3288_LVDS_CFG_REGC, RK3288_LVDS_CFG_REGC_PLL_ENABLE);
509 	lvds_writel(lvds, RK3288_LVDS_CFG_REG21, RK3288_LVDS_CFG_REG21_TX_ENABLE);
510 }
511 
512 static void rk3288_output_lvds(struct display_state *state)
513 {
514 	struct connector_state *conn_state = &state->conn_state;
515 	struct rockchip_lvds_device *lvds = conn_state->private;
516 
517 	rk3288_lvds_pwr_on(state);
518 
519 	lvds_writel(lvds, RK3288_LVDS_CH0_REG0,
520 		    RK3288_LVDS_CH0_REG0_LVDS_EN |
521 		    RK3288_LVDS_CH0_REG0_LANECK_EN |
522 		    RK3288_LVDS_CH0_REG0_LANE4_EN |
523 		    RK3288_LVDS_CH0_REG0_LANE3_EN |
524 		    RK3288_LVDS_CH0_REG0_LANE2_EN |
525 		    RK3288_LVDS_CH0_REG0_LANE1_EN |
526 		    RK3288_LVDS_CH0_REG0_LANE0_EN);
527 	lvds_writel(lvds, RK3288_LVDS_CH0_REG1,
528 		    RK3288_LVDS_CH0_REG1_LANECK_BIAS |
529 		    RK3288_LVDS_CH0_REG1_LANE4_BIAS |
530 		    RK3288_LVDS_CH0_REG1_LANE3_BIAS |
531 		    RK3288_LVDS_CH0_REG1_LANE2_BIAS |
532 		    RK3288_LVDS_CH0_REG1_LANE1_BIAS |
533 		    RK3288_LVDS_CH0_REG1_LANE0_BIAS);
534 	lvds_writel(lvds, RK3288_LVDS_CH0_REG2,
535 		    RK3288_LVDS_CH0_REG2_RESERVE_ON |
536 		    RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE |
537 		    RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE |
538 		    RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE |
539 		    RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE |
540 		    RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE |
541 		    RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE |
542 		    RK3288_LVDS_PLL_FBDIV_REG2(0x46));
543 	lvds_writel(lvds, RK3288_LVDS_CH0_REG3,
544 		    RK3288_LVDS_PLL_FBDIV_REG3(0x46));
545 	lvds_writel(lvds, RK3288_LVDS_CH0_REG4, 0x00);
546 	lvds_writel(lvds, RK3288_LVDS_CH0_REG5, 0x00);
547 	lvds_writel(lvds, RK3288_LVDS_CH0_REGD,
548 		    RK3288_LVDS_PLL_PREDIV_REGD(0x0a));
549 	lvds_writel(lvds, RK3288_LVDS_CH0_REG20,
550 		    RK3288_LVDS_CH0_REG20_LSB);
551 
552 	lvds_writel(lvds, RK3288_LVDS_CFG_REGC, RK3288_LVDS_CFG_REGC_PLL_ENABLE);
553 	lvds_writel(lvds, RK3288_LVDS_CFG_REG21, RK3288_LVDS_CFG_REG21_TX_ENABLE);
554 }
555 
556 static int rockchip_lvds_init(struct display_state *state)
557 {
558 	struct connector_state *conn_state = &state->conn_state;
559 	const struct rockchip_connector *connector = conn_state->connector;
560 	const struct rockchip_lvds_chip_data *pdata = connector->data;
561 	struct rockchip_lvds_device *lvds;
562 	const char *name;
563 	int i, width;
564 	struct resource lvds_phy, lvds_ctrl;
565 	struct panel_state *panel_state = &state->panel_state;
566 	ofnode panel_node = panel_state->node;
567 	int ret;
568 
569 	lvds = malloc(sizeof(*lvds));
570 	if (!lvds)
571 		return -ENOMEM;
572 	lvds->pdata = pdata;
573 
574 	if (pdata->chip_type == RK3288_LVDS) {
575 		lvds->regbase = dev_read_addr_ptr(conn_state->dev);
576 	} else {
577 		i = dev_read_resource(conn_state->dev, 0, &lvds_phy);
578 		if (i) {
579 			printf("can't get regs lvds_phy addresses!\n");
580 			free(lvds);
581 			return -ENOMEM;
582 		}
583 
584 		i = dev_read_resource(conn_state->dev, 1, &lvds_ctrl);
585 		if (i) {
586 			printf("can't get regs lvds_ctrl addresses!\n");
587 			free(lvds);
588 			return -ENOMEM;
589 		}
590 
591 		lvds->regbase = (void *)lvds_phy.start;
592 		lvds->ctrl_reg = (void *)lvds_ctrl.start;
593 	}
594 
595 	lvds->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
596 	if (lvds->grf <= 0) {
597 		printf("%s: Get syscon grf failed (ret=%p)\n",
598 		      __func__, lvds->grf);
599 		return  -ENXIO;
600 	}
601 
602 	ret = dev_read_string_index(panel_state->dev, "rockchip,output", 0, &name);
603 	if (ret)
604 		/* default set it as output rgb */
605 		lvds->output = DISPLAY_OUTPUT_RGB;
606 	else
607 		lvds->output = lvds_name_to_output(name);
608 	if (lvds->output < 0) {
609 		printf("invalid output type [%s]\n", name);
610 		free(lvds);
611 		return lvds->output;
612 	}
613 	ret = dev_read_string_index(panel_state->dev, "rockchip,data-mapping", 0, &name);
614 	if (ret)
615 		/* default set it as format jeida */
616 		lvds->format = LVDS_FORMAT_JEIDA;
617 	else
618 		lvds->format = lvds_name_to_format(name);
619 
620 	if (lvds->format < 0) {
621 		printf("invalid data-mapping format [%s]\n", name);
622 		free(lvds);
623 		return lvds->format;
624 	}
625 	width = ofnode_read_u32_default(panel_node, "rockchip,data-width", 24);
626 	if (width == 24) {
627 		lvds->format |= LVDS_24BIT;
628 	} else if (width == 18) {
629 		lvds->format |= LVDS_18BIT;
630 	} else {
631 		printf("rockchip-lvds unsupport data-width[%d]\n", width);
632 		free(lvds);
633 		return -EINVAL;
634 	}
635 
636 	printf("LVDS: data mapping: %s, data-width:%d, format:%d,\n",
637 		name, width, lvds->format);
638 	conn_state->private = lvds;
639 	conn_state->type = DRM_MODE_CONNECTOR_LVDS;
640 
641 	if ((lvds->output == DISPLAY_OUTPUT_RGB) && (width == 18))
642 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P666;
643 	else
644 		conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
645 	conn_state->color_space = V4L2_COLORSPACE_DEFAULT;
646 
647 	return 0;
648 }
649 
650 static void rockchip_lvds_deinit(struct display_state *state)
651 {
652 	struct connector_state *conn_state = &state->conn_state;
653 	struct rockchip_lvds_device *lvds = conn_state->private;
654 
655 	free(lvds);
656 }
657 
658 static int rockchip_lvds_prepare(struct display_state *state)
659 {
660 	struct connector_state *conn_state = &state->conn_state;
661 	struct rockchip_lvds_device *lvds = conn_state->private;
662 	lvds->mode = &conn_state->mode;
663 
664 	rockchip_lvds_clk_enable(lvds);
665 
666 	return 0;
667 }
668 
669 static void rockchip_lvds_vop_routing(struct rockchip_lvds_device *lvds, int pipe)
670 {
671 	u32 val;
672 
673 	if (lvds->pdata->chip_type == RK3288_LVDS) {
674 		if (pipe)
675 			val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT |
676 				(RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16);
677 		else
678 			val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16;
679 		writel(val, lvds->grf + lvds->pdata->grf_soc_con6);
680 	} else if (lvds->pdata->chip_type == PX30_LVDS) {
681 		if (lvds->output == DISPLAY_OUTPUT_RGB)
682 			writel(PX30_RGB_VOP_SEL(pipe),
683 			       lvds->grf + PX30_GRF_PD_VO_CON1);
684 		else if (lvds->output == DISPLAY_OUTPUT_LVDS)
685 			writel(PX30_LVDS_VOP_SEL(pipe),
686 			       lvds->grf + PX30_GRF_PD_VO_CON1);
687 	}
688 }
689 
690 static int rockchip_lvds_enable(struct display_state *state)
691 {
692 	struct connector_state *conn_state = &state->conn_state;
693 	struct rockchip_lvds_device *lvds = conn_state->private;
694 	struct crtc_state *crtc_state = &state->crtc_state;
695 
696 	if (lvds->pdata->has_vop_sel)
697 		rockchip_lvds_vop_routing(lvds, crtc_state->crtc_id);
698 
699 	if (lvds->output == DISPLAY_OUTPUT_LVDS) {
700 		if (lvds->pdata->chip_type == RK3288_LVDS)
701 			rk3288_output_lvds(state);
702 		else if (lvds->pdata->chip_type == RK3126_LVDS)
703 			rk3126_output_lvds(state);
704 		else if (lvds->pdata->chip_type == PX30_LVDS)
705 			px30_output_lvds(state);
706 		else
707 			rk336x_output_lvds(state);
708 	} else {
709 		if (lvds->pdata->chip_type == RK3288_LVDS)
710 			rk3288_output_ttl(state);
711 		else if (lvds->pdata->chip_type == RK3126_LVDS)
712 			rk3126_output_ttl(state);
713 		else if (lvds->pdata->chip_type == PX30_LVDS)
714 			px30_output_ttl(state);
715 		else
716 			rk336x_output_ttl(state);
717 	}
718 
719 	return 0;
720 }
721 
722 static int rockchip_lvds_disable(struct display_state *state)
723 {
724 	struct connector_state *conn_state = &state->conn_state;
725 	struct rockchip_lvds_device *lvds = conn_state->private;
726 
727 	if (lvds->pdata->chip_type == RK3288_LVDS)
728 		rk3288_lvds_pwr_off(state);
729 	else
730 		rk336x_lvds_pwr_off(state);
731 
732 	return 0;
733 }
734 
735 const struct rockchip_connector_funcs rockchip_lvds_funcs = {
736 	.init = rockchip_lvds_init,
737 	.deinit = rockchip_lvds_deinit,
738 	.prepare = rockchip_lvds_prepare,
739 	.enable = rockchip_lvds_enable,
740 	.disable = rockchip_lvds_disable,
741 };
742 
743 static const struct rockchip_lvds_chip_data px30_lvds_drv_data = {
744 	.chip_type = PX30_LVDS,
745 	.has_vop_sel = true,
746 };
747 
748 static const struct rockchip_connector px30_lvds_data = {
749 	 .funcs = &rockchip_lvds_funcs,
750 	 .data = &px30_lvds_drv_data,
751 };
752 
753 static const struct rockchip_lvds_chip_data rk3126_lvds_drv_data = {
754 	.chip_type = RK3126_LVDS,
755 	.grf_soc_con7  = RK3126_GRF_LVDS_CON0,
756 	.grf_soc_con15 = RK3126_GRF_CON1,
757 	.has_vop_sel = true,
758 };
759 
760 static const struct rockchip_connector rk3126_lvds_data = {
761 	 .funcs = &rockchip_lvds_funcs,
762 	 .data = &rk3126_lvds_drv_data,
763 };
764 
765 static const struct rockchip_lvds_chip_data rk3288_lvds_drv_data = {
766 	.chip_type = RK3288_LVDS,
767 	.has_vop_sel = true,
768 	.grf_soc_con6 = 0x025c,
769 	.grf_soc_con7 = 0x0260,
770 	.grf_gpio1d_iomux = 0x000c,
771 };
772 
773 static const struct rockchip_connector rk3288_lvds_data = {
774 	 .funcs = &rockchip_lvds_funcs,
775 	 .data = &rk3288_lvds_drv_data,
776 };
777 
778 static const struct rockchip_lvds_chip_data rk3368_lvds_drv_data = {
779 	.chip_type = RK3368_LVDS,
780 	.grf_soc_con7  = RK3368_GRF_SOC_CON7,
781 	.grf_soc_con15 = RK3368_GRF_SOC_CON15,
782 	.has_vop_sel = false,
783 };
784 
785 static const struct rockchip_connector rk3368_lvds_data = {
786 	 .funcs = &rockchip_lvds_funcs,
787 	 .data = &rk3368_lvds_drv_data,
788 };
789 
790 static const struct udevice_id rockchip_lvds_ids[] = {
791 	{
792 		.compatible = "rockchip,px30-lvds",
793 		.data = (ulong)&px30_lvds_data,
794 	},
795 	{
796 		.compatible = "rockchip,rk3126-lvds",
797 		.data = (ulong)&rk3126_lvds_data,
798 	},
799 	{
800 		.compatible = "rockchip,rk3288-lvds",
801 		.data = (ulong)&rk3288_lvds_data,
802 	},
803 	{
804 		.compatible = "rockchip,rk3368-lvds",
805 		.data = (ulong)&rk3368_lvds_data,
806 	},
807 	{}
808 };
809 
810 U_BOOT_DRIVER(rockchip_lvds) = {
811 	.name = "rockchip_lvds",
812 	.id = UCLASS_DISPLAY,
813 	.of_match = rockchip_lvds_ids,
814 };
815