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 218 if (!cmds) 219 return -EINVAL; 220 221 for (i = 0; i < cmds->cmd_cnt; i++) { 222 struct rockchip_cmd_desc *desc = &cmds->cmds[i]; 223 const struct rockchip_cmd_header *header = &desc->header; 224 225 switch (header->data_type) { 226 case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: 227 case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: 228 case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: 229 case MIPI_DSI_GENERIC_LONG_WRITE: 230 ret = mipi_dsi_generic_write(dsi, desc->payload, 231 header->payload_length); 232 break; 233 case MIPI_DSI_DCS_SHORT_WRITE: 234 case MIPI_DSI_DCS_SHORT_WRITE_PARAM: 235 case MIPI_DSI_DCS_LONG_WRITE: 236 ret = mipi_dsi_dcs_write_buffer(dsi, desc->payload, 237 header->payload_length); 238 break; 239 default: 240 printf("unsupport command data type: %d\n", 241 header->data_type); 242 return -EINVAL; 243 } 244 245 if (ret < 0) { 246 printf("failed to write cmd%d: %d\n", i, ret); 247 return ret; 248 } 249 250 if (header->delay_ms) 251 mdelay(header->delay_ms); 252 } 253 254 return 0; 255 } 256 257 static void panel_simple_prepare(struct rockchip_panel *panel) 258 { 259 struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 260 struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 261 struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev); 262 int ret; 263 264 if (priv->prepared) 265 return; 266 267 if (priv->power_supply) 268 regulator_set_enable(priv->power_supply, !plat->power_invert); 269 270 if (dm_gpio_is_valid(&priv->enable_gpio)) 271 dm_gpio_set_value(&priv->enable_gpio, 1); 272 273 if (plat->delay.prepare) 274 mdelay(plat->delay.prepare); 275 276 if (dm_gpio_is_valid(&priv->reset_gpio)) 277 dm_gpio_set_value(&priv->reset_gpio, 1); 278 279 if (plat->delay.reset) 280 mdelay(plat->delay.reset); 281 282 if (dm_gpio_is_valid(&priv->reset_gpio)) 283 dm_gpio_set_value(&priv->reset_gpio, 0); 284 285 if (plat->delay.init) 286 mdelay(plat->delay.init); 287 288 if (plat->on_cmds) { 289 if (priv->cmd_type == CMD_TYPE_SPI) 290 ret = rockchip_panel_send_spi_cmds(panel->state, 291 plat->on_cmds); 292 else if (priv->cmd_type == CMD_TYPE_MCU) 293 ret = rockchip_panel_send_mcu_cmds(panel->state, 294 plat->on_cmds); 295 else 296 ret = rockchip_panel_send_dsi_cmds(dsi, plat->on_cmds); 297 if (ret) 298 printf("failed to send on cmds: %d\n", ret); 299 } 300 301 priv->prepared = true; 302 } 303 304 static void panel_simple_unprepare(struct rockchip_panel *panel) 305 { 306 struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 307 struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 308 struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev); 309 int ret; 310 311 if (!priv->prepared) 312 return; 313 314 if (plat->off_cmds) { 315 if (priv->cmd_type == CMD_TYPE_SPI) 316 ret = rockchip_panel_send_spi_cmds(panel->state, 317 plat->off_cmds); 318 else if (priv->cmd_type == CMD_TYPE_MCU) 319 ret = rockchip_panel_send_mcu_cmds(panel->state, 320 plat->off_cmds); 321 else 322 ret = rockchip_panel_send_dsi_cmds(dsi, plat->off_cmds); 323 if (ret) 324 printf("failed to send off cmds: %d\n", ret); 325 } 326 327 if (dm_gpio_is_valid(&priv->reset_gpio)) 328 dm_gpio_set_value(&priv->reset_gpio, 1); 329 330 if (dm_gpio_is_valid(&priv->enable_gpio)) 331 dm_gpio_set_value(&priv->enable_gpio, 0); 332 333 if (priv->power_supply) 334 regulator_set_enable(priv->power_supply, plat->power_invert); 335 336 if (plat->delay.unprepare) 337 mdelay(plat->delay.unprepare); 338 339 priv->prepared = false; 340 } 341 342 static void panel_simple_enable(struct rockchip_panel *panel) 343 { 344 struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 345 struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 346 347 if (priv->enabled) 348 return; 349 350 if (plat->delay.enable) 351 mdelay(plat->delay.enable); 352 353 if (priv->backlight) 354 backlight_enable(priv->backlight); 355 356 priv->enabled = true; 357 } 358 359 static void panel_simple_disable(struct rockchip_panel *panel) 360 { 361 struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 362 struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 363 364 if (!priv->enabled) 365 return; 366 367 if (priv->backlight) 368 backlight_disable(priv->backlight); 369 370 if (plat->delay.disable) 371 mdelay(plat->delay.disable); 372 373 priv->enabled = false; 374 } 375 376 static void panel_simple_init(struct rockchip_panel *panel) 377 { 378 struct display_state *state = panel->state; 379 struct connector_state *conn_state = &state->conn_state; 380 381 conn_state->bus_format = panel->bus_format; 382 } 383 384 static const struct rockchip_panel_funcs rockchip_panel_funcs = { 385 .init = panel_simple_init, 386 .prepare = panel_simple_prepare, 387 .unprepare = panel_simple_unprepare, 388 .enable = panel_simple_enable, 389 .disable = panel_simple_disable, 390 }; 391 392 static int rockchip_panel_ofdata_to_platdata(struct udevice *dev) 393 { 394 struct rockchip_panel_plat *plat = dev_get_platdata(dev); 395 const void *data; 396 int len = 0; 397 int ret; 398 399 plat->power_invert = dev_read_bool(dev, "power-invert"); 400 401 plat->delay.prepare = dev_read_u32_default(dev, "prepare-delay-ms", 0); 402 plat->delay.unprepare = dev_read_u32_default(dev, "unprepare-delay-ms", 0); 403 plat->delay.enable = dev_read_u32_default(dev, "enable-delay-ms", 0); 404 plat->delay.disable = dev_read_u32_default(dev, "disable-delay-ms", 0); 405 plat->delay.init = dev_read_u32_default(dev, "init-delay-ms", 0); 406 plat->delay.reset = dev_read_u32_default(dev, "reset-delay-ms", 0); 407 408 plat->bus_format = dev_read_u32_default(dev, "bus-format", 409 MEDIA_BUS_FMT_RBG888_1X24); 410 plat->bpc = dev_read_u32_default(dev, "bpc", 8); 411 412 data = dev_read_prop(dev, "panel-init-sequence", &len); 413 if (data) { 414 plat->on_cmds = calloc(1, sizeof(*plat->on_cmds)); 415 if (!plat->on_cmds) 416 return -ENOMEM; 417 418 ret = rockchip_panel_parse_cmds(data, len, plat->on_cmds); 419 if (ret) { 420 printf("failed to parse panel init sequence\n"); 421 goto free_on_cmds; 422 } 423 } 424 425 data = dev_read_prop(dev, "panel-exit-sequence", &len); 426 if (data) { 427 plat->off_cmds = calloc(1, sizeof(*plat->off_cmds)); 428 if (!plat->off_cmds) { 429 ret = -ENOMEM; 430 goto free_on_cmds; 431 } 432 433 ret = rockchip_panel_parse_cmds(data, len, plat->off_cmds); 434 if (ret) { 435 printf("failed to parse panel exit sequence\n"); 436 goto free_cmds; 437 } 438 } 439 440 return 0; 441 442 free_cmds: 443 free(plat->off_cmds); 444 free_on_cmds: 445 free(plat->on_cmds); 446 return ret; 447 } 448 449 static int rockchip_panel_probe(struct udevice *dev) 450 { 451 struct rockchip_panel_priv *priv = dev_get_priv(dev); 452 struct rockchip_panel_plat *plat = dev_get_platdata(dev); 453 struct rockchip_panel *panel; 454 int ret; 455 const char *cmd_type; 456 457 ret = gpio_request_by_name(dev, "enable-gpios", 0, 458 &priv->enable_gpio, GPIOD_IS_OUT); 459 if (ret && ret != -ENOENT) { 460 printf("%s: Cannot get enable GPIO: %d\n", __func__, ret); 461 return ret; 462 } 463 464 ret = gpio_request_by_name(dev, "reset-gpios", 0, 465 &priv->reset_gpio, GPIOD_IS_OUT); 466 if (ret && ret != -ENOENT) { 467 printf("%s: Cannot get reset GPIO: %d\n", __func__, ret); 468 return ret; 469 } 470 471 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, 472 "backlight", &priv->backlight); 473 if (ret && ret != -ENOENT) { 474 printf("%s: Cannot get backlight: %d\n", __func__, ret); 475 return ret; 476 } 477 478 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, 479 "power-supply", &priv->power_supply); 480 if (ret && ret != -ENOENT) { 481 printf("%s: Cannot get power supply: %d\n", __func__, ret); 482 return ret; 483 } 484 485 ret = dev_read_string_index(dev, "rockchip,cmd-type", 0, &cmd_type); 486 if (ret) 487 priv->cmd_type = CMD_TYPE_DEFAULT; 488 else 489 priv->cmd_type = get_panel_cmd_type(cmd_type); 490 491 if (priv->cmd_type == CMD_TYPE_SPI) { 492 ret = gpio_request_by_name(dev, "spi-sdi-gpios", 0, 493 &priv->spi_sdi_gpio, GPIOD_IS_OUT); 494 if (ret && ret != -ENOENT) { 495 printf("%s: Cannot get spi sdi GPIO: %d\n", 496 __func__, ret); 497 return ret; 498 } 499 ret = gpio_request_by_name(dev, "spi-scl-gpios", 0, 500 &priv->spi_scl_gpio, GPIOD_IS_OUT); 501 if (ret && ret != -ENOENT) { 502 printf("%s: Cannot get spi scl GPIO: %d\n", 503 __func__, ret); 504 return ret; 505 } 506 ret = gpio_request_by_name(dev, "spi-cs-gpios", 0, 507 &priv->spi_cs_gpio, GPIOD_IS_OUT); 508 if (ret && ret != -ENOENT) { 509 printf("%s: Cannot get spi cs GPIO: %d\n", 510 __func__, ret); 511 return ret; 512 } 513 dm_gpio_set_value(&priv->spi_sdi_gpio, 1); 514 dm_gpio_set_value(&priv->spi_scl_gpio, 1); 515 dm_gpio_set_value(&priv->spi_cs_gpio, 1); 516 dm_gpio_set_value(&priv->reset_gpio, 0); 517 } 518 519 panel = calloc(1, sizeof(*panel)); 520 if (!panel) 521 return -ENOMEM; 522 523 dev->driver_data = (ulong)panel; 524 panel->dev = dev; 525 panel->bus_format = plat->bus_format; 526 panel->bpc = plat->bpc; 527 panel->funcs = &rockchip_panel_funcs; 528 529 return 0; 530 } 531 532 static const struct udevice_id rockchip_panel_ids[] = { 533 { .compatible = "simple-panel", }, 534 { .compatible = "simple-panel-dsi", }, 535 {} 536 }; 537 538 U_BOOT_DRIVER(rockchip_panel) = { 539 .name = "rockchip_panel", 540 .id = UCLASS_PANEL, 541 .of_match = rockchip_panel_ids, 542 .ofdata_to_platdata = rockchip_panel_ofdata_to_platdata, 543 .probe = rockchip_panel_probe, 544 .priv_auto_alloc_size = sizeof(struct rockchip_panel_priv), 545 .platdata_auto_alloc_size = sizeof(struct rockchip_panel_plat), 546 }; 547