1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Driver for panels based on Himax HX8394 controller, such as: 4 * 5 * - HannStar HSD060BHW4 5.99" MIPI-DSI panel 6 * 7 * Copyright (C) 2021 Kamil Trzciński 8 * 9 * Based on drivers/gpu/drm/panel/panel-sitronix-st7703.c 10 * Copyright (C) Purism SPC 2019 11 */ 12 13 #include <linux/delay.h> 14 #include <linux/gpio/consumer.h> 15 #include <linux/media-bus-format.h> 16 #include <linux/mod_devicetable.h> 17 #include <linux/module.h> 18 #include <linux/of.h> 19 #include <linux/regulator/consumer.h> 20 21 #include <video/mipi_display.h> 22 23 #include <drm/drm_mipi_dsi.h> 24 #include <drm/drm_modes.h> 25 #include <drm/drm_panel.h> 26 27 #define DRV_NAME "panel-himax-hx8394" 28 29 /* Manufacturer specific commands sent via DSI, listed in HX8394-F datasheet */ 30 #define HX8394_CMD_SETSEQUENCE 0xb0 31 #define HX8394_CMD_SETPOWER 0xb1 32 #define HX8394_CMD_SETDISP 0xb2 33 #define HX8394_CMD_SETCYC 0xb4 34 #define HX8394_CMD_SETVCOM 0xb6 35 #define HX8394_CMD_SETTE 0xb7 36 #define HX8394_CMD_SETSENSOR 0xb8 37 #define HX8394_CMD_SETEXTC 0xb9 38 #define HX8394_CMD_SETMIPI 0xba 39 #define HX8394_CMD_SETOTP 0xbb 40 #define HX8394_CMD_SETREGBANK 0xbd 41 #define HX8394_CMD_UNKNOWN1 0xc0 42 #define HX8394_CMD_SETDGCLUT 0xc1 43 #define HX8394_CMD_SETID 0xc3 44 #define HX8394_CMD_SETDDB 0xc4 45 #define HX8394_CMD_UNKNOWN2 0xc6 46 #define HX8394_CMD_SETCABC 0xc9 47 #define HX8394_CMD_SETCABCGAIN 0xca 48 #define HX8394_CMD_SETPANEL 0xcc 49 #define HX8394_CMD_SETOFFSET 0xd2 50 #define HX8394_CMD_SETGIP0 0xd3 51 #define HX8394_CMD_UNKNOWN3 0xd4 52 #define HX8394_CMD_SETGIP1 0xd5 53 #define HX8394_CMD_SETGIP2 0xd6 54 #define HX8394_CMD_SETGPO 0xd6 55 #define HX8394_CMD_SETSCALING 0xdd 56 #define HX8394_CMD_SETIDLE 0xdf 57 #define HX8394_CMD_SETGAMMA 0xe0 58 #define HX8394_CMD_SETCHEMODE_DYN 0xe4 59 #define HX8394_CMD_SETCHE 0xe5 60 #define HX8394_CMD_SETCESEL 0xe6 61 #define HX8394_CMD_SET_SP_CMD 0xe9 62 #define HX8394_CMD_SETREADINDEX 0xfe 63 #define HX8394_CMD_GETSPIREAD 0xff 64 65 struct hx8394 { 66 struct device *dev; 67 struct drm_panel panel; 68 struct gpio_desc *reset_gpio; 69 struct regulator *vcc; 70 struct regulator *iovcc; 71 bool prepared; 72 73 const struct hx8394_panel_desc *desc; 74 }; 75 76 struct hx8394_panel_desc { 77 const struct drm_display_mode *mode; 78 unsigned int lanes; 79 unsigned long mode_flags; 80 enum mipi_dsi_pixel_format format; 81 int (*init_sequence)(struct hx8394 *ctx); 82 }; 83 84 static inline struct hx8394 *panel_to_hx8394(struct drm_panel *panel) 85 { 86 return container_of(panel, struct hx8394, panel); 87 } 88 89 static int hsd060bhw4_init_sequence(struct hx8394 *ctx) 90 { 91 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 92 93 /* 5.19.8 SETEXTC: Set extension command (B9h) */ 94 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETEXTC, 95 0xff, 0x83, 0x94); 96 97 /* 5.19.2 SETPOWER: Set power (B1h) */ 98 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, 99 0x48, 0x11, 0x71, 0x09, 0x32, 0x24, 0x71, 0x31, 0x55, 0x30); 100 101 /* 5.19.9 SETMIPI: Set MIPI control (BAh) */ 102 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETMIPI, 103 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0); 104 105 /* 5.19.3 SETDISP: Set display related register (B2h) */ 106 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETDISP, 107 0x00, 0x80, 0x78, 0x0c, 0x07); 108 109 /* 5.19.4 SETCYC: Set display waveform cycles (B4h) */ 110 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCYC, 111 0x12, 0x63, 0x12, 0x63, 0x12, 0x63, 0x01, 0x0c, 0x7c, 0x55, 112 0x00, 0x3f, 0x12, 0x6b, 0x12, 0x6b, 0x12, 0x6b, 0x01, 0x0c, 113 0x7c); 114 115 /* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */ 116 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP0, 117 0x00, 0x00, 0x00, 0x00, 0x3c, 0x1c, 0x00, 0x00, 0x32, 0x10, 118 0x09, 0x00, 0x09, 0x32, 0x15, 0xad, 0x05, 0xad, 0x32, 0x00, 119 0x00, 0x00, 0x00, 0x37, 0x03, 0x0b, 0x0b, 0x37, 0x00, 0x00, 120 0x00, 0x0c, 0x40); 121 122 /* 5.19.20 Set GIP Option1 (D5h) */ 123 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP1, 124 0x19, 0x19, 0x18, 0x18, 0x1b, 0x1b, 0x1a, 0x1a, 0x00, 0x01, 125 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x18, 0x18, 126 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 127 0x24, 0x25, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 128 0x18, 0x18, 0x18, 0x18, 0x18, 0x18); 129 130 /* 5.19.21 Set GIP Option2 (D6h) */ 131 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP2, 132 0x18, 0x18, 0x19, 0x19, 0x1b, 0x1b, 0x1a, 0x1a, 0x07, 0x06, 133 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x25, 0x24, 0x18, 0x18, 134 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 135 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 136 0x18, 0x18, 0x18, 0x18, 0x18, 0x18); 137 138 /* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */ 139 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGAMMA, 140 0x00, 0x04, 0x0c, 0x12, 0x14, 0x18, 0x1a, 0x18, 0x31, 0x3f, 141 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a, 142 0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f, 0x00, 143 0x04, 0x0c, 0x11, 0x13, 0x17, 0x1a, 0x18, 0x31, 144 0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 145 0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b, 146 0x4a, 0x4c, 0x4b, 0x7f); 147 148 /* 5.19.17 SETPANEL (CCh) */ 149 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPANEL, 150 0x0b); 151 152 /* Unknown command, not listed in the HX8394-F datasheet */ 153 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN1, 154 0x1f, 0x31); 155 156 /* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */ 157 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETVCOM, 158 0x7d, 0x7d); 159 160 /* Unknown command, not listed in the HX8394-F datasheet */ 161 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3, 162 0x02); 163 164 /* 5.19.11 Set register bank (BDh) */ 165 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, 166 0x01); 167 168 /* 5.19.2 SETPOWER: Set power (B1h) */ 169 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, 170 0x00); 171 172 /* 5.19.11 Set register bank (BDh) */ 173 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, 174 0x00); 175 176 /* Unknown command, not listed in the HX8394-F datasheet */ 177 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3, 178 0xed); 179 180 return 0; 181 } 182 183 static const struct drm_display_mode hsd060bhw4_mode = { 184 .hdisplay = 720, 185 .hsync_start = 720 + 40, 186 .hsync_end = 720 + 40 + 46, 187 .htotal = 720 + 40 + 46 + 40, 188 .vdisplay = 1440, 189 .vsync_start = 1440 + 9, 190 .vsync_end = 1440 + 9 + 7, 191 .vtotal = 1440 + 9 + 7 + 7, 192 .clock = 74250, 193 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 194 .width_mm = 68, 195 .height_mm = 136, 196 }; 197 198 static const struct hx8394_panel_desc hsd060bhw4_desc = { 199 .mode = &hsd060bhw4_mode, 200 .lanes = 4, 201 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST, 202 .format = MIPI_DSI_FMT_RGB888, 203 .init_sequence = hsd060bhw4_init_sequence, 204 }; 205 206 static int hx8394_enable(struct drm_panel *panel) 207 { 208 struct hx8394 *ctx = panel_to_hx8394(panel); 209 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 210 int ret; 211 212 ret = ctx->desc->init_sequence(ctx); 213 if (ret) { 214 dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); 215 return ret; 216 } 217 218 ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 219 if (ret) { 220 dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret); 221 return ret; 222 } 223 224 /* Panel is operational 120 msec after reset */ 225 msleep(120); 226 227 ret = mipi_dsi_dcs_set_display_on(dsi); 228 if (ret) { 229 dev_err(ctx->dev, "Failed to turn on the display: %d\n", ret); 230 goto sleep_in; 231 } 232 233 return 0; 234 235 sleep_in: 236 /* This will probably fail, but let's try orderly power off anyway. */ 237 if (!mipi_dsi_dcs_enter_sleep_mode(dsi)) 238 msleep(50); 239 240 return ret; 241 } 242 243 static int hx8394_disable(struct drm_panel *panel) 244 { 245 struct hx8394 *ctx = panel_to_hx8394(panel); 246 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 247 int ret; 248 249 ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 250 if (ret) { 251 dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret); 252 return ret; 253 } 254 255 msleep(50); /* about 3 frames */ 256 257 return 0; 258 } 259 260 static int hx8394_unprepare(struct drm_panel *panel) 261 { 262 struct hx8394 *ctx = panel_to_hx8394(panel); 263 264 if (!ctx->prepared) 265 return 0; 266 267 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 268 269 regulator_disable(ctx->iovcc); 270 regulator_disable(ctx->vcc); 271 272 ctx->prepared = false; 273 274 return 0; 275 } 276 277 static int hx8394_prepare(struct drm_panel *panel) 278 { 279 struct hx8394 *ctx = panel_to_hx8394(panel); 280 int ret; 281 282 if (ctx->prepared) 283 return 0; 284 285 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 286 287 ret = regulator_enable(ctx->vcc); 288 if (ret) { 289 dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret); 290 return ret; 291 } 292 293 ret = regulator_enable(ctx->iovcc); 294 if (ret) { 295 dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret); 296 goto disable_vcc; 297 } 298 299 gpiod_set_value_cansleep(ctx->reset_gpio, 0); 300 301 msleep(180); 302 303 ctx->prepared = true; 304 305 return 0; 306 307 disable_vcc: 308 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 309 regulator_disable(ctx->vcc); 310 return ret; 311 } 312 313 static int hx8394_get_modes(struct drm_panel *panel, 314 struct drm_connector *connector) 315 { 316 struct hx8394 *ctx = panel_to_hx8394(panel); 317 struct drm_display_mode *mode; 318 319 mode = drm_mode_duplicate(connector->dev, ctx->desc->mode); 320 if (!mode) { 321 dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n", 322 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, 323 drm_mode_vrefresh(ctx->desc->mode)); 324 return -ENOMEM; 325 } 326 327 drm_mode_set_name(mode); 328 329 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 330 connector->display_info.width_mm = mode->width_mm; 331 connector->display_info.height_mm = mode->height_mm; 332 drm_mode_probed_add(connector, mode); 333 334 return 1; 335 } 336 337 static const struct drm_panel_funcs hx8394_drm_funcs = { 338 .disable = hx8394_disable, 339 .unprepare = hx8394_unprepare, 340 .prepare = hx8394_prepare, 341 .enable = hx8394_enable, 342 .get_modes = hx8394_get_modes, 343 }; 344 345 static int hx8394_probe(struct mipi_dsi_device *dsi) 346 { 347 struct device *dev = &dsi->dev; 348 struct hx8394 *ctx; 349 int ret; 350 351 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 352 if (!ctx) 353 return -ENOMEM; 354 355 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 356 if (IS_ERR(ctx->reset_gpio)) 357 return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), 358 "Failed to get reset gpio\n"); 359 360 mipi_dsi_set_drvdata(dsi, ctx); 361 362 ctx->dev = dev; 363 ctx->desc = of_device_get_match_data(dev); 364 365 dsi->mode_flags = ctx->desc->mode_flags; 366 dsi->format = ctx->desc->format; 367 dsi->lanes = ctx->desc->lanes; 368 369 ctx->vcc = devm_regulator_get(dev, "vcc"); 370 if (IS_ERR(ctx->vcc)) 371 return dev_err_probe(dev, PTR_ERR(ctx->vcc), 372 "Failed to request vcc regulator\n"); 373 374 ctx->iovcc = devm_regulator_get(dev, "iovcc"); 375 if (IS_ERR(ctx->iovcc)) 376 return dev_err_probe(dev, PTR_ERR(ctx->iovcc), 377 "Failed to request iovcc regulator\n"); 378 379 drm_panel_init(&ctx->panel, dev, &hx8394_drm_funcs, 380 DRM_MODE_CONNECTOR_DSI); 381 382 ret = drm_panel_of_backlight(&ctx->panel); 383 if (ret) 384 return ret; 385 386 drm_panel_add(&ctx->panel); 387 388 ret = mipi_dsi_attach(dsi); 389 if (ret < 0) { 390 dev_err_probe(dev, ret, "mipi_dsi_attach failed\n"); 391 drm_panel_remove(&ctx->panel); 392 return ret; 393 } 394 395 dev_dbg(dev, "%ux%u@%u %ubpp dsi %udl - ready\n", 396 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, 397 drm_mode_vrefresh(ctx->desc->mode), 398 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes); 399 400 return 0; 401 } 402 403 static void hx8394_shutdown(struct mipi_dsi_device *dsi) 404 { 405 struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi); 406 int ret; 407 408 ret = drm_panel_disable(&ctx->panel); 409 if (ret < 0) 410 dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); 411 412 ret = drm_panel_unprepare(&ctx->panel); 413 if (ret < 0) 414 dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); 415 } 416 417 static void hx8394_remove(struct mipi_dsi_device *dsi) 418 { 419 struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi); 420 int ret; 421 422 hx8394_shutdown(dsi); 423 424 ret = mipi_dsi_detach(dsi); 425 if (ret < 0) 426 dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); 427 428 drm_panel_remove(&ctx->panel); 429 } 430 431 static const struct of_device_id hx8394_of_match[] = { 432 { .compatible = "hannstar,hsd060bhw4", .data = &hsd060bhw4_desc }, 433 { /* sentinel */ } 434 }; 435 MODULE_DEVICE_TABLE(of, hx8394_of_match); 436 437 static struct mipi_dsi_driver hx8394_driver = { 438 .probe = hx8394_probe, 439 .remove = hx8394_remove, 440 .shutdown = hx8394_shutdown, 441 .driver = { 442 .name = DRV_NAME, 443 .of_match_table = hx8394_of_match, 444 }, 445 }; 446 module_mipi_dsi_driver(hx8394_driver); 447 448 MODULE_AUTHOR("Kamil Trzciński <ayufan@ayufan.eu>"); 449 MODULE_DESCRIPTION("DRM driver for Himax HX8394 based MIPI DSI panels"); 450 MODULE_LICENSE("GPL"); 451