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