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; 217*e22c03edSGuochun Huang struct drm_dsc_picture_parameter_set *pps = NULL; 218c493d00eSWyon Bi 219c493d00eSWyon Bi if (!cmds) 220c493d00eSWyon Bi return -EINVAL; 221c493d00eSWyon Bi 222c493d00eSWyon Bi for (i = 0; i < cmds->cmd_cnt; i++) { 223c493d00eSWyon Bi struct rockchip_cmd_desc *desc = &cmds->cmds[i]; 2241953e619SWyon Bi const struct rockchip_cmd_header *header = &desc->header; 225c493d00eSWyon Bi 2261953e619SWyon Bi switch (header->data_type) { 227*e22c03edSGuochun Huang case MIPI_DSI_COMPRESSION_MODE: 228*e22c03edSGuochun Huang ret = mipi_dsi_compression_mode(dsi, desc->payload[0]); 229*e22c03edSGuochun Huang break; 230c493d00eSWyon Bi case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: 231c493d00eSWyon Bi case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: 232c493d00eSWyon Bi case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: 233c493d00eSWyon Bi case MIPI_DSI_GENERIC_LONG_WRITE: 2341953e619SWyon Bi ret = mipi_dsi_generic_write(dsi, desc->payload, 2351953e619SWyon Bi header->payload_length); 236c493d00eSWyon Bi break; 237c493d00eSWyon Bi case MIPI_DSI_DCS_SHORT_WRITE: 238c493d00eSWyon Bi case MIPI_DSI_DCS_SHORT_WRITE_PARAM: 239c493d00eSWyon Bi case MIPI_DSI_DCS_LONG_WRITE: 2401953e619SWyon Bi ret = mipi_dsi_dcs_write_buffer(dsi, desc->payload, 2411953e619SWyon Bi header->payload_length); 242c493d00eSWyon Bi break; 243*e22c03edSGuochun Huang case MIPI_DSI_PICTURE_PARAMETER_SET: 244*e22c03edSGuochun Huang pps = kzalloc(sizeof(*pps), GFP_KERNEL); 245*e22c03edSGuochun Huang if (!pps) 246*e22c03edSGuochun Huang return -ENOMEM; 247*e22c03edSGuochun Huang 248*e22c03edSGuochun Huang memcpy(pps, desc->payload, header->payload_length); 249*e22c03edSGuochun Huang ret = mipi_dsi_picture_parameter_set(dsi, pps); 250*e22c03edSGuochun Huang kfree(pps); 251*e22c03edSGuochun Huang break; 252c493d00eSWyon Bi default: 253c493d00eSWyon Bi printf("unsupport command data type: %d\n", 2541953e619SWyon Bi header->data_type); 255c493d00eSWyon Bi return -EINVAL; 256c493d00eSWyon Bi } 257c493d00eSWyon Bi 2585b620adaSWyon Bi if (ret < 0) { 259c493d00eSWyon Bi printf("failed to write cmd%d: %d\n", i, ret); 260c493d00eSWyon Bi return ret; 261c493d00eSWyon Bi } 262c493d00eSWyon Bi 2631953e619SWyon Bi if (header->delay_ms) 2641953e619SWyon Bi mdelay(header->delay_ms); 265c493d00eSWyon Bi } 266c493d00eSWyon Bi 267c493d00eSWyon Bi return 0; 268c493d00eSWyon Bi } 269c493d00eSWyon Bi 2707cacd0a8SWyon Bi static void panel_simple_prepare(struct rockchip_panel *panel) 271c493d00eSWyon Bi { 2721a8d717cSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 2731a8d717cSWyon Bi struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 2741953e619SWyon Bi struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev); 275c493d00eSWyon Bi int ret; 276c493d00eSWyon Bi 277c493d00eSWyon Bi if (priv->prepared) 2787cacd0a8SWyon Bi return; 279c493d00eSWyon Bi 2807cacd0a8SWyon Bi if (priv->power_supply) 2817cacd0a8SWyon Bi regulator_set_enable(priv->power_supply, !plat->power_invert); 282c493d00eSWyon Bi 2837cacd0a8SWyon Bi if (dm_gpio_is_valid(&priv->enable_gpio)) 284c493d00eSWyon Bi dm_gpio_set_value(&priv->enable_gpio, 1); 2857cacd0a8SWyon Bi 2867cacd0a8SWyon Bi if (plat->delay.prepare) 287c493d00eSWyon Bi mdelay(plat->delay.prepare); 288c493d00eSWyon Bi 2897cacd0a8SWyon Bi if (dm_gpio_is_valid(&priv->reset_gpio)) 290c493d00eSWyon Bi dm_gpio_set_value(&priv->reset_gpio, 1); 2917cacd0a8SWyon Bi 2927cacd0a8SWyon Bi if (plat->delay.reset) 293c493d00eSWyon Bi mdelay(plat->delay.reset); 2947cacd0a8SWyon Bi 2957cacd0a8SWyon Bi if (dm_gpio_is_valid(&priv->reset_gpio)) 296c493d00eSWyon Bi dm_gpio_set_value(&priv->reset_gpio, 0); 297c493d00eSWyon Bi 2987cacd0a8SWyon Bi if (plat->delay.init) 299c493d00eSWyon Bi mdelay(plat->delay.init); 300c493d00eSWyon Bi 301c493d00eSWyon Bi if (plat->on_cmds) { 30245fa51f3SSandy Huang if (priv->cmd_type == CMD_TYPE_SPI) 3037cacd0a8SWyon Bi ret = rockchip_panel_send_spi_cmds(panel->state, 30445fa51f3SSandy Huang plat->on_cmds); 30567b9012cSSandy Huang else if (priv->cmd_type == CMD_TYPE_MCU) 3067cacd0a8SWyon Bi ret = rockchip_panel_send_mcu_cmds(panel->state, 3077cacd0a8SWyon Bi plat->on_cmds); 30845fa51f3SSandy Huang else 3091953e619SWyon Bi ret = rockchip_panel_send_dsi_cmds(dsi, plat->on_cmds); 310c493d00eSWyon Bi if (ret) 311c493d00eSWyon Bi printf("failed to send on cmds: %d\n", ret); 312c493d00eSWyon Bi } 313c493d00eSWyon Bi 314c493d00eSWyon Bi priv->prepared = true; 315c493d00eSWyon Bi } 316c493d00eSWyon Bi 3177cacd0a8SWyon Bi static void panel_simple_unprepare(struct rockchip_panel *panel) 318c493d00eSWyon Bi { 3191a8d717cSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 3201a8d717cSWyon Bi struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 3211953e619SWyon Bi struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev); 322c493d00eSWyon Bi int ret; 323c493d00eSWyon Bi 324c493d00eSWyon Bi if (!priv->prepared) 325c493d00eSWyon Bi return; 326c493d00eSWyon Bi 327c493d00eSWyon Bi if (plat->off_cmds) { 32845fa51f3SSandy Huang if (priv->cmd_type == CMD_TYPE_SPI) 3297cacd0a8SWyon Bi ret = rockchip_panel_send_spi_cmds(panel->state, 33045fa51f3SSandy Huang plat->off_cmds); 33167b9012cSSandy Huang else if (priv->cmd_type == CMD_TYPE_MCU) 3327cacd0a8SWyon Bi ret = rockchip_panel_send_mcu_cmds(panel->state, 33367b9012cSSandy Huang plat->off_cmds); 33445fa51f3SSandy Huang else 3351953e619SWyon Bi ret = rockchip_panel_send_dsi_cmds(dsi, plat->off_cmds); 336c493d00eSWyon Bi if (ret) 337c493d00eSWyon Bi printf("failed to send off cmds: %d\n", ret); 338c493d00eSWyon Bi } 339c493d00eSWyon Bi 3407cacd0a8SWyon Bi if (dm_gpio_is_valid(&priv->reset_gpio)) 341c493d00eSWyon Bi dm_gpio_set_value(&priv->reset_gpio, 1); 3427cacd0a8SWyon Bi 3437cacd0a8SWyon Bi if (dm_gpio_is_valid(&priv->enable_gpio)) 344c493d00eSWyon Bi dm_gpio_set_value(&priv->enable_gpio, 0); 345c493d00eSWyon Bi 3467cacd0a8SWyon Bi if (priv->power_supply) 3477cacd0a8SWyon Bi regulator_set_enable(priv->power_supply, plat->power_invert); 348c493d00eSWyon Bi 3497cacd0a8SWyon Bi if (plat->delay.unprepare) 350c493d00eSWyon Bi mdelay(plat->delay.unprepare); 351c493d00eSWyon Bi 352c493d00eSWyon Bi priv->prepared = false; 353c493d00eSWyon Bi } 354c493d00eSWyon Bi 3557cacd0a8SWyon Bi static void panel_simple_enable(struct rockchip_panel *panel) 356c493d00eSWyon Bi { 3571a8d717cSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 3581a8d717cSWyon Bi struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 359c493d00eSWyon Bi 360c493d00eSWyon Bi if (priv->enabled) 3617cacd0a8SWyon Bi return; 362c493d00eSWyon Bi 3637cacd0a8SWyon Bi if (plat->delay.enable) 364c493d00eSWyon Bi mdelay(plat->delay.enable); 365c493d00eSWyon Bi 366c493d00eSWyon Bi if (priv->backlight) 367c493d00eSWyon Bi backlight_enable(priv->backlight); 368c493d00eSWyon Bi 369c493d00eSWyon Bi priv->enabled = true; 370c493d00eSWyon Bi } 371c493d00eSWyon Bi 3727cacd0a8SWyon Bi static void panel_simple_disable(struct rockchip_panel *panel) 373c493d00eSWyon Bi { 3741a8d717cSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); 3751a8d717cSWyon Bi struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); 376c493d00eSWyon Bi 377c493d00eSWyon Bi if (!priv->enabled) 378c493d00eSWyon Bi return; 379c493d00eSWyon Bi 380c493d00eSWyon Bi if (priv->backlight) 381c493d00eSWyon Bi backlight_disable(priv->backlight); 382c493d00eSWyon Bi 3837cacd0a8SWyon Bi if (plat->delay.disable) 384c493d00eSWyon Bi mdelay(plat->delay.disable); 385c493d00eSWyon Bi 386c493d00eSWyon Bi priv->enabled = false; 387c493d00eSWyon Bi } 388c493d00eSWyon Bi 3897cacd0a8SWyon Bi static void panel_simple_init(struct rockchip_panel *panel) 390c493d00eSWyon Bi { 3917cacd0a8SWyon Bi struct display_state *state = panel->state; 392c493d00eSWyon Bi struct connector_state *conn_state = &state->conn_state; 393c493d00eSWyon Bi 3941a8d717cSWyon Bi conn_state->bus_format = panel->bus_format; 395c493d00eSWyon Bi } 396c493d00eSWyon Bi 397c493d00eSWyon Bi static const struct rockchip_panel_funcs rockchip_panel_funcs = { 3987cacd0a8SWyon Bi .init = panel_simple_init, 3997cacd0a8SWyon Bi .prepare = panel_simple_prepare, 4007cacd0a8SWyon Bi .unprepare = panel_simple_unprepare, 4017cacd0a8SWyon Bi .enable = panel_simple_enable, 4027cacd0a8SWyon Bi .disable = panel_simple_disable, 403c493d00eSWyon Bi }; 404c493d00eSWyon Bi 405c493d00eSWyon Bi static int rockchip_panel_ofdata_to_platdata(struct udevice *dev) 406c493d00eSWyon Bi { 407c493d00eSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(dev); 408c493d00eSWyon Bi const void *data; 409c493d00eSWyon Bi int len = 0; 410c493d00eSWyon Bi int ret; 411c493d00eSWyon Bi 412c493d00eSWyon Bi plat->power_invert = dev_read_bool(dev, "power-invert"); 413c493d00eSWyon Bi 414c493d00eSWyon Bi plat->delay.prepare = dev_read_u32_default(dev, "prepare-delay-ms", 0); 415c493d00eSWyon Bi plat->delay.unprepare = dev_read_u32_default(dev, "unprepare-delay-ms", 0); 416c493d00eSWyon Bi plat->delay.enable = dev_read_u32_default(dev, "enable-delay-ms", 0); 417c493d00eSWyon Bi plat->delay.disable = dev_read_u32_default(dev, "disable-delay-ms", 0); 418c493d00eSWyon Bi plat->delay.init = dev_read_u32_default(dev, "init-delay-ms", 0); 419c493d00eSWyon Bi plat->delay.reset = dev_read_u32_default(dev, "reset-delay-ms", 0); 420c493d00eSWyon Bi 421c493d00eSWyon Bi plat->bus_format = dev_read_u32_default(dev, "bus-format", 422c493d00eSWyon Bi MEDIA_BUS_FMT_RBG888_1X24); 42300cdbd6cSWyon Bi plat->bpc = dev_read_u32_default(dev, "bpc", 8); 424c493d00eSWyon Bi 425c493d00eSWyon Bi data = dev_read_prop(dev, "panel-init-sequence", &len); 426c493d00eSWyon Bi if (data) { 427c493d00eSWyon Bi plat->on_cmds = calloc(1, sizeof(*plat->on_cmds)); 428c493d00eSWyon Bi if (!plat->on_cmds) 429c493d00eSWyon Bi return -ENOMEM; 430c493d00eSWyon Bi 431c493d00eSWyon Bi ret = rockchip_panel_parse_cmds(data, len, plat->on_cmds); 432c493d00eSWyon Bi if (ret) { 433c493d00eSWyon Bi printf("failed to parse panel init sequence\n"); 434c493d00eSWyon Bi goto free_on_cmds; 435c493d00eSWyon Bi } 436c493d00eSWyon Bi } 437c493d00eSWyon Bi 438c493d00eSWyon Bi data = dev_read_prop(dev, "panel-exit-sequence", &len); 439c493d00eSWyon Bi if (data) { 440c493d00eSWyon Bi plat->off_cmds = calloc(1, sizeof(*plat->off_cmds)); 441c493d00eSWyon Bi if (!plat->off_cmds) { 442c493d00eSWyon Bi ret = -ENOMEM; 443c493d00eSWyon Bi goto free_on_cmds; 444c493d00eSWyon Bi } 445c493d00eSWyon Bi 446c493d00eSWyon Bi ret = rockchip_panel_parse_cmds(data, len, plat->off_cmds); 447c493d00eSWyon Bi if (ret) { 448c493d00eSWyon Bi printf("failed to parse panel exit sequence\n"); 449c493d00eSWyon Bi goto free_cmds; 450c493d00eSWyon Bi } 451c493d00eSWyon Bi } 452c493d00eSWyon Bi 453c493d00eSWyon Bi return 0; 454c493d00eSWyon Bi 455c493d00eSWyon Bi free_cmds: 456c493d00eSWyon Bi free(plat->off_cmds); 457c493d00eSWyon Bi free_on_cmds: 458c493d00eSWyon Bi free(plat->on_cmds); 459c493d00eSWyon Bi return ret; 460c493d00eSWyon Bi } 461c493d00eSWyon Bi 462c493d00eSWyon Bi static int rockchip_panel_probe(struct udevice *dev) 463c493d00eSWyon Bi { 464c493d00eSWyon Bi struct rockchip_panel_priv *priv = dev_get_priv(dev); 4651a8d717cSWyon Bi struct rockchip_panel_plat *plat = dev_get_platdata(dev); 4662942bf18SWyon Bi struct rockchip_panel *panel; 467c493d00eSWyon Bi int ret; 46845fa51f3SSandy Huang const char *cmd_type; 469c493d00eSWyon Bi 470c493d00eSWyon Bi ret = gpio_request_by_name(dev, "enable-gpios", 0, 471c493d00eSWyon Bi &priv->enable_gpio, GPIOD_IS_OUT); 472c493d00eSWyon Bi if (ret && ret != -ENOENT) { 473c493d00eSWyon Bi printf("%s: Cannot get enable GPIO: %d\n", __func__, ret); 474c493d00eSWyon Bi return ret; 475c493d00eSWyon Bi } 476c493d00eSWyon Bi 477c493d00eSWyon Bi ret = gpio_request_by_name(dev, "reset-gpios", 0, 478c493d00eSWyon Bi &priv->reset_gpio, GPIOD_IS_OUT); 479c493d00eSWyon Bi if (ret && ret != -ENOENT) { 480c493d00eSWyon Bi printf("%s: Cannot get reset GPIO: %d\n", __func__, ret); 481c493d00eSWyon Bi return ret; 482c493d00eSWyon Bi } 483c493d00eSWyon Bi 484c493d00eSWyon Bi ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, 485c493d00eSWyon Bi "backlight", &priv->backlight); 486c493d00eSWyon Bi if (ret && ret != -ENOENT) { 487c493d00eSWyon Bi printf("%s: Cannot get backlight: %d\n", __func__, ret); 488c493d00eSWyon Bi return ret; 489c493d00eSWyon Bi } 490c493d00eSWyon Bi 491c493d00eSWyon Bi ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, 492c493d00eSWyon Bi "power-supply", &priv->power_supply); 493c493d00eSWyon Bi if (ret && ret != -ENOENT) { 494c493d00eSWyon Bi printf("%s: Cannot get power supply: %d\n", __func__, ret); 495c493d00eSWyon Bi return ret; 496c493d00eSWyon Bi } 497c493d00eSWyon Bi 49845fa51f3SSandy Huang ret = dev_read_string_index(dev, "rockchip,cmd-type", 0, &cmd_type); 49945fa51f3SSandy Huang if (ret) 50045fa51f3SSandy Huang priv->cmd_type = CMD_TYPE_DEFAULT; 50145fa51f3SSandy Huang else 50245fa51f3SSandy Huang priv->cmd_type = get_panel_cmd_type(cmd_type); 50345fa51f3SSandy Huang 50445fa51f3SSandy Huang if (priv->cmd_type == CMD_TYPE_SPI) { 50545fa51f3SSandy Huang ret = gpio_request_by_name(dev, "spi-sdi-gpios", 0, 50645fa51f3SSandy Huang &priv->spi_sdi_gpio, GPIOD_IS_OUT); 50745fa51f3SSandy Huang if (ret && ret != -ENOENT) { 50845fa51f3SSandy Huang printf("%s: Cannot get spi sdi GPIO: %d\n", 50945fa51f3SSandy Huang __func__, ret); 51045fa51f3SSandy Huang return ret; 51145fa51f3SSandy Huang } 51245fa51f3SSandy Huang ret = gpio_request_by_name(dev, "spi-scl-gpios", 0, 51345fa51f3SSandy Huang &priv->spi_scl_gpio, GPIOD_IS_OUT); 51445fa51f3SSandy Huang if (ret && ret != -ENOENT) { 51545fa51f3SSandy Huang printf("%s: Cannot get spi scl GPIO: %d\n", 51645fa51f3SSandy Huang __func__, ret); 51745fa51f3SSandy Huang return ret; 51845fa51f3SSandy Huang } 51945fa51f3SSandy Huang ret = gpio_request_by_name(dev, "spi-cs-gpios", 0, 52045fa51f3SSandy Huang &priv->spi_cs_gpio, GPIOD_IS_OUT); 52145fa51f3SSandy Huang if (ret && ret != -ENOENT) { 52245fa51f3SSandy Huang printf("%s: Cannot get spi cs GPIO: %d\n", 52345fa51f3SSandy Huang __func__, ret); 52445fa51f3SSandy Huang return ret; 52545fa51f3SSandy Huang } 52645fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_sdi_gpio, 1); 52745fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_scl_gpio, 1); 52845fa51f3SSandy Huang dm_gpio_set_value(&priv->spi_cs_gpio, 1); 52945fa51f3SSandy Huang dm_gpio_set_value(&priv->reset_gpio, 0); 53045fa51f3SSandy Huang } 53145fa51f3SSandy Huang 5322942bf18SWyon Bi panel = calloc(1, sizeof(*panel)); 5332942bf18SWyon Bi if (!panel) 5342942bf18SWyon Bi return -ENOMEM; 5352942bf18SWyon Bi 5362942bf18SWyon Bi dev->driver_data = (ulong)panel; 5371a8d717cSWyon Bi panel->dev = dev; 5381a8d717cSWyon Bi panel->bus_format = plat->bus_format; 53900cdbd6cSWyon Bi panel->bpc = plat->bpc; 5402942bf18SWyon Bi panel->funcs = &rockchip_panel_funcs; 5411a8d717cSWyon Bi 542c493d00eSWyon Bi return 0; 543c493d00eSWyon Bi } 544c493d00eSWyon Bi 545186f8572SMark Yao static const struct udevice_id rockchip_panel_ids[] = { 5462942bf18SWyon Bi { .compatible = "simple-panel", }, 5472942bf18SWyon Bi { .compatible = "simple-panel-dsi", }, 548186f8572SMark Yao {} 549186f8572SMark Yao }; 550186f8572SMark Yao 551186f8572SMark Yao U_BOOT_DRIVER(rockchip_panel) = { 552186f8572SMark Yao .name = "rockchip_panel", 553186f8572SMark Yao .id = UCLASS_PANEL, 554186f8572SMark Yao .of_match = rockchip_panel_ids, 555c493d00eSWyon Bi .ofdata_to_platdata = rockchip_panel_ofdata_to_platdata, 556186f8572SMark Yao .probe = rockchip_panel_probe, 557c493d00eSWyon Bi .priv_auto_alloc_size = sizeof(struct rockchip_panel_priv), 558c493d00eSWyon Bi .platdata_auto_alloc_size = sizeof(struct rockchip_panel_plat), 559186f8572SMark Yao }; 560