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