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 <video.h> 12 #include <backlight.h> 13 #include <asm/gpio.h> 14 #include <dm/device.h> 15 #include <dm/read.h> 16 #include <dm/uclass.h> 17 #include <dm/uclass-id.h> 18 #include <linux/media-bus-format.h> 19 #include <power/regulator.h> 20 21 #include "rockchip_display.h" 22 #include "rockchip_crtc.h" 23 #include "rockchip_connector.h" 24 #include "rockchip_mipi_dsi.h" 25 #include "rockchip_panel.h" 26 27 struct rockchip_cmd_header { 28 u8 data_type; 29 u8 delay_ms; 30 u8 payload_length; 31 } __packed; 32 33 struct rockchip_cmd_desc { 34 struct rockchip_cmd_header header; 35 const u8 *payload; 36 }; 37 38 struct rockchip_panel_cmds { 39 struct rockchip_cmd_desc *cmds; 40 int cmd_cnt; 41 }; 42 43 struct rockchip_panel_plat { 44 bool power_invert; 45 u32 bus_format; 46 47 struct { 48 unsigned int prepare; 49 unsigned int unprepare; 50 unsigned int enable; 51 unsigned int disable; 52 unsigned int reset; 53 unsigned int init; 54 } delay; 55 56 struct rockchip_panel_cmds *on_cmds; 57 struct rockchip_panel_cmds *off_cmds; 58 }; 59 60 struct rockchip_panel_priv { 61 bool prepared; 62 bool enabled; 63 struct udevice *power_supply; 64 struct udevice *backlight; 65 struct gpio_desc enable_gpio; 66 struct gpio_desc reset_gpio; 67 68 int cmd_type; 69 struct gpio_desc spi_sdi_gpio; 70 struct gpio_desc spi_scl_gpio; 71 struct gpio_desc spi_cs_gpio; 72 }; 73 74 static inline int get_panel_cmd_type(const char *s) 75 { 76 if (!s) 77 return -EINVAL; 78 79 if (strncmp(s, "spi", 3) == 0) 80 return CMD_TYPE_SPI; 81 else if (strncmp(s, "mcu", 3) == 0) 82 return CMD_TYPE_MCU; 83 84 return CMD_TYPE_DEFAULT; 85 } 86 87 static int rockchip_panel_parse_cmds(const u8 *data, int length, 88 struct rockchip_panel_cmds *pcmds) 89 { 90 int len; 91 const u8 *buf; 92 const struct rockchip_cmd_header *header; 93 int i, cnt = 0; 94 95 /* scan commands */ 96 cnt = 0; 97 buf = data; 98 len = length; 99 while (len > sizeof(*header)) { 100 header = (const struct rockchip_cmd_header *)buf; 101 buf += sizeof(*header) + header->payload_length; 102 len -= sizeof(*header) + header->payload_length; 103 cnt++; 104 } 105 106 pcmds->cmds = calloc(cnt, sizeof(struct rockchip_cmd_desc)); 107 if (!pcmds->cmds) 108 return -ENOMEM; 109 110 pcmds->cmd_cnt = cnt; 111 112 buf = data; 113 len = length; 114 for (i = 0; i < cnt; i++) { 115 struct rockchip_cmd_desc *desc = &pcmds->cmds[i]; 116 117 header = (const struct rockchip_cmd_header *)buf; 118 length -= sizeof(*header); 119 buf += sizeof(*header); 120 desc->header.data_type = header->data_type; 121 desc->header.delay_ms = header->delay_ms; 122 desc->header.payload_length = header->payload_length; 123 desc->payload = buf; 124 buf += header->payload_length; 125 length -= header->payload_length; 126 } 127 128 return 0; 129 } 130 131 static void rockchip_panel_write_spi_cmds(struct rockchip_panel_priv *priv, 132 u8 type, int value) 133 { 134 int i; 135 136 dm_gpio_set_value(&priv->spi_cs_gpio, 0); 137 138 if (type == 0) 139 value &= (~(1 << 8)); 140 else 141 value |= (1 << 8); 142 143 for (i = 0; i < 9; i++) { 144 if (value & 0x100) 145 dm_gpio_set_value(&priv->spi_sdi_gpio, 1); 146 else 147 dm_gpio_set_value(&priv->spi_sdi_gpio, 0); 148 149 dm_gpio_set_value(&priv->spi_scl_gpio, 0); 150 udelay(10); 151 dm_gpio_set_value(&priv->spi_scl_gpio, 1); 152 value <<= 1; 153 udelay(10); 154 } 155 156 dm_gpio_set_value(&priv->spi_cs_gpio, 1); 157 } 158 159 static int rockchip_panel_send_mcu_cmds(struct display_state *state, 160 struct rockchip_panel_cmds *cmds) 161 { 162 int i; 163 164 if (!cmds) 165 return -EINVAL; 166 167 display_send_mcu_cmd(state, MCU_SETBYPASS, 1); 168 for (i = 0; i < cmds->cmd_cnt; i++) { 169 struct rockchip_cmd_desc *desc = &cmds->cmds[i]; 170 int value = 0; 171 172 value = desc->payload[0]; 173 display_send_mcu_cmd(state, desc->header.data_type, value); 174 175 if (desc->header.delay_ms) 176 mdelay(desc->header.delay_ms); 177 } 178 display_send_mcu_cmd(state, MCU_SETBYPASS, 0); 179 180 return 0; 181 } 182 183 static int rockchip_panel_send_spi_cmds(struct display_state *state, 184 struct rockchip_panel_cmds *cmds) 185 { 186 struct rockchip_panel *panel = state_get_panel(state); 187 struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 188 int i; 189 190 if (!cmds) 191 return -EINVAL; 192 193 for (i = 0; i < cmds->cmd_cnt; i++) { 194 struct rockchip_cmd_desc *desc = &cmds->cmds[i]; 195 int value = 0; 196 197 if (desc->header.payload_length == 2) 198 value = (desc->payload[0] << 8) | desc->payload[1]; 199 else 200 value = desc->payload[0]; 201 rockchip_panel_write_spi_cmds(priv, 202 desc->header.data_type, value); 203 204 if (desc->header.delay_ms) 205 mdelay(desc->header.delay_ms); 206 } 207 208 return 0; 209 } 210 211 static int rockchip_panel_send_dsi_cmds(struct display_state *state, 212 struct rockchip_panel_cmds *cmds) 213 { 214 int i, ret; 215 216 if (!cmds) 217 return -EINVAL; 218 219 for (i = 0; i < cmds->cmd_cnt; i++) { 220 struct rockchip_cmd_desc *desc = &cmds->cmds[i]; 221 222 switch (desc->header.data_type) { 223 case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: 224 case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: 225 case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: 226 case MIPI_DSI_GENERIC_LONG_WRITE: 227 ret = mipi_dsi_generic_write(state, desc->payload, 228 desc->header.payload_length); 229 break; 230 case MIPI_DSI_DCS_SHORT_WRITE: 231 case MIPI_DSI_DCS_SHORT_WRITE_PARAM: 232 case MIPI_DSI_DCS_LONG_WRITE: 233 ret = mipi_dsi_dcs_write(state, desc->payload, 234 desc->header.payload_length); 235 break; 236 default: 237 printf("unsupport command data type: %d\n", 238 desc->header.data_type); 239 return -EINVAL; 240 } 241 242 if (ret < 0) { 243 printf("failed to write cmd%d: %d\n", i, ret); 244 return ret; 245 } 246 247 if (desc->header.delay_ms) 248 mdelay(desc->header.delay_ms); 249 } 250 251 return 0; 252 } 253 254 static void panel_simple_prepare(struct rockchip_panel *panel) 255 { 256 struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 257 struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 258 int ret; 259 260 if (priv->prepared) 261 return; 262 263 if (priv->power_supply) 264 regulator_set_enable(priv->power_supply, !plat->power_invert); 265 266 if (dm_gpio_is_valid(&priv->enable_gpio)) 267 dm_gpio_set_value(&priv->enable_gpio, 1); 268 269 if (plat->delay.prepare) 270 mdelay(plat->delay.prepare); 271 272 if (dm_gpio_is_valid(&priv->reset_gpio)) 273 dm_gpio_set_value(&priv->reset_gpio, 1); 274 275 if (plat->delay.reset) 276 mdelay(plat->delay.reset); 277 278 if (dm_gpio_is_valid(&priv->reset_gpio)) 279 dm_gpio_set_value(&priv->reset_gpio, 0); 280 281 if (plat->delay.init) 282 mdelay(plat->delay.init); 283 284 if (plat->on_cmds) { 285 if (priv->cmd_type == CMD_TYPE_SPI) 286 ret = rockchip_panel_send_spi_cmds(panel->state, 287 plat->on_cmds); 288 else if (priv->cmd_type == CMD_TYPE_MCU) 289 ret = rockchip_panel_send_mcu_cmds(panel->state, 290 plat->on_cmds); 291 else 292 ret = rockchip_panel_send_dsi_cmds(panel->state, 293 plat->on_cmds); 294 if (ret) 295 printf("failed to send on cmds: %d\n", ret); 296 } 297 298 priv->prepared = true; 299 } 300 301 static void panel_simple_unprepare(struct rockchip_panel *panel) 302 { 303 struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 304 struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 305 int ret; 306 307 if (!priv->prepared) 308 return; 309 310 if (plat->off_cmds) { 311 if (priv->cmd_type == CMD_TYPE_SPI) 312 ret = rockchip_panel_send_spi_cmds(panel->state, 313 plat->off_cmds); 314 else if (priv->cmd_type == CMD_TYPE_MCU) 315 ret = rockchip_panel_send_mcu_cmds(panel->state, 316 plat->off_cmds); 317 else 318 ret = rockchip_panel_send_dsi_cmds(panel->state, 319 plat->off_cmds); 320 if (ret) 321 printf("failed to send off cmds: %d\n", ret); 322 } 323 324 if (dm_gpio_is_valid(&priv->reset_gpio)) 325 dm_gpio_set_value(&priv->reset_gpio, 1); 326 327 if (dm_gpio_is_valid(&priv->enable_gpio)) 328 dm_gpio_set_value(&priv->enable_gpio, 0); 329 330 if (priv->power_supply) 331 regulator_set_enable(priv->power_supply, plat->power_invert); 332 333 if (plat->delay.unprepare) 334 mdelay(plat->delay.unprepare); 335 336 priv->prepared = false; 337 } 338 339 static void panel_simple_enable(struct rockchip_panel *panel) 340 { 341 struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 342 struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 343 344 if (priv->enabled) 345 return; 346 347 if (plat->delay.enable) 348 mdelay(plat->delay.enable); 349 350 if (priv->backlight) 351 backlight_enable(priv->backlight); 352 353 priv->enabled = true; 354 } 355 356 static void panel_simple_disable(struct rockchip_panel *panel) 357 { 358 struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 359 struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 360 361 if (!priv->enabled) 362 return; 363 364 if (priv->backlight) 365 backlight_disable(priv->backlight); 366 367 if (plat->delay.disable) 368 mdelay(plat->delay.disable); 369 370 priv->enabled = false; 371 } 372 373 static void panel_simple_init(struct rockchip_panel *panel) 374 { 375 struct display_state *state = panel->state; 376 struct connector_state *conn_state = &state->conn_state; 377 378 conn_state->bus_format = panel->bus_format; 379 } 380 381 static const struct rockchip_panel_funcs rockchip_panel_funcs = { 382 .init = panel_simple_init, 383 .prepare = panel_simple_prepare, 384 .unprepare = panel_simple_unprepare, 385 .enable = panel_simple_enable, 386 .disable = panel_simple_disable, 387 }; 388 389 static int rockchip_panel_ofdata_to_platdata(struct udevice *dev) 390 { 391 struct rockchip_panel_plat *plat = dev_get_platdata(dev); 392 const void *data; 393 int len = 0; 394 int ret; 395 396 plat->power_invert = dev_read_bool(dev, "power-invert"); 397 398 plat->delay.prepare = dev_read_u32_default(dev, "prepare-delay-ms", 0); 399 plat->delay.unprepare = dev_read_u32_default(dev, "unprepare-delay-ms", 0); 400 plat->delay.enable = dev_read_u32_default(dev, "enable-delay-ms", 0); 401 plat->delay.disable = dev_read_u32_default(dev, "disable-delay-ms", 0); 402 plat->delay.init = dev_read_u32_default(dev, "init-delay-ms", 0); 403 plat->delay.reset = dev_read_u32_default(dev, "reset-delay-ms", 0); 404 405 plat->bus_format = dev_read_u32_default(dev, "bus-format", 406 MEDIA_BUS_FMT_RBG888_1X24); 407 408 data = dev_read_prop(dev, "panel-init-sequence", &len); 409 if (data) { 410 plat->on_cmds = calloc(1, sizeof(*plat->on_cmds)); 411 if (!plat->on_cmds) 412 return -ENOMEM; 413 414 ret = rockchip_panel_parse_cmds(data, len, plat->on_cmds); 415 if (ret) { 416 printf("failed to parse panel init sequence\n"); 417 goto free_on_cmds; 418 } 419 } 420 421 data = dev_read_prop(dev, "panel-exit-sequence", &len); 422 if (data) { 423 plat->off_cmds = calloc(1, sizeof(*plat->off_cmds)); 424 if (!plat->off_cmds) { 425 ret = -ENOMEM; 426 goto free_on_cmds; 427 } 428 429 ret = rockchip_panel_parse_cmds(data, len, plat->off_cmds); 430 if (ret) { 431 printf("failed to parse panel exit sequence\n"); 432 goto free_cmds; 433 } 434 } 435 436 return 0; 437 438 free_cmds: 439 free(plat->off_cmds); 440 free_on_cmds: 441 free(plat->on_cmds); 442 return ret; 443 } 444 445 static int rockchip_panel_probe(struct udevice *dev) 446 { 447 struct rockchip_panel_priv *priv = dev_get_priv(dev); 448 struct rockchip_panel_plat *plat = dev_get_platdata(dev); 449 struct rockchip_panel *panel = 450 (struct rockchip_panel *)dev_get_driver_data(dev); 451 int ret; 452 const char *cmd_type; 453 454 ret = gpio_request_by_name(dev, "enable-gpios", 0, 455 &priv->enable_gpio, GPIOD_IS_OUT); 456 if (ret && ret != -ENOENT) { 457 printf("%s: Cannot get enable GPIO: %d\n", __func__, ret); 458 return ret; 459 } 460 461 ret = gpio_request_by_name(dev, "reset-gpios", 0, 462 &priv->reset_gpio, GPIOD_IS_OUT); 463 if (ret && ret != -ENOENT) { 464 printf("%s: Cannot get reset GPIO: %d\n", __func__, ret); 465 return ret; 466 } 467 468 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, 469 "backlight", &priv->backlight); 470 if (ret && ret != -ENOENT) { 471 printf("%s: Cannot get backlight: %d\n", __func__, ret); 472 return ret; 473 } 474 475 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, 476 "power-supply", &priv->power_supply); 477 if (ret && ret != -ENOENT) { 478 printf("%s: Cannot get power supply: %d\n", __func__, ret); 479 return ret; 480 } 481 482 ret = dev_read_string_index(dev, "rockchip,cmd-type", 0, &cmd_type); 483 if (ret) 484 priv->cmd_type = CMD_TYPE_DEFAULT; 485 else 486 priv->cmd_type = get_panel_cmd_type(cmd_type); 487 488 if (priv->cmd_type == CMD_TYPE_SPI) { 489 ret = gpio_request_by_name(dev, "spi-sdi-gpios", 0, 490 &priv->spi_sdi_gpio, GPIOD_IS_OUT); 491 if (ret && ret != -ENOENT) { 492 printf("%s: Cannot get spi sdi GPIO: %d\n", 493 __func__, ret); 494 return ret; 495 } 496 ret = gpio_request_by_name(dev, "spi-scl-gpios", 0, 497 &priv->spi_scl_gpio, GPIOD_IS_OUT); 498 if (ret && ret != -ENOENT) { 499 printf("%s: Cannot get spi scl GPIO: %d\n", 500 __func__, ret); 501 return ret; 502 } 503 ret = gpio_request_by_name(dev, "spi-cs-gpios", 0, 504 &priv->spi_cs_gpio, GPIOD_IS_OUT); 505 if (ret && ret != -ENOENT) { 506 printf("%s: Cannot get spi cs GPIO: %d\n", 507 __func__, ret); 508 return ret; 509 } 510 dm_gpio_set_value(&priv->spi_sdi_gpio, 1); 511 dm_gpio_set_value(&priv->spi_scl_gpio, 1); 512 dm_gpio_set_value(&priv->spi_cs_gpio, 1); 513 dm_gpio_set_value(&priv->reset_gpio, 0); 514 } 515 516 panel->dev = dev; 517 panel->bus_format = plat->bus_format; 518 519 return 0; 520 } 521 522 static const struct drm_display_mode auo_b125han03_mode = { 523 .clock = 146900, 524 .hdisplay = 1920, 525 .hsync_start = 1920 + 48, 526 .hsync_end = 1920 + 48 + 32, 527 .htotal = 1920 + 48 + 32 + 140, 528 .vdisplay = 1080, 529 .vsync_start = 1080 + 2, 530 .vsync_end = 1080 + 2 + 5, 531 .vtotal = 1080 + 2 + 5 + 57, 532 .vrefresh = 60, 533 .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, 534 }; 535 536 static const struct rockchip_panel auo_b125han03_driver_data = { 537 .funcs = &rockchip_panel_funcs, 538 .data = &auo_b125han03_mode, 539 }; 540 541 static const struct drm_display_mode lg_lp079qx1_sp0v_mode = { 542 .clock = 200000, 543 .hdisplay = 1536, 544 .hsync_start = 1536 + 12, 545 .hsync_end = 1536 + 12 + 16, 546 .htotal = 1536 + 12 + 16 + 48, 547 .vdisplay = 2048, 548 .vsync_start = 2048 + 8, 549 .vsync_end = 2048 + 8 + 4, 550 .vtotal = 2048 + 8 + 4 + 8, 551 .vrefresh = 60, 552 .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, 553 }; 554 555 static const struct rockchip_panel lg_lp079qx1_sp0v_driver_data = { 556 .funcs = &rockchip_panel_funcs, 557 .data = &lg_lp079qx1_sp0v_mode, 558 }; 559 560 static const struct rockchip_panel panel_simple_driver_data = { 561 .funcs = &rockchip_panel_funcs, 562 }; 563 564 static const struct rockchip_panel panel_simple_dsi_driver_data = { 565 .funcs = &rockchip_panel_funcs, 566 }; 567 568 static const struct udevice_id rockchip_panel_ids[] = { 569 { 570 .compatible = "auo,b125han03", 571 .data = (ulong)&auo_b125han03_driver_data, 572 }, { 573 .compatible = "lg,lp079qx1-sp0v", 574 .data = (ulong)&lg_lp079qx1_sp0v_driver_data, 575 }, { 576 .compatible = "simple-panel", 577 .data = (ulong)&panel_simple_driver_data, 578 }, { 579 .compatible = "simple-panel-dsi", 580 .data = (ulong)&panel_simple_dsi_driver_data, 581 }, 582 {} 583 }; 584 585 U_BOOT_DRIVER(rockchip_panel) = { 586 .name = "rockchip_panel", 587 .id = UCLASS_PANEL, 588 .of_match = rockchip_panel_ids, 589 .ofdata_to_platdata = rockchip_panel_ofdata_to_platdata, 590 .probe = rockchip_panel_probe, 591 .priv_auto_alloc_size = sizeof(struct rockchip_panel_priv), 592 .platdata_auto_alloc_size = sizeof(struct rockchip_panel_plat), 593 }; 594