1 /* 2 * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <config.h> 8 #include <common.h> 9 #include <errno.h> 10 #include <malloc.h> 11 #include <video.h> 12 #include <backlight.h> 13 #include <asm/gpio.h> 14 #include <dm/device.h> 15 #include <dm/read.h> 16 #include <dm/uclass.h> 17 #include <dm/uclass-id.h> 18 #include <linux/media-bus-format.h> 19 #include <power/regulator.h> 20 21 #include "rockchip_display.h" 22 #include "rockchip_crtc.h" 23 #include "rockchip_connector.h" 24 #include "rockchip_mipi_dsi.h" 25 #include "rockchip_panel.h" 26 27 struct rockchip_cmd_header { 28 u8 data_type; 29 u8 delay_ms; 30 u8 payload_length; 31 } __packed; 32 33 struct rockchip_cmd_desc { 34 struct rockchip_cmd_header header; 35 const u8 *payload; 36 }; 37 38 struct rockchip_panel_cmds { 39 struct rockchip_cmd_desc *cmds; 40 int cmd_cnt; 41 }; 42 43 struct rockchip_panel_plat { 44 bool power_invert; 45 u32 bus_format; 46 47 struct { 48 unsigned int prepare; 49 unsigned int unprepare; 50 unsigned int enable; 51 unsigned int disable; 52 unsigned int reset; 53 unsigned int init; 54 } delay; 55 56 struct rockchip_panel_cmds *on_cmds; 57 struct rockchip_panel_cmds *off_cmds; 58 }; 59 60 struct rockchip_panel_priv { 61 bool prepared; 62 bool enabled; 63 struct udevice *power_supply; 64 struct udevice *backlight; 65 struct gpio_desc enable_gpio; 66 struct gpio_desc reset_gpio; 67 }; 68 69 static int rockchip_panel_parse_cmds(const u8 *data, int length, 70 struct rockchip_panel_cmds *pcmds) 71 { 72 int len; 73 const u8 *buf; 74 const struct rockchip_cmd_header *header; 75 int i, cnt = 0; 76 77 /* scan commands */ 78 cnt = 0; 79 buf = data; 80 len = length; 81 while (len > sizeof(*header)) { 82 header = (const struct rockchip_cmd_header *)buf; 83 buf += sizeof(*header) + header->payload_length; 84 len -= sizeof(*header) + header->payload_length; 85 cnt++; 86 } 87 88 pcmds->cmds = calloc(cnt, sizeof(struct rockchip_cmd_desc)); 89 if (!pcmds->cmds) 90 return -ENOMEM; 91 92 pcmds->cmd_cnt = cnt; 93 94 buf = data; 95 len = length; 96 for (i = 0; i < cnt; i++) { 97 struct rockchip_cmd_desc *desc = &pcmds->cmds[i]; 98 99 header = (const struct rockchip_cmd_header *)buf; 100 length -= sizeof(*header); 101 buf += sizeof(*header); 102 desc->header.data_type = header->data_type; 103 desc->header.delay_ms = header->delay_ms; 104 desc->header.payload_length = header->payload_length; 105 desc->payload = buf; 106 buf += header->payload_length; 107 length -= header->payload_length; 108 } 109 110 return 0; 111 } 112 113 static int rockchip_panel_send_cmds(struct display_state *state, 114 struct rockchip_panel_cmds *cmds) 115 { 116 int i, ret; 117 118 if (!cmds) 119 return -EINVAL; 120 121 for (i = 0; i < cmds->cmd_cnt; i++) { 122 struct rockchip_cmd_desc *desc = &cmds->cmds[i]; 123 124 switch (desc->header.data_type) { 125 case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: 126 case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: 127 case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: 128 case MIPI_DSI_GENERIC_LONG_WRITE: 129 ret = mipi_dsi_generic_write(state, desc->payload, 130 desc->header.payload_length); 131 break; 132 case MIPI_DSI_DCS_SHORT_WRITE: 133 case MIPI_DSI_DCS_SHORT_WRITE_PARAM: 134 case MIPI_DSI_DCS_LONG_WRITE: 135 ret = mipi_dsi_dcs_write(state, desc->payload, 136 desc->header.payload_length); 137 break; 138 default: 139 printf("unsupport command data type: %d\n", 140 desc->header.data_type); 141 return -EINVAL; 142 } 143 144 if (ret) { 145 printf("failed to write cmd%d: %d\n", i, ret); 146 return ret; 147 } 148 149 if (desc->header.delay_ms) 150 mdelay(desc->header.delay_ms); 151 } 152 153 return 0; 154 } 155 156 static int rockchip_panel_prepare(struct display_state *state) 157 { 158 struct panel_state *panel_state = &state->panel_state; 159 struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev); 160 struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev); 161 int ret; 162 163 if (priv->prepared) 164 return 0; 165 166 if (priv->power_supply) { 167 ret = regulator_set_enable(priv->power_supply, 168 !plat->power_invert); 169 if (ret) { 170 printf("%s: failed to enable power supply", __func__); 171 return ret; 172 } 173 } 174 175 dm_gpio_set_value(&priv->enable_gpio, 1); 176 mdelay(plat->delay.prepare); 177 178 dm_gpio_set_value(&priv->reset_gpio, 1); 179 mdelay(plat->delay.reset); 180 dm_gpio_set_value(&priv->reset_gpio, 0); 181 182 mdelay(plat->delay.init); 183 184 if (plat->on_cmds) { 185 ret = rockchip_panel_send_cmds(state, plat->on_cmds); 186 if (ret) 187 printf("failed to send on cmds: %d\n", ret); 188 } 189 190 priv->prepared = true; 191 192 return 0; 193 } 194 195 static void rockchip_panel_unprepare(struct display_state *state) 196 { 197 struct panel_state *panel_state = &state->panel_state; 198 struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev); 199 struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev); 200 int ret; 201 202 if (!priv->prepared) 203 return; 204 205 if (plat->off_cmds) { 206 ret = rockchip_panel_send_cmds(state, plat->off_cmds); 207 if (ret) 208 printf("failed to send off cmds: %d\n", ret); 209 } 210 211 dm_gpio_set_value(&priv->reset_gpio, 1); 212 dm_gpio_set_value(&priv->enable_gpio, 0); 213 214 if (priv->power_supply) { 215 ret = regulator_set_enable(priv->power_supply, 216 plat->power_invert); 217 if (ret) 218 printf("%s: failed to disable power supply", __func__); 219 } 220 221 mdelay(plat->delay.unprepare); 222 223 priv->prepared = false; 224 } 225 226 static int rockchip_panel_enable(struct display_state *state) 227 { 228 struct panel_state *panel_state = &state->panel_state; 229 struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev); 230 struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev); 231 232 if (priv->enabled) 233 return 0; 234 235 mdelay(plat->delay.enable); 236 237 if (priv->backlight) 238 backlight_enable(priv->backlight); 239 240 priv->enabled = true; 241 242 return 0; 243 } 244 245 static void rockchip_panel_disable(struct display_state *state) 246 { 247 struct panel_state *panel_state = &state->panel_state; 248 struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev); 249 struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev); 250 251 if (!priv->enabled) 252 return; 253 254 if (priv->backlight) 255 backlight_disable(priv->backlight); 256 257 mdelay(plat->delay.disable); 258 259 priv->enabled = false; 260 } 261 262 static int rockchip_panel_init(struct display_state *state) 263 { 264 struct connector_state *conn_state = &state->conn_state; 265 struct panel_state *panel_state = &state->panel_state; 266 struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev); 267 268 conn_state->bus_format = plat->bus_format; 269 270 return 0; 271 } 272 273 static const struct rockchip_panel_funcs rockchip_panel_funcs = { 274 .init = rockchip_panel_init, 275 .prepare = rockchip_panel_prepare, 276 .unprepare = rockchip_panel_unprepare, 277 .enable = rockchip_panel_enable, 278 .disable = rockchip_panel_disable, 279 }; 280 281 static int rockchip_panel_ofdata_to_platdata(struct udevice *dev) 282 { 283 struct rockchip_panel_plat *plat = dev_get_platdata(dev); 284 const void *data; 285 int len = 0; 286 int ret; 287 288 plat->power_invert = dev_read_bool(dev, "power-invert"); 289 290 plat->delay.prepare = dev_read_u32_default(dev, "prepare-delay-ms", 0); 291 plat->delay.unprepare = dev_read_u32_default(dev, "unprepare-delay-ms", 0); 292 plat->delay.enable = dev_read_u32_default(dev, "enable-delay-ms", 0); 293 plat->delay.disable = dev_read_u32_default(dev, "disable-delay-ms", 0); 294 plat->delay.init = dev_read_u32_default(dev, "init-delay-ms", 0); 295 plat->delay.reset = dev_read_u32_default(dev, "reset-delay-ms", 0); 296 297 plat->bus_format = dev_read_u32_default(dev, "bus-format", 298 MEDIA_BUS_FMT_RBG888_1X24); 299 300 data = dev_read_prop(dev, "panel-init-sequence", &len); 301 if (data) { 302 plat->on_cmds = calloc(1, sizeof(*plat->on_cmds)); 303 if (!plat->on_cmds) 304 return -ENOMEM; 305 306 ret = rockchip_panel_parse_cmds(data, len, plat->on_cmds); 307 if (ret) { 308 printf("failed to parse panel init sequence\n"); 309 goto free_on_cmds; 310 } 311 } 312 313 data = dev_read_prop(dev, "panel-exit-sequence", &len); 314 if (data) { 315 plat->off_cmds = calloc(1, sizeof(*plat->off_cmds)); 316 if (!plat->off_cmds) { 317 ret = -ENOMEM; 318 goto free_on_cmds; 319 } 320 321 ret = rockchip_panel_parse_cmds(data, len, plat->off_cmds); 322 if (ret) { 323 printf("failed to parse panel exit sequence\n"); 324 goto free_cmds; 325 } 326 } 327 328 return 0; 329 330 free_cmds: 331 free(plat->off_cmds); 332 free_on_cmds: 333 free(plat->on_cmds); 334 return ret; 335 } 336 337 static int rockchip_panel_probe(struct udevice *dev) 338 { 339 struct rockchip_panel_priv *priv = dev_get_priv(dev); 340 int ret; 341 342 ret = gpio_request_by_name(dev, "enable-gpios", 0, 343 &priv->enable_gpio, GPIOD_IS_OUT); 344 if (ret && ret != -ENOENT) { 345 printf("%s: Cannot get enable GPIO: %d\n", __func__, ret); 346 return ret; 347 } 348 349 ret = gpio_request_by_name(dev, "reset-gpios", 0, 350 &priv->reset_gpio, GPIOD_IS_OUT); 351 if (ret && ret != -ENOENT) { 352 printf("%s: Cannot get reset GPIO: %d\n", __func__, ret); 353 return ret; 354 } 355 356 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, 357 "backlight", &priv->backlight); 358 if (ret && ret != -ENOENT) { 359 printf("%s: Cannot get backlight: %d\n", __func__, ret); 360 return ret; 361 } 362 363 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, 364 "power-supply", &priv->power_supply); 365 if (ret && ret != -ENOENT) { 366 printf("%s: Cannot get power supply: %d\n", __func__, ret); 367 return ret; 368 } 369 370 return 0; 371 } 372 373 static const struct drm_display_mode auo_b125han03_mode = { 374 .clock = 146900, 375 .hdisplay = 1920, 376 .hsync_start = 1920 + 48, 377 .hsync_end = 1920 + 48 + 32, 378 .htotal = 1920 + 48 + 32 + 140, 379 .vdisplay = 1080, 380 .vsync_start = 1080 + 2, 381 .vsync_end = 1080 + 2 + 5, 382 .vtotal = 1080 + 2 + 5 + 57, 383 .vrefresh = 60, 384 .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, 385 }; 386 387 static const struct rockchip_panel auo_b125han03_data = { 388 .funcs = &rockchip_panel_funcs, 389 .data = &auo_b125han03_mode, 390 }; 391 392 static const struct drm_display_mode lg_lp079qx1_sp0v_mode = { 393 .clock = 200000, 394 .hdisplay = 1536, 395 .hsync_start = 1536 + 12, 396 .hsync_end = 1536 + 12 + 16, 397 .htotal = 1536 + 12 + 16 + 48, 398 .vdisplay = 2048, 399 .vsync_start = 2048 + 8, 400 .vsync_end = 2048 + 8 + 4, 401 .vtotal = 2048 + 8 + 4 + 8, 402 .vrefresh = 60, 403 .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, 404 }; 405 406 static const struct rockchip_panel lg_lp079qx1_sp0v_data = { 407 .funcs = &rockchip_panel_funcs, 408 .data = &lg_lp079qx1_sp0v_mode, 409 }; 410 411 static const struct rockchip_panel rockchip_panel_data = { 412 .funcs = &rockchip_panel_funcs, 413 }; 414 415 static const struct udevice_id rockchip_panel_ids[] = { 416 { 417 .compatible = "auo,b125han03", 418 .data = (ulong)&auo_b125han03_data, 419 }, { 420 .compatible = "lg,lp079qx1-sp0v", 421 .data = (ulong)&lg_lp079qx1_sp0v_data, 422 }, { 423 .compatible = "simple-panel", 424 .data = (ulong)&rockchip_panel_data, 425 }, { 426 .compatible = "simple-panel-dsi", 427 .data = (ulong)&rockchip_panel_data, 428 }, 429 {} 430 }; 431 432 U_BOOT_DRIVER(rockchip_panel) = { 433 .name = "rockchip_panel", 434 .id = UCLASS_PANEL, 435 .of_match = rockchip_panel_ids, 436 .ofdata_to_platdata = rockchip_panel_ofdata_to_platdata, 437 .probe = rockchip_panel_probe, 438 .priv_auto_alloc_size = sizeof(struct rockchip_panel_priv), 439 .platdata_auto_alloc_size = sizeof(struct rockchip_panel_plat), 440 }; 441