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 struct ili9805_desc { 29 void (*init)(struct mipi_dsi_multi_context *ctx); 30 const struct drm_display_mode *mode; 31 u32 width_mm; 32 u32 height_mm; 33 }; 34 35 struct ili9805 { 36 struct drm_panel panel; 37 struct mipi_dsi_device *dsi; 38 const struct ili9805_desc *desc; 39 40 struct regulator *dvdd; 41 struct regulator *avdd; 42 struct gpio_desc *reset_gpio; 43 }; 44 45 static void gpm1780a0_init(struct mipi_dsi_multi_context *ctx) 46 { 47 mipi_dsi_dcs_write_seq_multi(ctx, ILI9805_EXTCMD_CMD_SET_ENABLE_REG, 48 ILI9805_SETEXTC_PARAMETER1, ILI9805_SETEXTC_PARAMETER2, 49 ILI9805_SETEXTC_PARAMETER3); 50 mipi_dsi_msleep(ctx, 100); 51 mipi_dsi_dcs_write_seq_multi(ctx, 0xfd, 0x0f, 0x10, 0x44, 0x00); 52 mipi_dsi_msleep(ctx, 100); 53 mipi_dsi_dcs_write_seq_multi(ctx, 0xf8, 0x18, 0x02, 0x02, 0x18, 0x02, 0x02, 0x30, 0x00, 54 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00); 55 mipi_dsi_dcs_write_seq_multi(ctx, 0xb8, 0x62); 56 mipi_dsi_dcs_write_seq_multi(ctx, 0xf1, 0x00); 57 mipi_dsi_dcs_write_seq_multi(ctx, 0xf2, 0x00, 0x58, 0x40); 58 mipi_dsi_dcs_write_seq_multi(ctx, 0xf3, 0x60, 0x83, 0x04); 59 mipi_dsi_dcs_write_seq_multi(ctx, 0xfc, 0x04, 0x0f, 0x01); 60 mipi_dsi_dcs_write_seq_multi(ctx, 0xeb, 0x08, 0x0f); 61 mipi_dsi_dcs_write_seq_multi(ctx, 0xe0, 0x00, 0x08, 0x0d, 0x0e, 0x0e, 0x0d, 0x0a, 0x08, 62 0x04, 0x08, 0x0d, 0x0f, 0x0b, 0x1c, 0x14, 0x0a); 63 mipi_dsi_dcs_write_seq_multi(ctx, 0xe1, 0x00, 0x08, 0x0d, 0x0e, 0x0e, 0x0d, 0x0a, 0x08, 64 0x04, 0x08, 0x0d, 0x0f, 0x0b, 0x1c, 0x14, 0x0a); 65 mipi_dsi_dcs_write_seq_multi(ctx, 0xc1, 0x13, 0x39, 0x19, 0x06); 66 mipi_dsi_msleep(ctx, 10); 67 mipi_dsi_dcs_write_seq_multi(ctx, 0xc7, 0xe5); 68 mipi_dsi_msleep(ctx, 10); 69 mipi_dsi_dcs_write_seq_multi(ctx, 0xb1, 0x00, 0x12, 0x14); 70 mipi_dsi_msleep(ctx, 10); 71 mipi_dsi_dcs_write_seq_multi(ctx, 0xb4, 0x02); 72 mipi_dsi_msleep(ctx, 10); 73 mipi_dsi_dcs_write_seq_multi(ctx, 0xbb, 0x14, 0x55); 74 mipi_dsi_dcs_write_seq_multi(ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x08); 75 mipi_dsi_dcs_set_pixel_format_multi(ctx, 0x77); 76 mipi_dsi_dcs_write_seq_multi(ctx, 0x20); 77 mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x01); 78 mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x31, 0x00, 0xef); 79 mipi_dsi_dcs_write_seq_multi(ctx, 0xdf, 0x23); 80 mipi_dsi_dcs_write_seq_multi(ctx, 0xb9, 0x02, 0x00); 81 } 82 83 static void tm041xdhg01_init(struct mipi_dsi_multi_context *ctx) 84 { 85 mipi_dsi_dcs_write_seq_multi(ctx, ILI9805_EXTCMD_CMD_SET_ENABLE_REG, 86 ILI9805_SETEXTC_PARAMETER1, ILI9805_SETEXTC_PARAMETER2, 87 ILI9805_SETEXTC_PARAMETER3); 88 mipi_dsi_msleep(ctx, 100); 89 mipi_dsi_dcs_write_seq_multi(ctx, 0xfd, 0x0f, 0x13, 0x44, 0x00); 90 mipi_dsi_msleep(ctx, 100); 91 mipi_dsi_dcs_write_seq_multi(ctx, 0xf8, 0x18, 0x02, 0x02, 0x18, 0x02, 0x02, 0x30, 0x01, 92 0x01, 0x30, 0x01, 0x01, 0x30, 0x01, 0x01); 93 mipi_dsi_dcs_write_seq_multi(ctx, 0xb8, 0x74); 94 mipi_dsi_dcs_write_seq_multi(ctx, 0xf1, 0x00); 95 mipi_dsi_dcs_write_seq_multi(ctx, 0xf2, 0x00, 0x58, 0x40); 96 mipi_dsi_dcs_write_seq_multi(ctx, 0xfc, 0x04, 0x0f, 0x01); 97 mipi_dsi_dcs_write_seq_multi(ctx, 0xeb, 0x08, 0x0f); 98 mipi_dsi_dcs_write_seq_multi(ctx, 0xe0, 0x01, 0x0d, 0x15, 0x0e, 0x0f, 0x0f, 0x0b, 0x08, 99 0x04, 0x07, 0x0a, 0x0d, 0x0c, 0x15, 0x0f, 0x08); 100 mipi_dsi_dcs_write_seq_multi(ctx, 0xe1, 0x01, 0x0d, 0x15, 0x0e, 0x0f, 0x0f, 0x0b, 0x08, 101 0x04, 0x07, 0x0a, 0x0d, 0x0c, 0x15, 0x0f, 0x08); 102 mipi_dsi_dcs_write_seq_multi(ctx, 0xc1, 0x15, 0x03, 0x03, 0x31); 103 mipi_dsi_msleep(ctx, 10); 104 mipi_dsi_dcs_write_seq_multi(ctx, 0xb1, 0x00, 0x12, 0x14); 105 mipi_dsi_msleep(ctx, 10); 106 mipi_dsi_dcs_write_seq_multi(ctx, 0xb4, 0x02); 107 mipi_dsi_msleep(ctx, 10); 108 mipi_dsi_dcs_write_seq_multi(ctx, 0xbb, 0x14, 0x55); 109 mipi_dsi_dcs_write_seq_multi(ctx, MIPI_DCS_SET_ADDRESS_MODE, 0x0a); 110 mipi_dsi_dcs_set_pixel_format_multi(ctx, 0x77); 111 mipi_dsi_dcs_write_seq_multi(ctx, 0x20); 112 mipi_dsi_dcs_write_seq_multi(ctx, 0xb0, 0x00); 113 mipi_dsi_dcs_write_seq_multi(ctx, 0xb6, 0x01); 114 mipi_dsi_dcs_write_seq_multi(ctx, 0xc2, 0x11); 115 mipi_dsi_dcs_write_seq_multi(ctx, 0x51, 0xff); 116 mipi_dsi_dcs_write_seq_multi(ctx, 0x53, 0x24); 117 mipi_dsi_dcs_write_seq_multi(ctx, 0x55, 0x00); 118 } 119 120 static inline struct ili9805 *panel_to_ili9805(struct drm_panel *panel) 121 { 122 return container_of(panel, struct ili9805, panel); 123 } 124 125 static int ili9805_power_on(struct ili9805 *ctx) 126 { 127 struct mipi_dsi_device *dsi = ctx->dsi; 128 struct device *dev = &dsi->dev; 129 int ret; 130 131 ret = regulator_enable(ctx->avdd); 132 if (ret) { 133 dev_err(dev, "Failed to enable avdd regulator (%d)\n", ret); 134 return ret; 135 } 136 137 ret = regulator_enable(ctx->dvdd); 138 if (ret) { 139 dev_err(dev, "Failed to enable dvdd regulator (%d)\n", ret); 140 regulator_disable(ctx->avdd); 141 return ret; 142 } 143 144 gpiod_set_value(ctx->reset_gpio, 0); 145 usleep_range(5000, 10000); 146 gpiod_set_value(ctx->reset_gpio, 1); 147 msleep(120); 148 149 return 0; 150 } 151 152 static void ili9805_power_off(struct ili9805 *ctx) 153 { 154 gpiod_set_value(ctx->reset_gpio, 0); 155 regulator_disable(ctx->dvdd); 156 regulator_disable(ctx->avdd); 157 } 158 159 static int ili9805_activate(struct ili9805 *ctx) 160 { 161 struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; 162 163 ctx->desc->init(&dsi_ctx); 164 165 mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); 166 mipi_dsi_usleep_range(&dsi_ctx, 5000, 6000); 167 mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); 168 169 return dsi_ctx.accum_err; 170 } 171 172 static int ili9805_prepare(struct drm_panel *panel) 173 { 174 struct ili9805 *ctx = panel_to_ili9805(panel); 175 int ret; 176 177 ret = ili9805_power_on(ctx); 178 if (ret) 179 return ret; 180 181 ret = ili9805_activate(ctx); 182 if (ret) { 183 ili9805_power_off(ctx); 184 return ret; 185 } 186 187 return 0; 188 } 189 190 static void ili9805_deactivate(struct ili9805 *ctx) 191 { 192 struct mipi_dsi_multi_context dsi_ctx = { .dsi = ctx->dsi }; 193 194 mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); 195 mipi_dsi_usleep_range(&dsi_ctx, 5000, 10000); 196 mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); 197 } 198 199 static int ili9805_unprepare(struct drm_panel *panel) 200 { 201 struct ili9805 *ctx = panel_to_ili9805(panel); 202 203 ili9805_deactivate(ctx); 204 ili9805_power_off(ctx); 205 206 return 0; 207 } 208 209 static const struct drm_display_mode gpm1780a0_timing = { 210 .clock = 26227, 211 212 .hdisplay = 480, 213 .hsync_start = 480 + 10, 214 .hsync_end = 480 + 10 + 2, 215 .htotal = 480 + 10 + 2 + 36, 216 217 .vdisplay = 480, 218 .vsync_start = 480 + 2, 219 .vsync_end = 480 + 10 + 4, 220 .vtotal = 480 + 2 + 4 + 10, 221 }; 222 223 static const struct drm_display_mode tm041xdhg01_timing = { 224 .clock = 26227, 225 226 .hdisplay = 480, 227 .hsync_start = 480 + 10, 228 .hsync_end = 480 + 10 + 2, 229 .htotal = 480 + 10 + 2 + 36, 230 231 .vdisplay = 768, 232 .vsync_start = 768 + 2, 233 .vsync_end = 768 + 10 + 4, 234 .vtotal = 768 + 2 + 4 + 10, 235 }; 236 237 static int ili9805_get_modes(struct drm_panel *panel, 238 struct drm_connector *connector) 239 { 240 struct ili9805 *ctx = panel_to_ili9805(panel); 241 struct drm_display_mode *mode; 242 243 mode = drm_mode_duplicate(connector->dev, ctx->desc->mode); 244 if (!mode) { 245 dev_err(&ctx->dsi->dev, "failed to add mode %ux%ux@%u\n", 246 ctx->desc->mode->hdisplay, 247 ctx->desc->mode->vdisplay, 248 drm_mode_vrefresh(ctx->desc->mode)); 249 return -ENOMEM; 250 } 251 252 drm_mode_set_name(mode); 253 254 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 255 drm_mode_probed_add(connector, mode); 256 257 connector->display_info.width_mm = mode->width_mm; 258 connector->display_info.height_mm = mode->height_mm; 259 260 return 1; 261 } 262 263 static const struct drm_panel_funcs ili9805_funcs = { 264 .prepare = ili9805_prepare, 265 .unprepare = ili9805_unprepare, 266 .get_modes = ili9805_get_modes, 267 }; 268 269 static int ili9805_dsi_probe(struct mipi_dsi_device *dsi) 270 { 271 struct ili9805 *ctx; 272 int ret; 273 274 ctx = devm_drm_panel_alloc(&dsi->dev, struct ili9805, panel, 275 &ili9805_funcs, 276 DRM_MODE_CONNECTOR_DSI); 277 if (IS_ERR(ctx)) 278 return PTR_ERR(ctx); 279 280 mipi_dsi_set_drvdata(dsi, ctx); 281 ctx->dsi = dsi; 282 ctx->desc = of_device_get_match_data(&dsi->dev); 283 284 dsi->format = MIPI_DSI_FMT_RGB888; 285 dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | 286 MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM | 287 MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_NO_EOT_PACKET; 288 dsi->lanes = 2; 289 290 ctx->dvdd = devm_regulator_get(&dsi->dev, "dvdd"); 291 if (IS_ERR(ctx->dvdd)) 292 return PTR_ERR(ctx->dvdd); 293 ctx->avdd = devm_regulator_get(&dsi->dev, "avdd"); 294 if (IS_ERR(ctx->avdd)) 295 return PTR_ERR(ctx->avdd); 296 297 ctx->reset_gpio = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW); 298 if (IS_ERR(ctx->reset_gpio)) { 299 dev_err(&dsi->dev, "Couldn't get our reset GPIO\n"); 300 return PTR_ERR(ctx->reset_gpio); 301 } 302 303 ctx->panel.prepare_prev_first = true; 304 ret = drm_panel_of_backlight(&ctx->panel); 305 if (ret) 306 return ret; 307 308 drm_panel_add(&ctx->panel); 309 310 ret = mipi_dsi_attach(dsi); 311 if (ret < 0) { 312 dev_err(&dsi->dev, "mipi_dsi_attach failed: %d\n", ret); 313 drm_panel_remove(&ctx->panel); 314 return ret; 315 } 316 317 return 0; 318 } 319 320 static void ili9805_dsi_remove(struct mipi_dsi_device *dsi) 321 { 322 struct ili9805 *ctx = mipi_dsi_get_drvdata(dsi); 323 int ret; 324 325 ret = mipi_dsi_detach(dsi); 326 if (ret < 0) 327 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", 328 ret); 329 330 drm_panel_remove(&ctx->panel); 331 } 332 333 static const struct ili9805_desc gpm1780a0_desc = { 334 .init = gpm1780a0_init, 335 .mode = &gpm1780a0_timing, 336 .width_mm = 65, 337 .height_mm = 65, 338 }; 339 340 static const struct ili9805_desc tm041xdhg01_desc = { 341 .init = tm041xdhg01_init, 342 .mode = &tm041xdhg01_timing, 343 .width_mm = 42, 344 .height_mm = 96, 345 }; 346 347 static const struct of_device_id ili9805_of_match[] = { 348 { .compatible = "giantplus,gpm1790a0", .data = &gpm1780a0_desc }, 349 { .compatible = "tianma,tm041xdhg01", .data = &tm041xdhg01_desc }, 350 { } 351 }; 352 MODULE_DEVICE_TABLE(of, ili9805_of_match); 353 354 static struct mipi_dsi_driver ili9805_dsi_driver = { 355 .probe = ili9805_dsi_probe, 356 .remove = ili9805_dsi_remove, 357 .driver = { 358 .name = "ili9805-dsi", 359 .of_match_table = ili9805_of_match, 360 }, 361 }; 362 module_mipi_dsi_driver(ili9805_dsi_driver); 363 364 MODULE_AUTHOR("Matthias Proske <Matthias.Proske@bshg.com>"); 365 MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>"); 366 MODULE_DESCRIPTION("Ilitek ILI9805 Controller Driver"); 367 MODULE_LICENSE("GPL"); 368