1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2020 BSH Hausgerate GmbH 4 */ 5 6 #include <linux/delay.h> 7 #include <linux/device.h> 8 #include <linux/err.h> 9 #include <linux/errno.h> 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 14 #include <linux/gpio/consumer.h> 15 #include <linux/regulator/consumer.h> 16 17 #include <drm/drm_mipi_dsi.h> 18 #include <drm/drm_modes.h> 19 #include <drm/drm_panel.h> 20 21 #include <video/mipi_display.h> 22 23 #define ILI9805_EXTCMD_CMD_SET_ENABLE_REG (0xff) 24 #define ILI9805_SETEXTC_PARAMETER1 (0xff) 25 #define ILI9805_SETEXTC_PARAMETER2 (0x98) 26 #define ILI9805_SETEXTC_PARAMETER3 (0x05) 27 28 #define ILI9805_INSTR(_delay, ...) { \ 29 .delay = (_delay), \ 30 .len = sizeof((u8[]) {__VA_ARGS__}), \ 31 .data = (u8[]){__VA_ARGS__} \ 32 } 33 34 struct ili9805_instr { 35 size_t len; 36 const u8 *data; 37 u32 delay; 38 }; 39 40 struct ili9805_desc { 41 const char *name; 42 const struct ili9805_instr *init; 43 const size_t init_length; 44 const struct drm_display_mode *mode; 45 u32 width_mm; 46 u32 height_mm; 47 }; 48 49 struct ili9805 { 50 struct drm_panel panel; 51 struct mipi_dsi_device *dsi; 52 const struct ili9805_desc *desc; 53 54 struct regulator *dvdd; 55 struct regulator *avdd; 56 struct gpio_desc *reset_gpio; 57 }; 58 59 static const struct ili9805_instr gpm1780a0_init[] = { 60 ILI9805_INSTR(100, ILI9805_EXTCMD_CMD_SET_ENABLE_REG, ILI9805_SETEXTC_PARAMETER1, 61 ILI9805_SETEXTC_PARAMETER2, ILI9805_SETEXTC_PARAMETER3), 62 ILI9805_INSTR(100, 0xFD, 0x0F, 0x10, 0x44, 0x00), 63 ILI9805_INSTR(0, 0xf8, 0x18, 0x02, 0x02, 0x18, 0x02, 0x02, 0x30, 0x00, 64 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00), 65 ILI9805_INSTR(0, 0xB8, 0x62), 66 ILI9805_INSTR(0, 0xF1, 0x00), 67 ILI9805_INSTR(0, 0xF2, 0x00, 0x58, 0x40), 68 ILI9805_INSTR(0, 0xF3, 0x60, 0x83, 0x04), 69 ILI9805_INSTR(0, 0xFC, 0x04, 0x0F, 0x01), 70 ILI9805_INSTR(0, 0xEB, 0x08, 0x0F), 71 ILI9805_INSTR(0, 0xe0, 0x00, 0x08, 0x0d, 0x0e, 0x0e, 0x0d, 0x0a, 0x08, 0x04, 72 0x08, 0x0d, 0x0f, 0x0b, 0x1c, 0x14, 0x0a), 73 ILI9805_INSTR(0, 0xe1, 0x00, 0x08, 0x0d, 0x0e, 0x0e, 0x0d, 0x0a, 0x08, 0x04, 74 0x08, 0x0d, 0x0f, 0x0b, 0x1c, 0x14, 0x0a), 75 ILI9805_INSTR(10, 0xc1, 0x13, 0x39, 0x19, 0x06), 76 ILI9805_INSTR(10, 0xc7, 0xe5), 77 ILI9805_INSTR(10, 0xB1, 0x00, 0x12, 0x14), 78 ILI9805_INSTR(10, 0xB4, 0x02), 79 ILI9805_INSTR(0, 0xBB, 0x14, 0x55), 80 ILI9805_INSTR(0, MIPI_DCS_SET_ADDRESS_MODE, 0x08), 81 ILI9805_INSTR(0, MIPI_DCS_SET_PIXEL_FORMAT, 0x77), 82 ILI9805_INSTR(0, 0x20), 83 ILI9805_INSTR(0, 0xB0, 0x01), 84 ILI9805_INSTR(0, 0xB6, 0x31, 0x00, 0xef), 85 ILI9805_INSTR(0, 0xDF, 0x23), 86 ILI9805_INSTR(0, 0xB9, 0x02, 0x00), 87 }; 88 89 static const struct ili9805_instr tm041xdhg01_init[] = { 90 ILI9805_INSTR(100, ILI9805_EXTCMD_CMD_SET_ENABLE_REG, ILI9805_SETEXTC_PARAMETER1, 91 ILI9805_SETEXTC_PARAMETER2, ILI9805_SETEXTC_PARAMETER3), 92 ILI9805_INSTR(100, 0xFD, 0x0F, 0x13, 0x44, 0x00), 93 ILI9805_INSTR(0, 0xf8, 0x18, 0x02, 0x02, 0x18, 0x02, 0x02, 0x30, 0x01, 94 0x01, 0x30, 0x01, 0x01, 0x30, 0x01, 0x01), 95 ILI9805_INSTR(0, 0xB8, 0x74), 96 ILI9805_INSTR(0, 0xF1, 0x00), 97 ILI9805_INSTR(0, 0xF2, 0x00, 0x58, 0x40), 98 ILI9805_INSTR(0, 0xFC, 0x04, 0x0F, 0x01), 99 ILI9805_INSTR(0, 0xEB, 0x08, 0x0F), 100 ILI9805_INSTR(0, 0xe0, 0x01, 0x0d, 0x15, 0x0e, 0x0f, 0x0f, 0x0b, 0x08, 0x04, 101 0x07, 0x0a, 0x0d, 0x0c, 0x15, 0x0f, 0x08), 102 ILI9805_INSTR(0, 0xe1, 0x01, 0x0d, 0x15, 0x0e, 0x0f, 0x0f, 0x0b, 0x08, 0x04, 103 0x07, 0x0a, 0x0d, 0x0c, 0x15, 0x0f, 0x08), 104 ILI9805_INSTR(10, 0xc1, 0x15, 0x03, 0x03, 0x31), 105 ILI9805_INSTR(10, 0xB1, 0x00, 0x12, 0x14), 106 ILI9805_INSTR(10, 0xB4, 0x02), 107 ILI9805_INSTR(0, 0xBB, 0x14, 0x55), 108 ILI9805_INSTR(0, MIPI_DCS_SET_ADDRESS_MODE, 0x0a), 109 ILI9805_INSTR(0, MIPI_DCS_SET_PIXEL_FORMAT, 0x77), 110 ILI9805_INSTR(0, 0x20), 111 ILI9805_INSTR(0, 0xB0, 0x00), 112 ILI9805_INSTR(0, 0xB6, 0x01), 113 ILI9805_INSTR(0, 0xc2, 0x11), 114 ILI9805_INSTR(0, 0x51, 0xFF), 115 ILI9805_INSTR(0, 0x53, 0x24), 116 ILI9805_INSTR(0, 0x55, 0x00), 117 }; 118 119 static inline struct ili9805 *panel_to_ili9805(struct drm_panel *panel) 120 { 121 return container_of(panel, struct ili9805, panel); 122 } 123 124 static int ili9805_power_on(struct ili9805 *ctx) 125 { 126 struct mipi_dsi_device *dsi = ctx->dsi; 127 struct device *dev = &dsi->dev; 128 int ret; 129 130 ret = regulator_enable(ctx->avdd); 131 if (ret) { 132 dev_err(dev, "Failed to enable avdd regulator (%d)\n", ret); 133 return ret; 134 } 135 136 ret = regulator_enable(ctx->dvdd); 137 if (ret) { 138 dev_err(dev, "Failed to enable dvdd regulator (%d)\n", ret); 139 regulator_disable(ctx->avdd); 140 return ret; 141 } 142 143 gpiod_set_value(ctx->reset_gpio, 0); 144 usleep_range(5000, 10000); 145 gpiod_set_value(ctx->reset_gpio, 1); 146 msleep(120); 147 148 return 0; 149 } 150 151 static int ili9805_power_off(struct ili9805 *ctx) 152 { 153 gpiod_set_value(ctx->reset_gpio, 0); 154 regulator_disable(ctx->dvdd); 155 regulator_disable(ctx->avdd); 156 157 return 0; 158 } 159 160 static int ili9805_activate(struct ili9805 *ctx) 161 { 162 struct mipi_dsi_device *dsi = ctx->dsi; 163 struct device *dev = &dsi->dev; 164 int i, ret; 165 166 for (i = 0; i < ctx->desc->init_length; i++) { 167 const struct ili9805_instr *instr = &ctx->desc->init[i]; 168 169 ret = mipi_dsi_dcs_write_buffer(ctx->dsi, instr->data, instr->len); 170 if (ret < 0) 171 return ret; 172 173 if (instr->delay > 0) 174 msleep(instr->delay); 175 } 176 177 ret = mipi_dsi_dcs_exit_sleep_mode(ctx->dsi); 178 if (ret) { 179 dev_err(dev, "Failed to exit sleep mode (%d)\n", ret); 180 return ret; 181 } 182 183 usleep_range(5000, 6000); 184 185 ret = mipi_dsi_dcs_set_display_on(ctx->dsi); 186 if (ret) { 187 dev_err(dev, "Failed to set display ON (%d)\n", ret); 188 return ret; 189 } 190 191 return 0; 192 } 193 194 static int ili9805_prepare(struct drm_panel *panel) 195 { 196 struct ili9805 *ctx = panel_to_ili9805(panel); 197 int ret; 198 199 ret = ili9805_power_on(ctx); 200 if (ret) 201 return ret; 202 203 ret = ili9805_activate(ctx); 204 if (ret) { 205 ili9805_power_off(ctx); 206 return ret; 207 } 208 209 return 0; 210 } 211 212 static int ili9805_deactivate(struct ili9805 *ctx) 213 { 214 struct mipi_dsi_device *dsi = ctx->dsi; 215 struct device *dev = &dsi->dev; 216 int ret; 217 218 ret = mipi_dsi_dcs_set_display_off(ctx->dsi); 219 if (ret < 0) { 220 dev_err(dev, "Failed to set display OFF (%d)\n", ret); 221 return ret; 222 } 223 224 usleep_range(5000, 10000); 225 226 ret = mipi_dsi_dcs_enter_sleep_mode(ctx->dsi); 227 if (ret < 0) { 228 dev_err(dev, "Failed to enter sleep mode (%d)\n", ret); 229 return ret; 230 } 231 232 return 0; 233 } 234 235 static int ili9805_unprepare(struct drm_panel *panel) 236 { 237 struct ili9805 *ctx = panel_to_ili9805(panel); 238 239 ili9805_deactivate(ctx); 240 ili9805_power_off(ctx); 241 242 return 0; 243 } 244 245 static const struct drm_display_mode gpm1780a0_timing = { 246 .clock = 26227, 247 248 .hdisplay = 480, 249 .hsync_start = 480 + 10, 250 .hsync_end = 480 + 10 + 2, 251 .htotal = 480 + 10 + 2 + 36, 252 253 .vdisplay = 480, 254 .vsync_start = 480 + 2, 255 .vsync_end = 480 + 10 + 4, 256 .vtotal = 480 + 2 + 4 + 10, 257 }; 258 259 static const struct drm_display_mode tm041xdhg01_timing = { 260 .clock = 26227, 261 262 .hdisplay = 480, 263 .hsync_start = 480 + 10, 264 .hsync_end = 480 + 10 + 2, 265 .htotal = 480 + 10 + 2 + 36, 266 267 .vdisplay = 768, 268 .vsync_start = 768 + 2, 269 .vsync_end = 768 + 10 + 4, 270 .vtotal = 768 + 2 + 4 + 10, 271 }; 272 273 static int ili9805_get_modes(struct drm_panel *panel, 274 struct drm_connector *connector) 275 { 276 struct ili9805 *ctx = panel_to_ili9805(panel); 277 struct drm_display_mode *mode; 278 279 mode = drm_mode_duplicate(connector->dev, ctx->desc->mode); 280 if (!mode) { 281 dev_err(&ctx->dsi->dev, "failed to add mode %ux%ux@%u\n", 282 ctx->desc->mode->hdisplay, 283 ctx->desc->mode->vdisplay, 284 drm_mode_vrefresh(ctx->desc->mode)); 285 return -ENOMEM; 286 } 287 288 drm_mode_set_name(mode); 289 290 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 291 drm_mode_probed_add(connector, mode); 292 293 connector->display_info.width_mm = mode->width_mm; 294 connector->display_info.height_mm = mode->height_mm; 295 296 return 1; 297 } 298 299 static const struct drm_panel_funcs ili9805_funcs = { 300 .prepare = ili9805_prepare, 301 .unprepare = ili9805_unprepare, 302 .get_modes = ili9805_get_modes, 303 }; 304 305 static int ili9805_dsi_probe(struct mipi_dsi_device *dsi) 306 { 307 struct ili9805 *ctx; 308 int ret; 309 310 ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL); 311 if (!ctx) 312 return -ENOMEM; 313 mipi_dsi_set_drvdata(dsi, ctx); 314 ctx->dsi = dsi; 315 ctx->desc = of_device_get_match_data(&dsi->dev); 316 317 dsi->format = MIPI_DSI_FMT_RGB888; 318 dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | 319 MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM | 320 MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_NO_EOT_PACKET; 321 dsi->lanes = 2; 322 323 drm_panel_init(&ctx->panel, &dsi->dev, &ili9805_funcs, 324 DRM_MODE_CONNECTOR_DSI); 325 326 ctx->dvdd = devm_regulator_get(&dsi->dev, "dvdd"); 327 if (IS_ERR(ctx->dvdd)) 328 return PTR_ERR(ctx->dvdd); 329 ctx->avdd = devm_regulator_get(&dsi->dev, "avdd"); 330 if (IS_ERR(ctx->avdd)) 331 return PTR_ERR(ctx->avdd); 332 333 ctx->reset_gpio = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW); 334 if (IS_ERR(ctx->reset_gpio)) { 335 dev_err(&dsi->dev, "Couldn't get our reset GPIO\n"); 336 return PTR_ERR(ctx->reset_gpio); 337 } 338 339 ctx->panel.prepare_prev_first = true; 340 ret = drm_panel_of_backlight(&ctx->panel); 341 if (ret) 342 return ret; 343 344 drm_panel_add(&ctx->panel); 345 346 ret = mipi_dsi_attach(dsi); 347 if (ret < 0) { 348 dev_err(&dsi->dev, "mipi_dsi_attach failed: %d\n", ret); 349 drm_panel_remove(&ctx->panel); 350 return ret; 351 } 352 353 return 0; 354 } 355 356 static void ili9805_dsi_remove(struct mipi_dsi_device *dsi) 357 { 358 struct ili9805 *ctx = mipi_dsi_get_drvdata(dsi); 359 int ret; 360 361 ret = mipi_dsi_detach(dsi); 362 if (ret < 0) 363 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", 364 ret); 365 366 drm_panel_remove(&ctx->panel); 367 } 368 369 static const struct ili9805_desc gpm1780a0_desc = { 370 .init = gpm1780a0_init, 371 .init_length = ARRAY_SIZE(gpm1780a0_init), 372 .mode = &gpm1780a0_timing, 373 .width_mm = 65, 374 .height_mm = 65, 375 }; 376 377 static const struct ili9805_desc tm041xdhg01_desc = { 378 .init = tm041xdhg01_init, 379 .init_length = ARRAY_SIZE(tm041xdhg01_init), 380 .mode = &tm041xdhg01_timing, 381 .width_mm = 42, 382 .height_mm = 96, 383 }; 384 385 static const struct of_device_id ili9805_of_match[] = { 386 { .compatible = "giantplus,gpm1790a0", .data = &gpm1780a0_desc }, 387 { .compatible = "tianma,tm041xdhg01", .data = &tm041xdhg01_desc }, 388 { } 389 }; 390 MODULE_DEVICE_TABLE(of, ili9805_of_match); 391 392 static struct mipi_dsi_driver ili9805_dsi_driver = { 393 .probe = ili9805_dsi_probe, 394 .remove = ili9805_dsi_remove, 395 .driver = { 396 .name = "ili9805-dsi", 397 .of_match_table = ili9805_of_match, 398 }, 399 }; 400 module_mipi_dsi_driver(ili9805_dsi_driver); 401 402 MODULE_AUTHOR("Matthias Proske <Matthias.Proske@bshg.com>"); 403 MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>"); 404 MODULE_DESCRIPTION("Ilitek ILI9805 Controller Driver"); 405 MODULE_LICENSE("GPL"); 406