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