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 /* set clock lane enable */ 201 lvds_ctrl_writel(lvds, 0xa0, 0x4); 202 } 203 /* delay for waitting pll lock on */ 204 while (delay_times--) { 205 if (lvds_phy_lock(lvds)) 206 break; 207 udelay(100); 208 } 209 210 if (delay_times <= 0) 211 printf("wait lvds phy lock failed, please check the hardware!\n"); 212 213 return 0; 214 } 215 216 static void px30_output_ttl(struct display_state *state) 217 { 218 struct connector_state *conn_state = &state->conn_state; 219 struct rockchip_lvds_device *lvds = conn_state->private; 220 u32 val = 0; 221 222 /* enable lvds mode */ 223 val = PX30_RGB_SYNC_BYPASS(1) | PX30_DPHY_FORCERXMODE(1); 224 writel(val, lvds->grf + PX30_GRF_PD_VO_CON1); 225 226 /* enable lane */ 227 lvds_writel(lvds, MIPIPHY_REG0, 0x7f); 228 val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) | v_LANE3_EN(1) | 229 v_LANECLK_EN(1) | v_PLL_PWR_OFF(1); 230 lvds_writel(lvds, MIPIPHY_REGEB, val); 231 /* set ttl mode and reset phy config */ 232 val = v_LVDS_MODE_EN(0) | v_TTL_MODE_EN(1) | v_MIPI_MODE_EN(0) | 233 v_MSB_SEL(1) | v_DIG_INTER_RST(1); 234 lvds_writel(lvds, MIPIPHY_REGE0, val); 235 rk336x_lvds_pwr_on(state); 236 } 237 238 static void rk3126_output_ttl(struct display_state *state) 239 { 240 struct connector_state *conn_state = &state->conn_state; 241 struct rockchip_lvds_device *lvds = conn_state->private; 242 u32 val = 0; 243 244 /* enable lvds mode */ 245 val = v_RK3126_LVDSMODE_EN(0) | 246 v_RK3126_MIPIPHY_TTL_EN(1) | 247 v_RK3126_MIPIPHY_LANE0_EN(1) | 248 v_RK3126_MIPIDPI_FORCEX_EN(1); 249 writel(val, lvds->grf + lvds->pdata->grf_soc_con7); 250 val = v_RK3126_MIPITTL_CLK_EN(1) | 251 v_RK3126_MIPITTL_LANE0_EN(1) | 252 v_RK3126_MIPITTL_LANE1_EN(1) | 253 v_RK3126_MIPITTL_LANE2_EN(1) | 254 v_RK3126_MIPITTL_LANE3_EN(1); 255 writel(val, lvds->grf + lvds->pdata->grf_soc_con15); 256 /* enable lane */ 257 lvds_writel(lvds, MIPIPHY_REG0, 0x7f); 258 val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) | v_LANE3_EN(1) | 259 v_LANECLK_EN(1) | v_PLL_PWR_OFF(1); 260 lvds_writel(lvds, MIPIPHY_REGEB, val); 261 /* set ttl mode and reset phy config */ 262 val = v_LVDS_MODE_EN(0) | v_TTL_MODE_EN(1) | v_MIPI_MODE_EN(0) | 263 v_MSB_SEL(1) | v_DIG_INTER_RST(1); 264 lvds_writel(lvds, MIPIPHY_REGE0, val); 265 rk336x_lvds_pwr_on(state); 266 } 267 268 static void rk336x_output_ttl(struct display_state *state) 269 { 270 struct connector_state *conn_state = &state->conn_state; 271 struct rockchip_lvds_device *lvds = conn_state->private; 272 u32 val = 0; 273 274 /* enable lvds mode */ 275 val = v_RK336X_LVDSMODE_EN(0) | v_RK336X_MIPIPHY_TTL_EN(1) | 276 v_RK336X_MIPIPHY_LANE0_EN(1) | 277 v_RK336X_MIPIDPI_FORCEX_EN(1); 278 writel(val, lvds->grf + lvds->pdata->grf_soc_con7); 279 val = v_RK336X_FORCE_JETAG(0); 280 writel(val, lvds->grf + lvds->pdata->grf_soc_con15); 281 282 /* enable lane */ 283 lvds_writel(lvds, MIPIPHY_REG0, 0x7f); 284 val = v_LANE0_EN(1) | v_LANE1_EN(1) | v_LANE2_EN(1) | v_LANE3_EN(1) | 285 v_LANECLK_EN(1) | v_PLL_PWR_OFF(1); 286 lvds_writel(lvds, MIPIPHY_REGEB, val); 287 288 /* set ttl mode and reset phy config */ 289 val = v_LVDS_MODE_EN(0) | v_TTL_MODE_EN(1) | v_MIPI_MODE_EN(0) | 290 v_MSB_SEL(1) | v_DIG_INTER_RST(1); 291 lvds_writel(lvds, MIPIPHY_REGE0, val); 292 293 rk336x_lvds_pwr_on(state); 294 } 295 296 static void px30_output_lvds(struct display_state *state) 297 { 298 struct connector_state *conn_state = &state->conn_state; 299 struct rockchip_lvds_device *lvds = conn_state->private; 300 u32 val = 0; 301 302 /* enable lvds mode */ 303 val = PX30_LVDS_PHY_MODE(1) | PX30_DPHY_FORCERXMODE(1); 304 /* config lvds_format */ 305 val |= PX30_LVDS_OUTPUT_FORMAT(lvds->format); 306 /* LSB receive mode */ 307 val |= PX30_LVDS_MSBSEL(LVDS_MSB_D7); 308 writel(val, lvds->grf + PX30_GRF_PD_VO_CON1); 309 310 /* digital internal disable */ 311 lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(0)); 312 313 /* set pll prediv and fbdiv */ 314 lvds_writel(lvds, MIPIPHY_REG3, v_PREDIV(2) | v_FBDIV_MSB(0)); 315 lvds_writel(lvds, MIPIPHY_REG4, v_FBDIV_LSB(28)); 316 317 lvds_writel(lvds, MIPIPHY_REGE8, 0xfc); 318 319 lvds_msk_reg(lvds, MIPIPHY_REG8, 320 m_SAMPLE_CLK_DIR, v_SAMPLE_CLK_DIR_REVERSE); 321 322 /* set lvds mode and reset phy config */ 323 lvds_msk_reg(lvds, MIPIPHY_REGE0, 324 m_MSB_SEL | m_DIG_INTER_RST, 325 v_MSB_SEL(1) | v_DIG_INTER_RST(1)); 326 327 rk336x_lvds_pwr_on(state); 328 lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(1)); 329 } 330 331 static void rk3126_output_lvds(struct display_state *state) 332 { 333 struct connector_state *conn_state = &state->conn_state; 334 struct rockchip_lvds_device *lvds = conn_state->private; 335 u32 val = 0; 336 337 /* enable lvds mode */ 338 val = v_RK3126_LVDSMODE_EN(1) | 339 v_RK3126_MIPIPHY_TTL_EN(0); 340 /* config lvds_format */ 341 val |= v_RK3126_LVDS_OUTPUT_FORMAT(lvds->format); 342 /* LSB receive mode */ 343 val |= v_RK3126_LVDS_MSBSEL(LVDS_MSB_D7); 344 val |= v_RK3126_MIPIPHY_LANE0_EN(1) | 345 v_RK3126_MIPIDPI_FORCEX_EN(1); 346 writel(val, lvds->grf + lvds->pdata->grf_soc_con7); 347 348 /* digital internal disable */ 349 lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(0)); 350 351 /* set pll prediv and fbdiv */ 352 lvds_writel(lvds, MIPIPHY_REG3, v_PREDIV(2) | v_FBDIV_MSB(0)); 353 lvds_writel(lvds, MIPIPHY_REG4, v_FBDIV_LSB(28)); 354 355 lvds_writel(lvds, MIPIPHY_REGE8, 0xfc); 356 357 /* set lvds mode and reset phy config */ 358 lvds_msk_reg(lvds, MIPIPHY_REGE0, 359 m_MSB_SEL | m_DIG_INTER_RST, 360 v_MSB_SEL(1) | v_DIG_INTER_RST(1)); 361 362 rk336x_lvds_pwr_on(state); 363 lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(1)); 364 } 365 366 static void rk336x_output_lvds(struct display_state *state) 367 { 368 struct connector_state *conn_state = &state->conn_state; 369 struct rockchip_lvds_device *lvds = conn_state->private; 370 u32 val = 0; 371 372 /* enable lvds mode */ 373 val |= v_RK336X_LVDSMODE_EN(1) | v_RK336X_MIPIPHY_TTL_EN(0); 374 /* config lvds_format */ 375 val |= v_RK336X_LVDS_OUTPUT_FORMAT(lvds->format); 376 /* LSB receive mode */ 377 val |= v_RK336X_LVDS_MSBSEL(LVDS_MSB_D7); 378 val |= v_RK336X_MIPIPHY_LANE0_EN(1) | 379 v_RK336X_MIPIDPI_FORCEX_EN(1); 380 writel(val, lvds->grf + lvds->pdata->grf_soc_con7); 381 /* digital internal disable */ 382 lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(0)); 383 384 /* set pll prediv and fbdiv */ 385 lvds_writel(lvds, MIPIPHY_REG3, v_PREDIV(2) | v_FBDIV_MSB(0)); 386 lvds_writel(lvds, MIPIPHY_REG4, v_FBDIV_LSB(28)); 387 388 lvds_writel(lvds, MIPIPHY_REGE8, 0xfc); 389 390 /* set lvds mode and reset phy config */ 391 lvds_msk_reg(lvds, MIPIPHY_REGE0, 392 m_MSB_SEL | m_DIG_INTER_RST, 393 v_MSB_SEL(1) | v_DIG_INTER_RST(1)); 394 395 rk336x_lvds_pwr_on(state); 396 lvds_msk_reg(lvds, MIPIPHY_REGE1, m_DIG_INTER_EN, v_DIG_INTER_EN(1)); 397 } 398 399 static int rk3288_lvds_pwr_on(struct display_state *state) 400 { 401 struct connector_state *conn_state = &state->conn_state; 402 struct rockchip_lvds_device *lvds = conn_state->private; 403 struct drm_display_mode *mode = &conn_state->mode; 404 u32 val; 405 u32 h_bp = mode->htotal - mode->hsync_start; 406 u8 pin_hsync = (mode->flags & DRM_MODE_FLAG_PHSYNC) ? 1 : 0; 407 u8 pin_dclk = (mode->flags & DRM_MODE_FLAG_PCSYNC) ? 1 : 0; 408 409 val = lvds->format; 410 if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS) 411 val |= LVDS_DUAL | LVDS_CH0_EN | LVDS_CH1_EN; 412 else if (lvds->output == DISPLAY_OUTPUT_LVDS) 413 val |= LVDS_CH0_EN; 414 else if (lvds->output == DISPLAY_OUTPUT_RGB) 415 val |= LVDS_TTL_EN | LVDS_CH0_EN | LVDS_CH1_EN; 416 417 if (h_bp & 0x01) 418 val |= LVDS_START_PHASE_RST_1; 419 420 val |= (pin_dclk << 8) | (pin_hsync << 9); 421 val |= (0xffff << 16); 422 writel(val, lvds->grf + lvds->pdata->grf_soc_con7); 423 424 return 0; 425 } 426 427 static void rk3288_output_ttl(struct display_state *state) 428 { 429 struct connector_state *conn_state = &state->conn_state; 430 struct rockchip_lvds_device *lvds = conn_state->private; 431 432 rk3288_lvds_pwr_on(state); 433 lvds_writel(lvds, RK3288_LVDS_CH0_REG0, 434 RK3288_LVDS_CH0_REG0_TTL_EN | 435 RK3288_LVDS_CH0_REG0_LANECK_EN | 436 RK3288_LVDS_CH0_REG0_LANE4_EN | 437 RK3288_LVDS_CH0_REG0_LANE3_EN | 438 RK3288_LVDS_CH0_REG0_LANE2_EN | 439 RK3288_LVDS_CH0_REG0_LANE1_EN | 440 RK3288_LVDS_CH0_REG0_LANE0_EN); 441 lvds_writel(lvds, RK3288_LVDS_CH0_REG2, 442 RK3288_LVDS_PLL_FBDIV_REG2(0x46)); 443 444 lvds_writel(lvds, RK3288_LVDS_CH0_REG3, 445 RK3288_LVDS_PLL_FBDIV_REG3(0x46)); 446 lvds_writel(lvds, RK3288_LVDS_CH0_REG4, 447 RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE | 448 RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE | 449 RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE | 450 RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE | 451 RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE | 452 RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE); 453 lvds_writel(lvds, RK3288_LVDS_CH0_REG5, 454 RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA | 455 RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA | 456 RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA | 457 RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA | 458 RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA | 459 RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA); 460 lvds_writel(lvds, RK3288_LVDS_CH0_REGD, 461 RK3288_LVDS_PLL_PREDIV_REGD(0x0a)); 462 lvds_writel(lvds, RK3288_LVDS_CH0_REG20, 463 RK3288_LVDS_CH0_REG20_LSB); 464 465 lvds_writel(lvds, RK3288_LVDS_CFG_REGC, RK3288_LVDS_CFG_REGC_PLL_ENABLE); 466 lvds_writel(lvds, RK3288_LVDS_CFG_REG21, RK3288_LVDS_CFG_REG21_TX_ENABLE); 467 } 468 469 static void rk3288_output_lvds(struct display_state *state) 470 { 471 struct connector_state *conn_state = &state->conn_state; 472 struct rockchip_lvds_device *lvds = conn_state->private; 473 474 rk3288_lvds_pwr_on(state); 475 476 lvds_writel(lvds, RK3288_LVDS_CH0_REG0, 477 RK3288_LVDS_CH0_REG0_LVDS_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_REG1, 485 RK3288_LVDS_CH0_REG1_LANECK_BIAS | 486 RK3288_LVDS_CH0_REG1_LANE4_BIAS | 487 RK3288_LVDS_CH0_REG1_LANE3_BIAS | 488 RK3288_LVDS_CH0_REG1_LANE2_BIAS | 489 RK3288_LVDS_CH0_REG1_LANE1_BIAS | 490 RK3288_LVDS_CH0_REG1_LANE0_BIAS); 491 lvds_writel(lvds, RK3288_LVDS_CH0_REG2, 492 RK3288_LVDS_CH0_REG2_RESERVE_ON | 493 RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE | 494 RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE | 495 RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE | 496 RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE | 497 RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE | 498 RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE | 499 RK3288_LVDS_PLL_FBDIV_REG2(0x46)); 500 lvds_writel(lvds, RK3288_LVDS_CH0_REG3, 501 RK3288_LVDS_PLL_FBDIV_REG3(0x46)); 502 lvds_writel(lvds, RK3288_LVDS_CH0_REG4, 0x00); 503 lvds_writel(lvds, RK3288_LVDS_CH0_REG5, 0x00); 504 lvds_writel(lvds, RK3288_LVDS_CH0_REGD, 505 RK3288_LVDS_PLL_PREDIV_REGD(0x0a)); 506 lvds_writel(lvds, RK3288_LVDS_CH0_REG20, 507 RK3288_LVDS_CH0_REG20_LSB); 508 509 lvds_writel(lvds, RK3288_LVDS_CFG_REGC, RK3288_LVDS_CFG_REGC_PLL_ENABLE); 510 lvds_writel(lvds, RK3288_LVDS_CFG_REG21, RK3288_LVDS_CFG_REG21_TX_ENABLE); 511 } 512 513 static int rockchip_lvds_init(struct display_state *state) 514 { 515 struct connector_state *conn_state = &state->conn_state; 516 const struct rockchip_connector *connector = conn_state->connector; 517 const struct rockchip_lvds_chip_data *pdata = connector->data; 518 struct rockchip_lvds_device *lvds; 519 const char *name; 520 int i, width; 521 struct resource lvds_phy, lvds_ctrl; 522 struct panel_state *panel_state = &state->panel_state; 523 ofnode panel_node = panel_state->node; 524 int ret; 525 526 lvds = malloc(sizeof(*lvds)); 527 if (!lvds) 528 return -ENOMEM; 529 lvds->pdata = pdata; 530 531 if (pdata->chip_type == RK3288_LVDS) { 532 lvds->regbase = dev_read_addr_ptr(conn_state->dev); 533 } else { 534 i = dev_read_resource(conn_state->dev, 0, &lvds_phy); 535 if (i) { 536 printf("can't get regs lvds_phy addresses!\n"); 537 free(lvds); 538 return -ENOMEM; 539 } 540 541 i = dev_read_resource(conn_state->dev, 1, &lvds_ctrl); 542 if (i) { 543 printf("can't get regs lvds_ctrl addresses!\n"); 544 free(lvds); 545 return -ENOMEM; 546 } 547 548 lvds->regbase = (void *)lvds_phy.start; 549 lvds->ctrl_reg = (void *)lvds_ctrl.start; 550 } 551 552 lvds->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 553 if (lvds->grf <= 0) { 554 printf("%s: Get syscon grf failed (ret=%p)\n", 555 __func__, lvds->grf); 556 return -ENXIO; 557 } 558 559 ret = dev_read_string_index(panel_state->dev, "rockchip,output", 0, &name); 560 if (ret) 561 /* default set it as output rgb */ 562 lvds->output = DISPLAY_OUTPUT_RGB; 563 else 564 lvds->output = lvds_name_to_output(name); 565 if (lvds->output < 0) { 566 printf("invalid output type [%s]\n", name); 567 free(lvds); 568 return lvds->output; 569 } 570 ret = dev_read_string_index(panel_state->dev, "rockchip,data-mapping", 0, &name); 571 if (ret) 572 /* default set it as format jeida */ 573 lvds->format = LVDS_FORMAT_JEIDA; 574 else 575 lvds->format = lvds_name_to_format(name); 576 577 if (lvds->format < 0) { 578 printf("invalid data-mapping format [%s]\n", name); 579 free(lvds); 580 return lvds->format; 581 } 582 width = ofnode_read_u32_default(panel_node, "rockchip,data-width", 24); 583 if (width == 24) { 584 lvds->format |= LVDS_24BIT; 585 } else if (width == 18) { 586 lvds->format |= LVDS_18BIT; 587 } else { 588 printf("rockchip-lvds unsupport data-width[%d]\n", width); 589 free(lvds); 590 return -EINVAL; 591 } 592 593 printf("LVDS: data mapping: %s, data-width:%d, format:%d,\n", 594 name, width, lvds->format); 595 conn_state->private = lvds; 596 conn_state->type = DRM_MODE_CONNECTOR_LVDS; 597 598 if ((lvds->output == DISPLAY_OUTPUT_RGB) && (width == 18)) 599 conn_state->output_mode = ROCKCHIP_OUT_MODE_P666; 600 else 601 conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 602 conn_state->color_space = V4L2_COLORSPACE_DEFAULT; 603 604 return 0; 605 } 606 607 static void rockchip_lvds_deinit(struct display_state *state) 608 { 609 struct connector_state *conn_state = &state->conn_state; 610 struct rockchip_lvds_device *lvds = conn_state->private; 611 612 free(lvds); 613 } 614 615 static int rockchip_lvds_prepare(struct display_state *state) 616 { 617 struct connector_state *conn_state = &state->conn_state; 618 struct rockchip_lvds_device *lvds = conn_state->private; 619 lvds->mode = &conn_state->mode; 620 621 rockchip_lvds_clk_enable(lvds); 622 623 return 0; 624 } 625 626 static void rockchip_lvds_vop_routing(struct rockchip_lvds_device *lvds, int pipe) 627 { 628 u32 val; 629 630 if (lvds->pdata->chip_type == RK3288_LVDS) { 631 if (pipe) 632 val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT | 633 (RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16); 634 else 635 val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16; 636 writel(val, lvds->grf + lvds->pdata->grf_soc_con6); 637 } else if (lvds->pdata->chip_type == PX30_LVDS) { 638 if (lvds->output == DISPLAY_OUTPUT_RGB) 639 writel(PX30_RGB_VOP_SEL(pipe), 640 lvds->grf + PX30_GRF_PD_VO_CON1); 641 else if (lvds->output == DISPLAY_OUTPUT_LVDS) 642 writel(PX30_LVDS_VOP_SEL(pipe), 643 lvds->grf + PX30_GRF_PD_VO_CON1); 644 } 645 } 646 647 static int rockchip_lvds_enable(struct display_state *state) 648 { 649 struct connector_state *conn_state = &state->conn_state; 650 struct rockchip_lvds_device *lvds = conn_state->private; 651 struct crtc_state *crtc_state = &state->crtc_state; 652 653 if (lvds->pdata->has_vop_sel) 654 rockchip_lvds_vop_routing(lvds, crtc_state->crtc_id); 655 656 if ((lvds->output == DISPLAY_OUTPUT_LVDS) || 657 (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS)) { 658 if (lvds->pdata->chip_type == RK3288_LVDS) 659 rk3288_output_lvds(state); 660 else if (lvds->pdata->chip_type == RK3126_LVDS) 661 rk3126_output_lvds(state); 662 else if (lvds->pdata->chip_type == PX30_LVDS) 663 px30_output_lvds(state); 664 else 665 rk336x_output_lvds(state); 666 } else { 667 if (lvds->pdata->chip_type == RK3288_LVDS) 668 rk3288_output_ttl(state); 669 else if (lvds->pdata->chip_type == RK3126_LVDS) 670 rk3126_output_ttl(state); 671 else if (lvds->pdata->chip_type == PX30_LVDS) 672 px30_output_ttl(state); 673 else 674 rk336x_output_ttl(state); 675 } 676 677 return 0; 678 } 679 680 static int rockchip_lvds_disable(struct display_state *state) 681 { 682 struct connector_state *conn_state = &state->conn_state; 683 struct rockchip_lvds_device *lvds = conn_state->private; 684 685 if (lvds->pdata->chip_type == RK3288_LVDS) 686 rk3288_lvds_pwr_off(state); 687 else 688 rk336x_lvds_pwr_off(state); 689 690 return 0; 691 } 692 693 const struct rockchip_connector_funcs rockchip_lvds_funcs = { 694 .init = rockchip_lvds_init, 695 .deinit = rockchip_lvds_deinit, 696 .prepare = rockchip_lvds_prepare, 697 .enable = rockchip_lvds_enable, 698 .disable = rockchip_lvds_disable, 699 }; 700 701 static const struct rockchip_lvds_chip_data px30_lvds_drv_data = { 702 .chip_type = PX30_LVDS, 703 .has_vop_sel = true, 704 }; 705 706 static const struct rockchip_connector px30_lvds_data = { 707 .funcs = &rockchip_lvds_funcs, 708 .data = &px30_lvds_drv_data, 709 }; 710 711 static const struct rockchip_lvds_chip_data rk3126_lvds_drv_data = { 712 .chip_type = RK3126_LVDS, 713 .grf_soc_con7 = RK3126_GRF_LVDS_CON0, 714 .grf_soc_con15 = RK3126_GRF_CON1, 715 .has_vop_sel = true, 716 }; 717 718 static const struct rockchip_connector rk3126_lvds_data = { 719 .funcs = &rockchip_lvds_funcs, 720 .data = &rk3126_lvds_drv_data, 721 }; 722 723 static const struct rockchip_lvds_chip_data rk3288_lvds_drv_data = { 724 .chip_type = RK3288_LVDS, 725 .has_vop_sel = true, 726 .grf_soc_con6 = 0x025c, 727 .grf_soc_con7 = 0x0260, 728 .grf_gpio1d_iomux = 0x000c, 729 }; 730 731 static const struct rockchip_connector rk3288_lvds_data = { 732 .funcs = &rockchip_lvds_funcs, 733 .data = &rk3288_lvds_drv_data, 734 }; 735 736 static const struct rockchip_lvds_chip_data rk3368_lvds_drv_data = { 737 .chip_type = RK3368_LVDS, 738 .grf_soc_con7 = RK3368_GRF_SOC_CON7, 739 .grf_soc_con15 = RK3368_GRF_SOC_CON15, 740 .has_vop_sel = false, 741 }; 742 743 static const struct rockchip_connector rk3368_lvds_data = { 744 .funcs = &rockchip_lvds_funcs, 745 .data = &rk3368_lvds_drv_data, 746 }; 747 748 static const struct udevice_id rockchip_lvds_ids[] = { 749 { 750 .compatible = "rockchip,px30-lvds", 751 .data = (ulong)&px30_lvds_data, 752 }, 753 { 754 .compatible = "rockchip,rk3126-lvds", 755 .data = (ulong)&rk3126_lvds_data, 756 }, 757 { 758 .compatible = "rockchip,rk3288-lvds", 759 .data = (ulong)&rk3288_lvds_data, 760 }, 761 { 762 .compatible = "rockchip,rk3368-lvds", 763 .data = (ulong)&rk3368_lvds_data, 764 }, 765 {} 766 }; 767 768 U_BOOT_DRIVER(rockchip_lvds) = { 769 .name = "rockchip_lvds", 770 .id = UCLASS_DISPLAY, 771 .of_match = rockchip_lvds_ids, 772 }; 773