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