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 const struct rockchip_panel_funcs rockchip_panel_funcs = { 390 .prepare = panel_simple_prepare, 391 .unprepare = panel_simple_unprepare, 392 .enable = panel_simple_enable, 393 .disable = panel_simple_disable, 394 }; 395 396 static int rockchip_panel_ofdata_to_platdata(struct udevice *dev) 397 { 398 struct rockchip_panel_plat *plat = dev_get_platdata(dev); 399 const void *data; 400 int len = 0; 401 int ret; 402 403 plat->power_invert = dev_read_bool(dev, "power-invert"); 404 405 plat->delay.prepare = dev_read_u32_default(dev, "prepare-delay-ms", 0); 406 plat->delay.unprepare = dev_read_u32_default(dev, "unprepare-delay-ms", 0); 407 plat->delay.enable = dev_read_u32_default(dev, "enable-delay-ms", 0); 408 plat->delay.disable = dev_read_u32_default(dev, "disable-delay-ms", 0); 409 plat->delay.init = dev_read_u32_default(dev, "init-delay-ms", 0); 410 plat->delay.reset = dev_read_u32_default(dev, "reset-delay-ms", 0); 411 412 plat->bus_format = dev_read_u32_default(dev, "bus-format", 413 MEDIA_BUS_FMT_RBG888_1X24); 414 plat->bpc = dev_read_u32_default(dev, "bpc", 8); 415 416 data = dev_read_prop(dev, "panel-init-sequence", &len); 417 if (data) { 418 plat->on_cmds = calloc(1, sizeof(*plat->on_cmds)); 419 if (!plat->on_cmds) 420 return -ENOMEM; 421 422 ret = rockchip_panel_parse_cmds(data, len, plat->on_cmds); 423 if (ret) { 424 printf("failed to parse panel init sequence\n"); 425 goto free_on_cmds; 426 } 427 } 428 429 data = dev_read_prop(dev, "panel-exit-sequence", &len); 430 if (data) { 431 plat->off_cmds = calloc(1, sizeof(*plat->off_cmds)); 432 if (!plat->off_cmds) { 433 ret = -ENOMEM; 434 goto free_on_cmds; 435 } 436 437 ret = rockchip_panel_parse_cmds(data, len, plat->off_cmds); 438 if (ret) { 439 printf("failed to parse panel exit sequence\n"); 440 goto free_cmds; 441 } 442 } 443 444 return 0; 445 446 free_cmds: 447 free(plat->off_cmds); 448 free_on_cmds: 449 free(plat->on_cmds); 450 return ret; 451 } 452 453 static int rockchip_panel_probe(struct udevice *dev) 454 { 455 struct rockchip_panel_priv *priv = dev_get_priv(dev); 456 struct rockchip_panel_plat *plat = dev_get_platdata(dev); 457 struct rockchip_panel *panel; 458 int ret; 459 const char *cmd_type; 460 461 ret = gpio_request_by_name(dev, "enable-gpios", 0, 462 &priv->enable_gpio, GPIOD_IS_OUT); 463 if (ret && ret != -ENOENT) { 464 printf("%s: Cannot get enable GPIO: %d\n", __func__, ret); 465 return ret; 466 } 467 468 ret = gpio_request_by_name(dev, "reset-gpios", 0, 469 &priv->reset_gpio, GPIOD_IS_OUT); 470 if (ret && ret != -ENOENT) { 471 printf("%s: Cannot get reset GPIO: %d\n", __func__, ret); 472 return ret; 473 } 474 475 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, 476 "backlight", &priv->backlight); 477 if (ret && ret != -ENOENT) { 478 printf("%s: Cannot get backlight: %d\n", __func__, ret); 479 return ret; 480 } 481 482 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, 483 "power-supply", &priv->power_supply); 484 if (ret && ret != -ENOENT) { 485 printf("%s: Cannot get power supply: %d\n", __func__, ret); 486 return ret; 487 } 488 489 ret = dev_read_string_index(dev, "rockchip,cmd-type", 0, &cmd_type); 490 if (ret) 491 priv->cmd_type = CMD_TYPE_DEFAULT; 492 else 493 priv->cmd_type = get_panel_cmd_type(cmd_type); 494 495 if (priv->cmd_type == CMD_TYPE_SPI) { 496 ret = gpio_request_by_name(dev, "spi-sdi-gpios", 0, 497 &priv->spi_sdi_gpio, GPIOD_IS_OUT); 498 if (ret && ret != -ENOENT) { 499 printf("%s: Cannot get spi sdi GPIO: %d\n", 500 __func__, ret); 501 return ret; 502 } 503 ret = gpio_request_by_name(dev, "spi-scl-gpios", 0, 504 &priv->spi_scl_gpio, GPIOD_IS_OUT); 505 if (ret && ret != -ENOENT) { 506 printf("%s: Cannot get spi scl GPIO: %d\n", 507 __func__, ret); 508 return ret; 509 } 510 ret = gpio_request_by_name(dev, "spi-cs-gpios", 0, 511 &priv->spi_cs_gpio, GPIOD_IS_OUT); 512 if (ret && ret != -ENOENT) { 513 printf("%s: Cannot get spi cs GPIO: %d\n", 514 __func__, ret); 515 return ret; 516 } 517 dm_gpio_set_value(&priv->spi_sdi_gpio, 1); 518 dm_gpio_set_value(&priv->spi_scl_gpio, 1); 519 dm_gpio_set_value(&priv->spi_cs_gpio, 1); 520 dm_gpio_set_value(&priv->reset_gpio, 0); 521 } 522 523 panel = calloc(1, sizeof(*panel)); 524 if (!panel) 525 return -ENOMEM; 526 527 dev->driver_data = (ulong)panel; 528 panel->dev = dev; 529 panel->bus_format = plat->bus_format; 530 panel->bpc = plat->bpc; 531 panel->funcs = &rockchip_panel_funcs; 532 533 return 0; 534 } 535 536 static const struct udevice_id rockchip_panel_ids[] = { 537 { .compatible = "simple-panel", }, 538 { .compatible = "simple-panel-dsi", }, 539 {} 540 }; 541 542 U_BOOT_DRIVER(rockchip_panel) = { 543 .name = "rockchip_panel", 544 .id = UCLASS_PANEL, 545 .of_match = rockchip_panel_ids, 546 .ofdata_to_platdata = rockchip_panel_ofdata_to_platdata, 547 .probe = rockchip_panel_probe, 548 .priv_auto_alloc_size = sizeof(struct rockchip_panel_priv), 549 .platdata_auto_alloc_size = sizeof(struct rockchip_panel_plat), 550 }; 551