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