1 /* 2 * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm/of_access.h> 9 #include <errno.h> 10 #include <syscon.h> 11 #include <regmap.h> 12 #include <dm/device.h> 13 #include <dm/read.h> 14 #include <dm/pinctrl.h> 15 #include <linux/media-bus-format.h> 16 #include <asm/gpio.h> 17 #include <backlight.h> 18 19 #include "rockchip_display.h" 20 #include "rockchip_crtc.h" 21 #include "rockchip_connector.h" 22 #include "rockchip_phy.h" 23 #include "rockchip_panel.h" 24 25 #define HIWORD_UPDATE(v, l, h) (((v) << (l)) | (GENMASK(h, l) << 16)) 26 27 #define PX30_GRF_PD_VO_CON1 0x0438 28 #define PX30_RGB_DATA_SYNC_BYPASS(v) HIWORD_UPDATE(v, 3, 3) 29 #define PX30_RGB_VOP_SEL(v) HIWORD_UPDATE(v, 2, 2) 30 31 #define RK1808_GRF_PD_VO_CON1 0x0444 32 #define RK1808_RGB_DATA_SYNC_BYPASS(v) HIWORD_UPDATE(v, 3, 3) 33 34 #define RV1106_VENC_GRF_VOP_IO_WRAPPER 0x1000c 35 #define RV1106_IO_BYPASS_SEL(v) HIWORD_UPDATE(v, 0, 1) 36 #define RV1106_VOGRF_VOP_PIPE_BYPASS 0x60034 37 #define RV1106_VOP_PIPE_BYPASS(v) HIWORD_UPDATE(v, 0, 1) 38 39 #define RV1126_GRF_IOFUNC_CON3 0x1026c 40 #define RV1126_LCDC_IO_BYPASS(v) HIWORD_UPDATE(v, 0, 0) 41 42 #define RK3288_GRF_SOC_CON6 0x025c 43 #define RK3288_LVDS_LCDC_SEL(v) HIWORD_UPDATE(v, 3, 3) 44 #define RK3288_GRF_SOC_CON7 0x0260 45 #define RK3288_LVDS_PWRDWN(v) HIWORD_UPDATE(v, 15, 15) 46 #define RK3288_LVDS_CON_ENABLE_2(v) HIWORD_UPDATE(v, 12, 12) 47 #define RK3288_LVDS_CON_ENABLE_1(v) HIWORD_UPDATE(v, 11, 11) 48 #define RK3288_LVDS_CON_CLKINV(v) HIWORD_UPDATE(v, 8, 8) 49 #define RK3288_LVDS_CON_TTL_EN(v) HIWORD_UPDATE(v, 6, 6) 50 51 #define RK3368_GRF_SOC_CON15 0x043c 52 #define RK3368_FORCE_JETAG(v) HIWORD_UPDATE(v, 13, 13) 53 54 #define RK3506_GRF_SOC_CON2 0x0008 55 #define RK3506_GRF_VOP_DATA_BYPASS(v) HIWORD_UPDATE(v, 1, 2) 56 57 #define RK3562_GRF_IOC_VO_IO_CON 0x10500 58 #define RK3562_RGB_DATA_BYPASS(v) HIWORD_UPDATE(v, 6, 6) 59 60 #define RK3568_GRF_VO_CON1 0X0364 61 #define RK3568_RGB_DATA_BYPASS(v) HIWORD_UPDATE(v, 6, 6) 62 63 #define RK3576_VCCIO_IOC_MISC_CON8 0x6420 64 #define RK3576_VOP_MCU_SEL(v) HIWORD_UPDATE(v, 10, 10) 65 #define RK3576_VOP_DLL_SEL(v) HIWORD_UPDATE(v, 8, 8) 66 #define RK3576_VOP_DCLK_DELAYLINE(v) HIWORD_UPDATE(v, 0, 6) 67 68 struct rockchip_rgb; 69 70 struct rockchip_rgb_funcs { 71 void (*prepare)(struct rockchip_rgb *rgb, int pipe); 72 void (*unprepare)(struct rockchip_rgb *rgb); 73 }; 74 75 struct rockchip_rgb_data { 76 u32 rgb_max_dclk_rate; 77 u32 mcu_max_dclk_rate; 78 u32 dclk_delayline; 79 const struct rockchip_rgb_funcs *funcs; 80 }; 81 82 struct rockchip_rgb { 83 struct rockchip_connector connector; 84 int id; 85 struct udevice *dev; 86 struct regmap *grf; 87 bool data_sync_bypass; 88 struct rockchip_phy *phy; 89 const struct rockchip_rgb_funcs *funcs; 90 u32 max_dclk_rate; 91 u32 dclk_delayline; 92 }; 93 94 struct mcu_cmd_header { 95 u8 data_type; 96 u8 delay; 97 u8 payload_length; 98 } __packed; 99 100 struct mcu_cmd_desc { 101 struct mcu_cmd_header header; 102 const u8 *payload; 103 }; 104 105 struct mcu_cmd_seq { 106 struct mcu_cmd_desc *cmds; 107 unsigned int cmd_cnt; 108 }; 109 110 struct rockchip_mcu_panel_desc { 111 struct mcu_cmd_seq *init_seq; 112 struct mcu_cmd_seq *exit_seq; 113 114 struct { 115 unsigned int width; 116 unsigned int height; 117 } size; 118 119 struct { 120 unsigned int prepare; 121 unsigned int enable; 122 unsigned int disable; 123 unsigned int unprepare; 124 unsigned int reset; 125 unsigned int init; 126 } delay; 127 128 unsigned int bpc; 129 u32 bus_format; 130 u32 bus_flags; 131 bool power_invert; 132 }; 133 134 struct rockchip_mcu_panel { 135 struct rockchip_panel base; 136 struct rockchip_mcu_panel_desc *desc; 137 struct udevice *power_supply; 138 struct udevice *backlight; 139 140 struct gpio_desc enable_gpio; 141 struct gpio_desc reset_gpio; 142 143 bool prepared; 144 bool enabled; 145 }; 146 147 static inline struct rockchip_mcu_panel *to_rockchip_mcu_panel(struct rockchip_panel *panel) 148 { 149 return container_of(panel, struct rockchip_mcu_panel, base); 150 } 151 152 static int rockchip_rgb_connector_prepare(struct rockchip_connector *conn, 153 struct display_state *state) 154 { 155 struct rockchip_rgb *rgb = dev_get_priv(conn->dev); 156 struct crtc_state *crtc_state = &state->crtc_state; 157 int pipe = crtc_state->crtc_id; 158 int ret; 159 160 pinctrl_select_state(rgb->dev, "default"); 161 162 if (rgb->funcs && rgb->funcs->prepare) 163 rgb->funcs->prepare(rgb, pipe); 164 165 if (rgb->phy) { 166 ret = rockchip_phy_set_mode(rgb->phy, PHY_MODE_VIDEO_TTL); 167 if (ret) { 168 dev_err(rgb->dev, "failed to set phy mode: %d\n", ret); 169 return ret; 170 } 171 172 rockchip_phy_power_on(rgb->phy); 173 } 174 175 return 0; 176 } 177 178 static void rockchip_rgb_connector_unprepare(struct rockchip_connector *conn, 179 struct display_state *state) 180 { 181 struct rockchip_rgb *rgb = dev_get_priv(conn->dev); 182 183 if (rgb->phy) 184 rockchip_phy_power_off(rgb->phy); 185 186 if (rgb->funcs && rgb->funcs->unprepare) 187 rgb->funcs->unprepare(rgb); 188 189 pinctrl_select_state(rgb->dev, "sleep"); 190 } 191 192 static int rockchip_rgb_connector_init(struct rockchip_connector *conn, struct display_state *state) 193 { 194 struct rockchip_rgb *rgb = dev_get_priv(conn->dev); 195 struct connector_state *conn_state = &state->conn_state; 196 197 rgb->phy = conn->phy; 198 199 conn_state->color_range = DRM_COLOR_YCBCR_FULL_RANGE; 200 conn_state->color_encoding = DRM_COLOR_YCBCR_BT709; 201 conn_state->disp_info = rockchip_get_disp_info(conn_state->type, rgb->id); 202 203 switch (conn_state->bus_format) { 204 case MEDIA_BUS_FMT_RGB666_1X18: 205 conn_state->output_mode = ROCKCHIP_OUT_MODE_P666; 206 conn_state->output_if = VOP_OUTPUT_IF_RGB; 207 break; 208 case MEDIA_BUS_FMT_RGB565_1X16: 209 conn_state->output_mode = ROCKCHIP_OUT_MODE_P565; 210 conn_state->output_if = VOP_OUTPUT_IF_RGB; 211 break; 212 case MEDIA_BUS_FMT_RGB565_2X8_LE: 213 case MEDIA_BUS_FMT_BGR565_2X8_LE: 214 conn_state->output_mode = ROCKCHIP_OUT_MODE_S565; 215 conn_state->output_if = VOP_OUTPUT_IF_RGB; 216 break; 217 case MEDIA_BUS_FMT_RGB666_3X6: 218 conn_state->output_mode = ROCKCHIP_OUT_MODE_S666; 219 conn_state->output_if = VOP_OUTPUT_IF_RGB; 220 break; 221 case MEDIA_BUS_FMT_RGB888_3X8: 222 case MEDIA_BUS_FMT_BGR888_3X8: 223 conn_state->output_mode = ROCKCHIP_OUT_MODE_S888; 224 conn_state->output_if = VOP_OUTPUT_IF_RGB; 225 break; 226 case MEDIA_BUS_FMT_RGB888_DUMMY_4X8: 227 case MEDIA_BUS_FMT_BGR888_DUMMY_4X8: 228 conn_state->output_mode = ROCKCHIP_OUT_MODE_S888_DUMMY; 229 conn_state->output_if = VOP_OUTPUT_IF_RGB; 230 break; 231 case MEDIA_BUS_FMT_YUYV8_2X8: 232 case MEDIA_BUS_FMT_YVYU8_2X8: 233 case MEDIA_BUS_FMT_UYVY8_2X8: 234 case MEDIA_BUS_FMT_VYUY8_2X8: 235 conn_state->output_mode = ROCKCHIP_OUT_MODE_BT656; 236 conn_state->output_if = VOP_OUTPUT_IF_BT656; 237 conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; 238 conn_state->color_encoding = DRM_COLOR_YCBCR_BT601; 239 break; 240 case MEDIA_BUS_FMT_YUYV8_1X16: 241 case MEDIA_BUS_FMT_YVYU8_1X16: 242 case MEDIA_BUS_FMT_UYVY8_1X16: 243 case MEDIA_BUS_FMT_VYUY8_1X16: 244 conn_state->output_mode = ROCKCHIP_OUT_MODE_BT1120; 245 conn_state->output_if = VOP_OUTPUT_IF_BT1120; 246 conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; 247 break; 248 case MEDIA_BUS_FMT_RGB888_1X24: 249 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 250 default: 251 conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 252 conn_state->output_if = VOP_OUTPUT_IF_RGB; 253 break; 254 } 255 256 return 0; 257 } 258 259 static int rockchip_rgb_connector_mode_valid(struct rockchip_connector *conn, 260 struct display_state *state) 261 { 262 struct rockchip_rgb *rgb = dev_get_priv(conn->dev); 263 struct connector_state *conn_state = &state->conn_state; 264 struct crtc_state *crtc_state = &state->crtc_state; 265 struct drm_display_mode *mode = &conn_state->mode; 266 u32 request_clock = mode->clock; 267 u32 max_clock = rgb->max_dclk_rate; 268 269 if (mode->flags & DRM_MODE_FLAG_DBLCLK) 270 request_clock *= 2; 271 272 if (rgb->data_sync_bypass) 273 request_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format) * 274 (crtc_state->mcu_timing.mcu_pix_total + 1); 275 276 if (max_clock != 0 && request_clock > max_clock) { 277 printf("mode [%dx%d] clock %d is higher than max_clock %d\n", 278 mode->hdisplay, mode->vdisplay, request_clock, max_clock); 279 return -EINVAL; 280 } 281 282 return 0; 283 } 284 285 static const struct rockchip_connector_funcs rockchip_rgb_connector_funcs = { 286 .init = rockchip_rgb_connector_init, 287 .prepare = rockchip_rgb_connector_prepare, 288 .unprepare = rockchip_rgb_connector_unprepare, 289 .mode_valid = rockchip_rgb_connector_mode_valid, 290 }; 291 292 static int rockchip_mcu_panel_send_cmds(struct display_state *state, 293 struct mcu_cmd_seq *cmds) 294 { 295 int i; 296 297 if (!cmds) 298 return -EINVAL; 299 300 display_send_mcu_cmd(state, MCU_SETBYPASS, 1); 301 for (i = 0; i < cmds->cmd_cnt; i++) { 302 struct mcu_cmd_desc *desc = &cmds->cmds[i]; 303 int value = 0; 304 305 value = desc->payload[0]; 306 display_send_mcu_cmd(state, desc->header.data_type, value); 307 308 if (desc->header.delay) 309 mdelay(desc->header.delay); 310 } 311 display_send_mcu_cmd(state, MCU_SETBYPASS, 0); 312 313 return 0; 314 } 315 316 static void rockchip_mcu_panel_prepare(struct rockchip_panel *panel) 317 { 318 struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel); 319 int ret; 320 321 if (mcu_panel->prepared) 322 return; 323 324 if (dm_gpio_is_valid(&mcu_panel->enable_gpio)) 325 dm_gpio_set_value(&mcu_panel->enable_gpio, 1); 326 327 if (mcu_panel->desc->delay.prepare) 328 mdelay(mcu_panel->desc->delay.prepare); 329 330 if (dm_gpio_is_valid(&mcu_panel->reset_gpio)) 331 dm_gpio_set_value(&mcu_panel->reset_gpio, 1); 332 333 if (mcu_panel->desc->delay.reset) 334 mdelay(mcu_panel->desc->delay.reset); 335 336 if (dm_gpio_is_valid(&mcu_panel->reset_gpio)) 337 dm_gpio_set_value(&mcu_panel->reset_gpio, 0); 338 339 if (mcu_panel->desc->delay.init) 340 mdelay(mcu_panel->desc->delay.init); 341 342 if (mcu_panel->desc->init_seq) { 343 ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->init_seq); 344 if (ret) 345 printf("failed to send mcu panel init cmds: %d\n", ret); 346 } 347 348 mcu_panel->prepared = true; 349 } 350 351 static void rockchip_mcu_panel_unprepare(struct rockchip_panel *panel) 352 { 353 struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel); 354 int ret; 355 356 if (!mcu_panel->prepared) 357 return; 358 359 if (mcu_panel->desc->exit_seq) { 360 ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->exit_seq); 361 if (ret) 362 printf("failed to send mcu panel exit cmds: %d\n", ret); 363 } 364 365 if (dm_gpio_is_valid(&mcu_panel->reset_gpio)) 366 dm_gpio_set_value(&mcu_panel->reset_gpio, 1); 367 368 if (dm_gpio_is_valid(&mcu_panel->enable_gpio)) 369 dm_gpio_set_value(&mcu_panel->enable_gpio, 0); 370 371 if (mcu_panel->desc->delay.unprepare) 372 mdelay(mcu_panel->desc->delay.unprepare); 373 374 mcu_panel->prepared = false; 375 } 376 377 static void rockchip_mcu_panel_enable(struct rockchip_panel *panel) 378 { 379 struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel); 380 381 if (mcu_panel->enabled) 382 return; 383 384 if (mcu_panel->desc->delay.enable) 385 mdelay(mcu_panel->desc->delay.enable); 386 387 if (mcu_panel->backlight) 388 backlight_enable(mcu_panel->backlight); 389 390 mcu_panel->enabled = true; 391 } 392 393 static void rockchip_mcu_panel_disable(struct rockchip_panel *panel) 394 { 395 struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel); 396 397 if (!mcu_panel->enabled) 398 return; 399 400 if (mcu_panel->backlight) 401 backlight_disable(mcu_panel->backlight); 402 403 if (mcu_panel->desc->delay.disable) 404 mdelay(mcu_panel->desc->delay.disable); 405 406 mcu_panel->enabled = false; 407 } 408 409 static const struct rockchip_panel_funcs rockchip_mcu_panel_funcs = { 410 .prepare = rockchip_mcu_panel_prepare, 411 .unprepare = rockchip_mcu_panel_unprepare, 412 .enable = rockchip_mcu_panel_enable, 413 .disable = rockchip_mcu_panel_disable, 414 }; 415 416 static int rockchip_mcu_panel_parse_cmds(const u8 *data, int length, 417 struct mcu_cmd_seq *pcmds) 418 { 419 int len; 420 const u8 *buf; 421 const struct mcu_cmd_header *header; 422 int i, cnt = 0; 423 424 /* scan commands */ 425 cnt = 0; 426 buf = data; 427 len = length; 428 while (len > sizeof(*header)) { 429 header = (const struct mcu_cmd_header *)buf; 430 buf += sizeof(*header) + header->payload_length; 431 len -= sizeof(*header) + header->payload_length; 432 cnt++; 433 } 434 435 pcmds->cmds = calloc(cnt, sizeof(struct mcu_cmd_desc)); 436 if (!pcmds->cmds) 437 return -ENOMEM; 438 439 pcmds->cmd_cnt = cnt; 440 441 buf = data; 442 len = length; 443 for (i = 0; i < cnt; i++) { 444 struct mcu_cmd_desc *desc = &pcmds->cmds[i]; 445 446 header = (const struct mcu_cmd_header *)buf; 447 length -= sizeof(*header); 448 buf += sizeof(*header); 449 desc->header.data_type = header->data_type; 450 desc->header.delay = header->delay; 451 desc->header.payload_length = header->payload_length; 452 desc->payload = buf; 453 buf += header->payload_length; 454 length -= header->payload_length; 455 } 456 457 return 0; 458 } 459 460 static int rockchip_mcu_panel_init(struct rockchip_mcu_panel *mcu_panel, ofnode mcu_panel_node) 461 { 462 const void *data; 463 int len; 464 int ret; 465 466 ret = gpio_request_by_name_nodev(mcu_panel_node, "enable-gpios", 0, 467 &mcu_panel->enable_gpio, GPIOD_IS_OUT); 468 if (ret && ret != -ENOENT) { 469 printf("%s: Cannot get mcu panel enable GPIO: %d\n", __func__, ret); 470 return ret; 471 } 472 473 ret = gpio_request_by_name_nodev(mcu_panel_node, "reset-gpios", 0, 474 &mcu_panel->reset_gpio, GPIOD_IS_OUT); 475 if (ret && ret != -ENOENT) { 476 printf("%s: Cannot get mcu panel reset GPIO: %d\n", __func__, ret); 477 return ret; 478 } 479 480 mcu_panel->desc = malloc(sizeof(struct rockchip_mcu_panel_desc)); 481 if (!mcu_panel->desc) 482 return -ENOMEM; 483 484 mcu_panel->desc->power_invert = ofnode_read_bool(mcu_panel_node, "power-invert"); 485 486 mcu_panel->desc->delay.prepare = ofnode_read_u32_default(mcu_panel_node, "prepare-delay-ms", 0); 487 mcu_panel->desc->delay.unprepare = ofnode_read_u32_default(mcu_panel_node, "unprepare-delay-ms", 0); 488 mcu_panel->desc->delay.enable = ofnode_read_u32_default(mcu_panel_node, "enable-delay-ms", 0); 489 mcu_panel->desc->delay.disable = ofnode_read_u32_default(mcu_panel_node, "disable-delay-ms", 0); 490 mcu_panel->desc->delay.init = ofnode_read_u32_default(mcu_panel_node, "init-delay-ms", 0); 491 mcu_panel->desc->delay.reset = ofnode_read_u32_default(mcu_panel_node, "reset-delay-ms", 0); 492 493 mcu_panel->desc->bus_format = ofnode_read_u32_default(mcu_panel_node, "bus-format", 494 MEDIA_BUS_FMT_RBG888_1X24); 495 mcu_panel->desc->bpc = ofnode_read_u32_default(mcu_panel_node, "bpc", 8); 496 497 data = ofnode_get_property(mcu_panel_node, "panel-init-sequence", &len); 498 if (data) { 499 mcu_panel->desc->init_seq = calloc(1, sizeof(*mcu_panel->desc->init_seq)); 500 if (!mcu_panel->desc->init_seq) 501 return -ENOMEM; 502 503 ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->init_seq); 504 if (ret) { 505 printf("failed to parse panel init sequence\n"); 506 goto free_on_cmds; 507 } 508 } 509 510 data = ofnode_get_property(mcu_panel_node, "panel-exit-sequence", &len); 511 if (data) { 512 mcu_panel->desc->exit_seq = calloc(1, sizeof(*mcu_panel->desc->exit_seq)); 513 if (!mcu_panel->desc->exit_seq) { 514 ret = -ENOMEM; 515 goto free_on_cmds; 516 } 517 518 ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->exit_seq); 519 if (ret) { 520 printf("failed to parse panel exit sequence\n"); 521 goto free_cmds; 522 } 523 } 524 525 return 0; 526 527 free_cmds: 528 free(mcu_panel->desc->exit_seq); 529 free_on_cmds: 530 free(mcu_panel->desc->init_seq); 531 return ret; 532 } 533 534 static int rockchip_rgb_probe(struct udevice *dev) 535 { 536 struct rockchip_rgb *rgb = dev_get_priv(dev); 537 const struct rockchip_rgb_data *rgb_data; 538 ofnode mcu_panel_node; 539 int phandle; 540 int ret; 541 542 rgb->data_sync_bypass = dev_read_bool(dev, "rockchip,data-sync-bypass"); 543 rgb_data = (const struct rockchip_rgb_data *)dev_get_driver_data(dev); 544 if (rgb_data) { 545 rgb->funcs = rgb_data->funcs; 546 if (rgb->data_sync_bypass) 547 rgb->max_dclk_rate = rgb_data->mcu_max_dclk_rate; 548 else 549 rgb->max_dclk_rate = rgb_data->rgb_max_dclk_rate; 550 rgb->dclk_delayline = rgb_data->dclk_delayline; 551 } 552 rgb->dev = dev; 553 rgb->grf = syscon_get_regmap(dev_get_parent(dev)); 554 rgb->id = of_alias_get_id(ofnode_to_np(dev->node), "rgb"); 555 if (rgb->id < 0) 556 rgb->id = 0; 557 558 mcu_panel_node = dev_read_subnode(dev, "mcu-panel"); 559 if (ofnode_valid(mcu_panel_node) && ofnode_is_available(mcu_panel_node)) { 560 struct rockchip_mcu_panel *mcu_panel; 561 562 mcu_panel = malloc(sizeof(struct rockchip_mcu_panel)); 563 if (!mcu_panel) { 564 printf("failed to alloc mcu_panel data\n"); 565 return -ENOMEM; 566 } 567 568 ret = rockchip_mcu_panel_init(mcu_panel, mcu_panel_node); 569 if (ret < 0) { 570 printf("failed to init mcu_panel: %d\n", ret); 571 return ret; 572 } 573 574 phandle = ofnode_read_u32_default(mcu_panel_node, "backlight", -1); 575 if (phandle < 0) { 576 printf("failed to find backlight phandle\n"); 577 return -EINVAL; 578 } 579 580 ret = uclass_get_device_by_phandle_id(UCLASS_PANEL_BACKLIGHT, phandle, 581 &mcu_panel->backlight); 582 if (ret && ret != -ENOENT) { 583 printf("%s: failed to get backlight device: %d\n", __func__, ret); 584 return ret; 585 } 586 587 mcu_panel->base.dev = dev; 588 mcu_panel->base.bus_format = mcu_panel->desc->bus_format; 589 mcu_panel->base.bpc = mcu_panel->desc->bpc; 590 mcu_panel->base.funcs = &rockchip_mcu_panel_funcs; 591 mcu_panel->enabled = false; 592 mcu_panel->prepared = false; 593 594 rgb->connector.panel = &mcu_panel->base; 595 } 596 597 rockchip_connector_bind(&rgb->connector, dev, rgb->id, &rockchip_rgb_connector_funcs, 598 NULL, DRM_MODE_CONNECTOR_LVDS); 599 600 return 0; 601 } 602 603 static void rv1106_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 604 { 605 regmap_write(rgb->grf, RV1106_VENC_GRF_VOP_IO_WRAPPER, 606 RV1106_IO_BYPASS_SEL(rgb->data_sync_bypass ? 0x3 : 0x0)); 607 regmap_write(rgb->grf, RV1106_VOGRF_VOP_PIPE_BYPASS, 608 RV1106_VOP_PIPE_BYPASS(rgb->data_sync_bypass ? 0x3 : 0x0)); 609 } 610 611 static const struct rockchip_rgb_funcs rv1106_rgb_funcs = { 612 .prepare = rv1106_rgb_prepare, 613 }; 614 615 static const struct rockchip_rgb_data rv1106_rgb = { 616 .rgb_max_dclk_rate = 74250, 617 .mcu_max_dclk_rate = 150000, 618 .funcs = &rv1106_rgb_funcs, 619 }; 620 621 static void rv1126_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 622 { 623 regmap_write(rgb->grf, RV1126_GRF_IOFUNC_CON3, 624 RV1126_LCDC_IO_BYPASS(rgb->data_sync_bypass)); 625 } 626 627 static const struct rockchip_rgb_funcs rv1126_rgb_funcs = { 628 .prepare = rv1126_rgb_prepare, 629 }; 630 631 static const struct rockchip_rgb_data rv1126_rgb = { 632 .funcs = &rv1126_rgb_funcs, 633 }; 634 635 static void px30_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 636 { 637 regmap_write(rgb->grf, PX30_GRF_PD_VO_CON1, PX30_RGB_VOP_SEL(pipe) | 638 PX30_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass)); 639 } 640 641 static const struct rockchip_rgb_funcs px30_rgb_funcs = { 642 .prepare = px30_rgb_prepare, 643 }; 644 645 static const struct rockchip_rgb_data px30_rgb = { 646 .funcs = &px30_rgb_funcs, 647 }; 648 649 static void rk1808_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 650 { 651 regmap_write(rgb->grf, RK1808_GRF_PD_VO_CON1, 652 RK1808_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass)); 653 } 654 655 static const struct rockchip_rgb_funcs rk1808_rgb_funcs = { 656 .prepare = rk1808_rgb_prepare, 657 }; 658 659 static const struct rockchip_rgb_data rk1808_rgb = { 660 .funcs = &rk1808_rgb_funcs, 661 }; 662 663 static void rk3288_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 664 { 665 regmap_write(rgb->grf, RK3288_GRF_SOC_CON6, RK3288_LVDS_LCDC_SEL(pipe)); 666 regmap_write(rgb->grf, RK3288_GRF_SOC_CON7, 667 RK3288_LVDS_PWRDWN(0) | RK3288_LVDS_CON_ENABLE_2(1) | 668 RK3288_LVDS_CON_ENABLE_1(1) | RK3288_LVDS_CON_CLKINV(0) | 669 RK3288_LVDS_CON_TTL_EN(1)); 670 } 671 672 static void rk3288_rgb_unprepare(struct rockchip_rgb *rgb) 673 { 674 regmap_write(rgb->grf, RK3288_GRF_SOC_CON7, 675 RK3288_LVDS_PWRDWN(1) | RK3288_LVDS_CON_ENABLE_2(0) | 676 RK3288_LVDS_CON_ENABLE_1(0) | RK3288_LVDS_CON_TTL_EN(0)); 677 } 678 679 static const struct rockchip_rgb_funcs rk3288_rgb_funcs = { 680 .prepare = rk3288_rgb_prepare, 681 .unprepare = rk3288_rgb_unprepare, 682 }; 683 684 static const struct rockchip_rgb_data rk3288_rgb = { 685 .funcs = &rk3288_rgb_funcs, 686 }; 687 688 static void rk3368_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 689 { 690 regmap_write(rgb->grf, RK3368_GRF_SOC_CON15, RK3368_FORCE_JETAG(0)); 691 } 692 693 static const struct rockchip_rgb_funcs rk3368_rgb_funcs = { 694 .prepare = rk3368_rgb_prepare, 695 }; 696 697 static const struct rockchip_rgb_data rk3368_rgb = { 698 .funcs = &rk3368_rgb_funcs, 699 }; 700 701 static void rk3506_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 702 { 703 regmap_write(rgb->grf, RK3506_GRF_SOC_CON2, 704 RK3506_GRF_VOP_DATA_BYPASS(rgb->data_sync_bypass ? 0x3 : 0x0)); 705 } 706 707 static const struct rockchip_rgb_funcs rk3506_rgb_funcs = { 708 .prepare = rk3506_rgb_prepare, 709 }; 710 711 static const struct rockchip_rgb_data rk3506_rgb = { 712 .rgb_max_dclk_rate = 120000, 713 .mcu_max_dclk_rate = 120000, 714 .funcs = &rk3506_rgb_funcs, 715 }; 716 717 static void rk3562_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 718 { 719 regmap_write(rgb->grf, RK3562_GRF_IOC_VO_IO_CON, 720 RK3562_RGB_DATA_BYPASS(rgb->data_sync_bypass)); 721 } 722 723 static const struct rockchip_rgb_funcs rk3562_rgb_funcs = { 724 .prepare = rk3562_rgb_prepare, 725 }; 726 727 static const struct rockchip_rgb_data rk3562_rgb = { 728 .funcs = &rk3562_rgb_funcs, 729 }; 730 731 static void rk3568_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 732 { 733 regmap_write(rgb->grf, RK3568_GRF_VO_CON1, RK3568_RGB_DATA_BYPASS(rgb->data_sync_bypass)); 734 } 735 736 static const struct rockchip_rgb_funcs rk3568_rgb_funcs = { 737 .prepare = rk3568_rgb_prepare, 738 }; 739 740 static const struct rockchip_rgb_data rk3568_rgb = { 741 .funcs = &rk3568_rgb_funcs, 742 }; 743 744 static void rk3576_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 745 { 746 regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8, 747 RK3576_VOP_MCU_SEL(rgb->data_sync_bypass)); 748 regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8, 749 RK3576_VOP_DLL_SEL(true)); 750 regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8, 751 RK3576_VOP_DCLK_DELAYLINE(rgb->dclk_delayline)); 752 } 753 754 static const struct rockchip_rgb_funcs rk3576_rgb_funcs = { 755 .prepare = rk3576_rgb_prepare, 756 }; 757 758 static const struct rockchip_rgb_data rk3576_rgb = { 759 .dclk_delayline = 5, 760 .funcs = &rk3576_rgb_funcs, 761 }; 762 763 static const struct udevice_id rockchip_rgb_ids[] = { 764 { 765 .compatible = "rockchip,px30-rgb", 766 .data = (ulong)&px30_rgb, 767 }, 768 { 769 .compatible = "rockchip,rk1808-rgb", 770 .data = (ulong)&rk1808_rgb, 771 }, 772 { 773 .compatible = "rockchip,rk3066-rgb", 774 }, 775 { 776 .compatible = "rockchip,rk3128-rgb", 777 }, 778 { 779 .compatible = "rockchip,rk3288-rgb", 780 .data = (ulong)&rk3288_rgb, 781 }, 782 { 783 .compatible = "rockchip,rk3308-rgb", 784 }, 785 { 786 .compatible = "rockchip,rk3368-rgb", 787 .data = (ulong)&rk3368_rgb, 788 }, 789 { 790 .compatible = "rockchip,rk3506-rgb", 791 .data = (ulong)&rk3506_rgb, 792 }, 793 { 794 .compatible = "rockchip,rk3562-rgb", 795 .data = (ulong)&rk3562_rgb, 796 }, 797 { 798 .compatible = "rockchip,rk3568-rgb", 799 .data = (ulong)&rk3568_rgb, 800 }, 801 { 802 .compatible = "rockchip,rk3576-rgb", 803 .data = (ulong)&rk3576_rgb, 804 }, 805 { 806 .compatible = "rockchip,rk3588-rgb", 807 }, 808 { 809 .compatible = "rockchip,rv1106-rgb", 810 .data = (ulong)&rv1106_rgb, 811 }, 812 { 813 .compatible = "rockchip,rv1108-rgb", 814 }, 815 { 816 .compatible = "rockchip,rv1126-rgb", 817 .data = (ulong)&rv1126_rgb, 818 }, 819 {} 820 }; 821 822 U_BOOT_DRIVER(rockchip_rgb) = { 823 .name = "rockchip_rgb", 824 .id = UCLASS_DISPLAY, 825 .of_match = rockchip_rgb_ids, 826 .probe = rockchip_rgb_probe, 827 .priv_auto_alloc_size = sizeof(struct rockchip_rgb), 828 }; 829