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