1186f8572SMark Yao /* 2186f8572SMark Yao * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 3186f8572SMark Yao * 4186f8572SMark Yao * SPDX-License-Identifier: GPL-2.0+ 5186f8572SMark Yao */ 6186f8572SMark Yao 71953e619SWyon Bi #include <drm/drm_mipi_dsi.h> 81953e619SWyon Bi 9186f8572SMark Yao #include <config.h> 10186f8572SMark Yao #include <common.h> 11186f8572SMark Yao #include <errno.h> 12c493d00eSWyon Bi #include <malloc.h> 13c493d00eSWyon Bi #include <video.h> 14c493d00eSWyon Bi #include <backlight.h> 15c493d00eSWyon Bi #include <asm/gpio.h> 164b8c2ef1SMark Yao #include <dm/device.h> 17c493d00eSWyon Bi #include <dm/read.h> 18c493d00eSWyon Bi #include <dm/uclass.h> 19c493d00eSWyon Bi #include <dm/uclass-id.h> 20c493d00eSWyon Bi #include <linux/media-bus-format.h> 21c493d00eSWyon Bi #include <power/regulator.h> 22186f8572SMark Yao 23186f8572SMark Yao #include "rockchip_display.h" 24186f8572SMark Yao #include "rockchip_crtc.h" 25186f8572SMark Yao #include "rockchip_connector.h" 26186f8572SMark Yao #include "rockchip_panel.h" 27186f8572SMark Yao 28c493d00eSWyon Bi struct rockchip_cmd_header { 29c493d00eSWyon Bi u8 data_type; 30c493d00eSWyon Bi u8 delay_ms; 31c493d00eSWyon Bi u8 payload_length; 32c493d00eSWyon Bi } __packed; 33c493d00eSWyon Bi 34c493d00eSWyon Bi struct rockchip_cmd_desc { 35c493d00eSWyon Bi struct rockchip_cmd_header header; 36c493d00eSWyon Bi const u8 *payload; 37c493d00eSWyon Bi }; 38c493d00eSWyon Bi 39c493d00eSWyon Bi struct rockchip_panel_cmds { 40c493d00eSWyon Bi struct rockchip_cmd_desc *cmds; 41c493d00eSWyon Bi int cmd_cnt; 42c493d00eSWyon Bi }; 43c493d00eSWyon Bi 44c493d00eSWyon Bi struct rockchip_panel_plat { 45c493d00eSWyon Bi bool power_invert; 46c493d00eSWyon Bi u32 bus_format; 4700cdbd6cSWyon Bi unsigned int bpc; 48c493d00eSWyon Bi 49c493d00eSWyon Bi struct { 50c493d00eSWyon Bi unsigned int prepare; 51c493d00eSWyon Bi unsigned int unprepare; 52c493d00eSWyon Bi unsigned int enable; 53c493d00eSWyon Bi unsigned int disable; 54c493d00eSWyon Bi unsigned int reset; 55c493d00eSWyon Bi unsigned int init; 56c493d00eSWyon Bi } delay; 57c493d00eSWyon Bi 58c493d00eSWyon Bi struct rockchip_panel_cmds *on_cmds; 59c493d00eSWyon Bi struct rockchip_panel_cmds *off_cmds; 60c493d00eSWyon Bi }; 61c493d00eSWyon Bi 62c493d00eSWyon Bi struct rockchip_panel_priv { 63c493d00eSWyon Bi bool prepared; 64c493d00eSWyon Bi bool enabled; 65c493d00eSWyon Bi struct udevice *power_supply; 66c493d00eSWyon Bi struct udevice *backlight; 67c493d00eSWyon Bi struct gpio_desc enable_gpio; 68c493d00eSWyon Bi struct gpio_desc reset_gpio; 6945fa51f3SSandy Huang 7045fa51f3SSandy Huang int cmd_type; 7145fa51f3SSandy Huang struct gpio_desc spi_sdi_gpio; 7245fa51f3SSandy Huang struct gpio_desc spi_scl_gpio; 7345fa51f3SSandy Huang struct gpio_desc spi_cs_gpio; 74c493d00eSWyon Bi }; 75c493d00eSWyon Bi 7645fa51f3SSandy Huang static inline int get_panel_cmd_type(const char *s) 7745fa51f3SSandy Huang { 7845fa51f3SSandy Huang if (!s) 7945fa51f3SSandy Huang return -EINVAL; 8045fa51f3SSandy Huang 8145fa51f3SSandy Huang if (strncmp(s, "spi", 3) == 0) 8245fa51f3SSandy Huang return CMD_TYPE_SPI; 8345fa51f3SSandy Huang else if (strncmp(s, "mcu", 3) == 0) 8445fa51f3SSandy Huang return CMD_TYPE_MCU; 8545fa51f3SSandy Huang 8645fa51f3SSandy Huang return CMD_TYPE_DEFAULT; 8745fa51f3SSandy Huang } 8845fa51f3SSandy Huang 89c493d00eSWyon Bi static int rockchip_panel_parse_cmds(const u8 *data, int length, 90c493d00eSWyon Bi struct rockchip_panel_cmds *pcmds) 91c493d00eSWyon Bi { 92c493d00eSWyon Bi int len; 93c493d00eSWyon Bi const u8 *buf; 94c493d00eSWyon Bi const struct rockchip_cmd_header *header; 95c493d00eSWyon Bi int i, cnt = 0; 96c493d00eSWyon Bi 97c493d00eSWyon Bi /* scan commands */ 98c493d00eSWyon Bi cnt = 0; 99c493d00eSWyon Bi buf = data; 100c493d00eSWyon Bi len = length; 101c493d00eSWyon Bi while (len > sizeof(*header)) { 102c493d00eSWyon Bi header = (const struct rockchip_cmd_header *)buf; 103c493d00eSWyon Bi buf += sizeof(*header) + header->payload_length; 104c493d00eSWyon Bi len -= sizeof(*header) + header->payload_length; 105c493d00eSWyon Bi cnt++; 106c493d00eSWyon Bi } 107c493d00eSWyon Bi 108c493d00eSWyon Bi pcmds->cmds = calloc(cnt, sizeof(struct rockchip_cmd_desc)); 109c493d00eSWyon Bi if (!pcmds->cmds) 110c493d00eSWyon Bi return -ENOMEM; 111c493d00eSWyon Bi 112c493d00eSWyon Bi pcmds->cmd_cnt = cnt; 113c493d00eSWyon Bi 114c493d00eSWyon Bi buf = data; 115c493d00eSWyon Bi len = length; 116c493d00eSWyon Bi for (i = 0; i < cnt; i++) { 117c493d00eSWyon Bi struct rockchip_cmd_desc *desc = &pcmds->cmds[i]; 118c493d00eSWyon Bi 119c493d00eSWyon Bi header = (const struct rockchip_cmd_header *)buf; 120c493d00eSWyon Bi length -= sizeof(*header); 121c493d00eSWyon Bi buf += sizeof(*header); 122c493d00eSWyon Bi desc->header.data_type = header->data_type; 123c493d00eSWyon Bi desc->header.delay_ms = header->delay_ms; 124c493d00eSWyon Bi desc->header.payload_length = header->payload_length; 125c493d00eSWyon Bi desc->payload = buf; 126c493d00eSWyon Bi buf += header->payload_length; 127c493d00eSWyon Bi length -= header->payload_length; 128c493d00eSWyon Bi } 129c493d00eSWyon Bi 130c493d00eSWyon Bi return 0; 131c493d00eSWyon Bi } 132c493d00eSWyon Bi 13345fa51f3SSandy Huang static void rockchip_panel_write_spi_cmds(struct rockchip_panel_priv *priv, 13445fa51f3SSandy Huang u8 type, int value) 13545fa51f3SSandy Huang { 13645fa51f3SSandy Huang int i; 13745fa51f3SSandy Huang 13845fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_cs_gpio, 0); 13945fa51f3SSandy Huang 14045fa51f3SSandy Huang if (type == 0) 14145fa51f3SSandy Huang value &= (~(1 << 8)); 14245fa51f3SSandy Huang else 14345fa51f3SSandy Huang value |= (1 << 8); 14445fa51f3SSandy Huang 14545fa51f3SSandy Huang for (i = 0; i < 9; i++) { 14645fa51f3SSandy Huang if (value & 0x100) 14745fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_sdi_gpio, 1); 14845fa51f3SSandy Huang else 14945fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_sdi_gpio, 0); 15045fa51f3SSandy Huang 15145fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_scl_gpio, 0); 15245fa51f3SSandy Huang udelay(10); 15345fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_scl_gpio, 1); 15445fa51f3SSandy Huang value <<= 1; 15545fa51f3SSandy Huang udelay(10); 15645fa51f3SSandy Huang } 15745fa51f3SSandy Huang 15845fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_cs_gpio, 1); 15945fa51f3SSandy Huang } 16045fa51f3SSandy Huang 16167b9012cSSandy Huang static int rockchip_panel_send_mcu_cmds(struct display_state *state, 16267b9012cSSandy Huang struct rockchip_panel_cmds *cmds) 16367b9012cSSandy Huang { 16467b9012cSSandy Huang int i; 16567b9012cSSandy Huang 16667b9012cSSandy Huang if (!cmds) 16767b9012cSSandy Huang return -EINVAL; 16867b9012cSSandy Huang 16967b9012cSSandy Huang display_send_mcu_cmd(state, MCU_SETBYPASS, 1); 17067b9012cSSandy Huang for (i = 0; i < cmds->cmd_cnt; i++) { 17167b9012cSSandy Huang struct rockchip_cmd_desc *desc = &cmds->cmds[i]; 17267b9012cSSandy Huang int value = 0; 17367b9012cSSandy Huang 17467b9012cSSandy Huang value = desc->payload[0]; 17567b9012cSSandy Huang display_send_mcu_cmd(state, desc->header.data_type, value); 17667b9012cSSandy Huang 17767b9012cSSandy Huang if (desc->header.delay_ms) 17867b9012cSSandy Huang mdelay(desc->header.delay_ms); 17967b9012cSSandy Huang } 18067b9012cSSandy Huang display_send_mcu_cmd(state, MCU_SETBYPASS, 0); 18167b9012cSSandy Huang 18267b9012cSSandy Huang return 0; 18367b9012cSSandy Huang } 18467b9012cSSandy Huang 18545fa51f3SSandy Huang static int rockchip_panel_send_spi_cmds(struct display_state *state, 18645fa51f3SSandy Huang struct rockchip_panel_cmds *cmds) 18745fa51f3SSandy Huang { 1881a8d717cSWyon Bi struct rockchip_panel *panel = state_get_panel(state); 1891a8d717cSWyon Bi struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 19045fa51f3SSandy Huang int i; 19145fa51f3SSandy Huang 19245fa51f3SSandy Huang if (!cmds) 19345fa51f3SSandy Huang return -EINVAL; 19445fa51f3SSandy Huang 19545fa51f3SSandy Huang for (i = 0; i < cmds->cmd_cnt; i++) { 19645fa51f3SSandy Huang struct rockchip_cmd_desc *desc = &cmds->cmds[i]; 19745fa51f3SSandy Huang int value = 0; 19845fa51f3SSandy Huang 19945fa51f3SSandy Huang if (desc->header.payload_length == 2) 20045fa51f3SSandy Huang value = (desc->payload[0] << 8) | desc->payload[1]; 20145fa51f3SSandy Huang else 20245fa51f3SSandy Huang value = desc->payload[0]; 20345fa51f3SSandy Huang rockchip_panel_write_spi_cmds(priv, 20445fa51f3SSandy Huang desc->header.data_type, value); 20545fa51f3SSandy Huang 20645fa51f3SSandy Huang if (desc->header.delay_ms) 20745fa51f3SSandy Huang mdelay(desc->header.delay_ms); 20845fa51f3SSandy Huang } 20945fa51f3SSandy Huang 21045fa51f3SSandy Huang return 0; 21145fa51f3SSandy Huang } 21245fa51f3SSandy Huang 2131953e619SWyon Bi static int rockchip_panel_send_dsi_cmds(struct mipi_dsi_device *dsi, 214c493d00eSWyon Bi struct rockchip_panel_cmds *cmds) 215c493d00eSWyon Bi { 216c493d00eSWyon Bi int i, ret; 217c493d00eSWyon Bi 218c493d00eSWyon Bi if (!cmds) 219c493d00eSWyon Bi return -EINVAL; 220c493d00eSWyon Bi 221c493d00eSWyon Bi for (i = 0; i < cmds->cmd_cnt; i++) { 222c493d00eSWyon Bi struct rockchip_cmd_desc *desc = &cmds->cmds[i]; 2231953e619SWyon Bi const struct rockchip_cmd_header *header = &desc->header; 224c493d00eSWyon Bi 2251953e619SWyon Bi switch (header->data_type) { 226c493d00eSWyon Bi case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: 227c493d00eSWyon Bi case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: 228c493d00eSWyon Bi case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: 229c493d00eSWyon Bi case MIPI_DSI_GENERIC_LONG_WRITE: 2301953e619SWyon Bi ret = mipi_dsi_generic_write(dsi, desc->payload, 2311953e619SWyon Bi header->payload_length); 232c493d00eSWyon Bi break; 233c493d00eSWyon Bi case MIPI_DSI_DCS_SHORT_WRITE: 234c493d00eSWyon Bi case MIPI_DSI_DCS_SHORT_WRITE_PARAM: 235c493d00eSWyon Bi case MIPI_DSI_DCS_LONG_WRITE: 2361953e619SWyon Bi ret = mipi_dsi_dcs_write_buffer(dsi, desc->payload, 2371953e619SWyon Bi header->payload_length); 238c493d00eSWyon Bi break; 239c493d00eSWyon Bi default: 240c493d00eSWyon Bi printf("unsupport command data type: %d\n", 2411953e619SWyon Bi header->data_type); 242c493d00eSWyon Bi return -EINVAL; 243c493d00eSWyon Bi } 244c493d00eSWyon Bi 2455b620adaSWyon Bi if (ret < 0) { 246c493d00eSWyon Bi printf("failed to write cmd%d: %d\n", i, ret); 247c493d00eSWyon Bi return ret; 248c493d00eSWyon Bi } 249c493d00eSWyon Bi 2501953e619SWyon Bi if (header->delay_ms) 2511953e619SWyon Bi mdelay(header->delay_ms); 252c493d00eSWyon Bi } 253c493d00eSWyon Bi 254c493d00eSWyon Bi return 0; 255c493d00eSWyon Bi } 256c493d00eSWyon Bi 2577cacd0a8SWyon Bi static void panel_simple_prepare(struct rockchip_panel *panel) 258c493d00eSWyon Bi { 2591a8d717cSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 2601a8d717cSWyon Bi struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 2611953e619SWyon Bi struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev); 262c493d00eSWyon Bi int ret; 263c493d00eSWyon Bi 264c493d00eSWyon Bi if (priv->prepared) 2657cacd0a8SWyon Bi return; 266c493d00eSWyon Bi 2677cacd0a8SWyon Bi if (priv->power_supply) 2687cacd0a8SWyon Bi regulator_set_enable(priv->power_supply, !plat->power_invert); 269c493d00eSWyon Bi 2707cacd0a8SWyon Bi if (dm_gpio_is_valid(&priv->enable_gpio)) 271c493d00eSWyon Bi dm_gpio_set_value(&priv->enable_gpio, 1); 2727cacd0a8SWyon Bi 2737cacd0a8SWyon Bi if (plat->delay.prepare) 274c493d00eSWyon Bi mdelay(plat->delay.prepare); 275c493d00eSWyon Bi 2767cacd0a8SWyon Bi if (dm_gpio_is_valid(&priv->reset_gpio)) 277c493d00eSWyon Bi dm_gpio_set_value(&priv->reset_gpio, 1); 2787cacd0a8SWyon Bi 2797cacd0a8SWyon Bi if (plat->delay.reset) 280c493d00eSWyon Bi mdelay(plat->delay.reset); 2817cacd0a8SWyon Bi 2827cacd0a8SWyon Bi if (dm_gpio_is_valid(&priv->reset_gpio)) 283c493d00eSWyon Bi dm_gpio_set_value(&priv->reset_gpio, 0); 284c493d00eSWyon Bi 2857cacd0a8SWyon Bi if (plat->delay.init) 286c493d00eSWyon Bi mdelay(plat->delay.init); 287c493d00eSWyon Bi 288c493d00eSWyon Bi if (plat->on_cmds) { 28945fa51f3SSandy Huang if (priv->cmd_type == CMD_TYPE_SPI) 2907cacd0a8SWyon Bi ret = rockchip_panel_send_spi_cmds(panel->state, 29145fa51f3SSandy Huang plat->on_cmds); 29267b9012cSSandy Huang else if (priv->cmd_type == CMD_TYPE_MCU) 2937cacd0a8SWyon Bi ret = rockchip_panel_send_mcu_cmds(panel->state, 2947cacd0a8SWyon Bi plat->on_cmds); 29545fa51f3SSandy Huang else 2961953e619SWyon Bi ret = rockchip_panel_send_dsi_cmds(dsi, plat->on_cmds); 297c493d00eSWyon Bi if (ret) 298c493d00eSWyon Bi printf("failed to send on cmds: %d\n", ret); 299c493d00eSWyon Bi } 300c493d00eSWyon Bi 301c493d00eSWyon Bi priv->prepared = true; 302c493d00eSWyon Bi } 303c493d00eSWyon Bi 3047cacd0a8SWyon Bi static void panel_simple_unprepare(struct rockchip_panel *panel) 305c493d00eSWyon Bi { 3061a8d717cSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 3071a8d717cSWyon Bi struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 3081953e619SWyon Bi struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev); 309c493d00eSWyon Bi int ret; 310c493d00eSWyon Bi 311c493d00eSWyon Bi if (!priv->prepared) 312c493d00eSWyon Bi return; 313c493d00eSWyon Bi 314c493d00eSWyon Bi if (plat->off_cmds) { 31545fa51f3SSandy Huang if (priv->cmd_type == CMD_TYPE_SPI) 3167cacd0a8SWyon Bi ret = rockchip_panel_send_spi_cmds(panel->state, 31745fa51f3SSandy Huang plat->off_cmds); 31867b9012cSSandy Huang else if (priv->cmd_type == CMD_TYPE_MCU) 3197cacd0a8SWyon Bi ret = rockchip_panel_send_mcu_cmds(panel->state, 32067b9012cSSandy Huang plat->off_cmds); 32145fa51f3SSandy Huang else 3221953e619SWyon Bi ret = rockchip_panel_send_dsi_cmds(dsi, plat->off_cmds); 323c493d00eSWyon Bi if (ret) 324c493d00eSWyon Bi printf("failed to send off cmds: %d\n", ret); 325c493d00eSWyon Bi } 326c493d00eSWyon Bi 3277cacd0a8SWyon Bi if (dm_gpio_is_valid(&priv->reset_gpio)) 328c493d00eSWyon Bi dm_gpio_set_value(&priv->reset_gpio, 1); 3297cacd0a8SWyon Bi 3307cacd0a8SWyon Bi if (dm_gpio_is_valid(&priv->enable_gpio)) 331c493d00eSWyon Bi dm_gpio_set_value(&priv->enable_gpio, 0); 332c493d00eSWyon Bi 3337cacd0a8SWyon Bi if (priv->power_supply) 3347cacd0a8SWyon Bi regulator_set_enable(priv->power_supply, plat->power_invert); 335c493d00eSWyon Bi 3367cacd0a8SWyon Bi if (plat->delay.unprepare) 337c493d00eSWyon Bi mdelay(plat->delay.unprepare); 338c493d00eSWyon Bi 339c493d00eSWyon Bi priv->prepared = false; 340c493d00eSWyon Bi } 341c493d00eSWyon Bi 3427cacd0a8SWyon Bi static void panel_simple_enable(struct rockchip_panel *panel) 343c493d00eSWyon Bi { 3441a8d717cSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 3451a8d717cSWyon Bi struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 346c493d00eSWyon Bi 347c493d00eSWyon Bi if (priv->enabled) 3487cacd0a8SWyon Bi return; 349c493d00eSWyon Bi 3507cacd0a8SWyon Bi if (plat->delay.enable) 351c493d00eSWyon Bi mdelay(plat->delay.enable); 352c493d00eSWyon Bi 353c493d00eSWyon Bi if (priv->backlight) 354c493d00eSWyon Bi backlight_enable(priv->backlight); 355c493d00eSWyon Bi 356c493d00eSWyon Bi priv->enabled = true; 357c493d00eSWyon Bi } 358c493d00eSWyon Bi 3597cacd0a8SWyon Bi static void panel_simple_disable(struct rockchip_panel *panel) 360c493d00eSWyon Bi { 3611a8d717cSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 3621a8d717cSWyon Bi struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 363c493d00eSWyon Bi 364c493d00eSWyon Bi if (!priv->enabled) 365c493d00eSWyon Bi return; 366c493d00eSWyon Bi 367c493d00eSWyon Bi if (priv->backlight) 368c493d00eSWyon Bi backlight_disable(priv->backlight); 369c493d00eSWyon Bi 3707cacd0a8SWyon Bi if (plat->delay.disable) 371c493d00eSWyon Bi mdelay(plat->delay.disable); 372c493d00eSWyon Bi 373c493d00eSWyon Bi priv->enabled = false; 374c493d00eSWyon Bi } 375c493d00eSWyon Bi 3767cacd0a8SWyon Bi static void panel_simple_init(struct rockchip_panel *panel) 377c493d00eSWyon Bi { 3787cacd0a8SWyon Bi struct display_state *state = panel->state; 379c493d00eSWyon Bi struct connector_state *conn_state = &state->conn_state; 380c493d00eSWyon Bi 3811a8d717cSWyon Bi conn_state->bus_format = panel->bus_format; 382c493d00eSWyon Bi } 383c493d00eSWyon Bi 384c493d00eSWyon Bi static const struct rockchip_panel_funcs rockchip_panel_funcs = { 3857cacd0a8SWyon Bi .init = panel_simple_init, 3867cacd0a8SWyon Bi .prepare = panel_simple_prepare, 3877cacd0a8SWyon Bi .unprepare = panel_simple_unprepare, 3887cacd0a8SWyon Bi .enable = panel_simple_enable, 3897cacd0a8SWyon Bi .disable = panel_simple_disable, 390c493d00eSWyon Bi }; 391c493d00eSWyon Bi 392c493d00eSWyon Bi static int rockchip_panel_ofdata_to_platdata(struct udevice *dev) 393c493d00eSWyon Bi { 394c493d00eSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(dev); 395c493d00eSWyon Bi const void *data; 396c493d00eSWyon Bi int len = 0; 397c493d00eSWyon Bi int ret; 398c493d00eSWyon Bi 399c493d00eSWyon Bi plat->power_invert = dev_read_bool(dev, "power-invert"); 400c493d00eSWyon Bi 401c493d00eSWyon Bi plat->delay.prepare = dev_read_u32_default(dev, "prepare-delay-ms", 0); 402c493d00eSWyon Bi plat->delay.unprepare = dev_read_u32_default(dev, "unprepare-delay-ms", 0); 403c493d00eSWyon Bi plat->delay.enable = dev_read_u32_default(dev, "enable-delay-ms", 0); 404c493d00eSWyon Bi plat->delay.disable = dev_read_u32_default(dev, "disable-delay-ms", 0); 405c493d00eSWyon Bi plat->delay.init = dev_read_u32_default(dev, "init-delay-ms", 0); 406c493d00eSWyon Bi plat->delay.reset = dev_read_u32_default(dev, "reset-delay-ms", 0); 407c493d00eSWyon Bi 408c493d00eSWyon Bi plat->bus_format = dev_read_u32_default(dev, "bus-format", 409c493d00eSWyon Bi MEDIA_BUS_FMT_RBG888_1X24); 41000cdbd6cSWyon Bi plat->bpc = dev_read_u32_default(dev, "bpc", 8); 411c493d00eSWyon Bi 412c493d00eSWyon Bi data = dev_read_prop(dev, "panel-init-sequence", &len); 413c493d00eSWyon Bi if (data) { 414c493d00eSWyon Bi plat->on_cmds = calloc(1, sizeof(*plat->on_cmds)); 415c493d00eSWyon Bi if (!plat->on_cmds) 416c493d00eSWyon Bi return -ENOMEM; 417c493d00eSWyon Bi 418c493d00eSWyon Bi ret = rockchip_panel_parse_cmds(data, len, plat->on_cmds); 419c493d00eSWyon Bi if (ret) { 420c493d00eSWyon Bi printf("failed to parse panel init sequence\n"); 421c493d00eSWyon Bi goto free_on_cmds; 422c493d00eSWyon Bi } 423c493d00eSWyon Bi } 424c493d00eSWyon Bi 425c493d00eSWyon Bi data = dev_read_prop(dev, "panel-exit-sequence", &len); 426c493d00eSWyon Bi if (data) { 427c493d00eSWyon Bi plat->off_cmds = calloc(1, sizeof(*plat->off_cmds)); 428c493d00eSWyon Bi if (!plat->off_cmds) { 429c493d00eSWyon Bi ret = -ENOMEM; 430c493d00eSWyon Bi goto free_on_cmds; 431c493d00eSWyon Bi } 432c493d00eSWyon Bi 433c493d00eSWyon Bi ret = rockchip_panel_parse_cmds(data, len, plat->off_cmds); 434c493d00eSWyon Bi if (ret) { 435c493d00eSWyon Bi printf("failed to parse panel exit sequence\n"); 436c493d00eSWyon Bi goto free_cmds; 437c493d00eSWyon Bi } 438c493d00eSWyon Bi } 439c493d00eSWyon Bi 440c493d00eSWyon Bi return 0; 441c493d00eSWyon Bi 442c493d00eSWyon Bi free_cmds: 443c493d00eSWyon Bi free(plat->off_cmds); 444c493d00eSWyon Bi free_on_cmds: 445c493d00eSWyon Bi free(plat->on_cmds); 446c493d00eSWyon Bi return ret; 447c493d00eSWyon Bi } 448c493d00eSWyon Bi 449c493d00eSWyon Bi static int rockchip_panel_probe(struct udevice *dev) 450c493d00eSWyon Bi { 451c493d00eSWyon Bi struct rockchip_panel_priv *priv = dev_get_priv(dev); 4521a8d717cSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(dev); 453*2942bf18SWyon Bi struct rockchip_panel *panel; 454c493d00eSWyon Bi int ret; 45545fa51f3SSandy Huang const char *cmd_type; 456c493d00eSWyon Bi 457c493d00eSWyon Bi ret = gpio_request_by_name(dev, "enable-gpios", 0, 458c493d00eSWyon Bi &priv->enable_gpio, GPIOD_IS_OUT); 459c493d00eSWyon Bi if (ret && ret != -ENOENT) { 460c493d00eSWyon Bi printf("%s: Cannot get enable GPIO: %d\n", __func__, ret); 461c493d00eSWyon Bi return ret; 462c493d00eSWyon Bi } 463c493d00eSWyon Bi 464c493d00eSWyon Bi ret = gpio_request_by_name(dev, "reset-gpios", 0, 465c493d00eSWyon Bi &priv->reset_gpio, GPIOD_IS_OUT); 466c493d00eSWyon Bi if (ret && ret != -ENOENT) { 467c493d00eSWyon Bi printf("%s: Cannot get reset GPIO: %d\n", __func__, ret); 468c493d00eSWyon Bi return ret; 469c493d00eSWyon Bi } 470c493d00eSWyon Bi 471c493d00eSWyon Bi ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, 472c493d00eSWyon Bi "backlight", &priv->backlight); 473c493d00eSWyon Bi if (ret && ret != -ENOENT) { 474c493d00eSWyon Bi printf("%s: Cannot get backlight: %d\n", __func__, ret); 475c493d00eSWyon Bi return ret; 476c493d00eSWyon Bi } 477c493d00eSWyon Bi 478c493d00eSWyon Bi ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, 479c493d00eSWyon Bi "power-supply", &priv->power_supply); 480c493d00eSWyon Bi if (ret && ret != -ENOENT) { 481c493d00eSWyon Bi printf("%s: Cannot get power supply: %d\n", __func__, ret); 482c493d00eSWyon Bi return ret; 483c493d00eSWyon Bi } 484c493d00eSWyon Bi 48545fa51f3SSandy Huang ret = dev_read_string_index(dev, "rockchip,cmd-type", 0, &cmd_type); 48645fa51f3SSandy Huang if (ret) 48745fa51f3SSandy Huang priv->cmd_type = CMD_TYPE_DEFAULT; 48845fa51f3SSandy Huang else 48945fa51f3SSandy Huang priv->cmd_type = get_panel_cmd_type(cmd_type); 49045fa51f3SSandy Huang 49145fa51f3SSandy Huang if (priv->cmd_type == CMD_TYPE_SPI) { 49245fa51f3SSandy Huang ret = gpio_request_by_name(dev, "spi-sdi-gpios", 0, 49345fa51f3SSandy Huang &priv->spi_sdi_gpio, GPIOD_IS_OUT); 49445fa51f3SSandy Huang if (ret && ret != -ENOENT) { 49545fa51f3SSandy Huang printf("%s: Cannot get spi sdi GPIO: %d\n", 49645fa51f3SSandy Huang __func__, ret); 49745fa51f3SSandy Huang return ret; 49845fa51f3SSandy Huang } 49945fa51f3SSandy Huang ret = gpio_request_by_name(dev, "spi-scl-gpios", 0, 50045fa51f3SSandy Huang &priv->spi_scl_gpio, GPIOD_IS_OUT); 50145fa51f3SSandy Huang if (ret && ret != -ENOENT) { 50245fa51f3SSandy Huang printf("%s: Cannot get spi scl GPIO: %d\n", 50345fa51f3SSandy Huang __func__, ret); 50445fa51f3SSandy Huang return ret; 50545fa51f3SSandy Huang } 50645fa51f3SSandy Huang ret = gpio_request_by_name(dev, "spi-cs-gpios", 0, 50745fa51f3SSandy Huang &priv->spi_cs_gpio, GPIOD_IS_OUT); 50845fa51f3SSandy Huang if (ret && ret != -ENOENT) { 50945fa51f3SSandy Huang printf("%s: Cannot get spi cs GPIO: %d\n", 51045fa51f3SSandy Huang __func__, ret); 51145fa51f3SSandy Huang return ret; 51245fa51f3SSandy Huang } 51345fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_sdi_gpio, 1); 51445fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_scl_gpio, 1); 51545fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_cs_gpio, 1); 51645fa51f3SSandy Huang dm_gpio_set_value(&priv->reset_gpio, 0); 51745fa51f3SSandy Huang } 51845fa51f3SSandy Huang 519*2942bf18SWyon Bi panel = calloc(1, sizeof(*panel)); 520*2942bf18SWyon Bi if (!panel) 521*2942bf18SWyon Bi return -ENOMEM; 522*2942bf18SWyon Bi 523*2942bf18SWyon Bi dev->driver_data = (ulong)panel; 5241a8d717cSWyon Bi panel->dev = dev; 5251a8d717cSWyon Bi panel->bus_format = plat->bus_format; 52600cdbd6cSWyon Bi panel->bpc = plat->bpc; 527*2942bf18SWyon Bi panel->funcs = &rockchip_panel_funcs; 5281a8d717cSWyon Bi 529c493d00eSWyon Bi return 0; 530c493d00eSWyon Bi } 531c493d00eSWyon Bi 532186f8572SMark Yao static const struct udevice_id rockchip_panel_ids[] = { 533*2942bf18SWyon Bi { .compatible = "simple-panel", }, 534*2942bf18SWyon Bi { .compatible = "simple-panel-dsi", }, 535186f8572SMark Yao {} 536186f8572SMark Yao }; 537186f8572SMark Yao 538186f8572SMark Yao U_BOOT_DRIVER(rockchip_panel) = { 539186f8572SMark Yao .name = "rockchip_panel", 540186f8572SMark Yao .id = UCLASS_PANEL, 541186f8572SMark Yao .of_match = rockchip_panel_ids, 542c493d00eSWyon Bi .ofdata_to_platdata = rockchip_panel_ofdata_to_platdata, 543186f8572SMark Yao .probe = rockchip_panel_probe, 544c493d00eSWyon Bi .priv_auto_alloc_size = sizeof(struct rockchip_panel_priv), 545c493d00eSWyon Bi .platdata_auto_alloc_size = sizeof(struct rockchip_panel_plat), 546186f8572SMark Yao }; 547