0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include <linux/bitops.h>
0022 #include <linux/delay.h>
0023 #include <linux/gpio/consumer.h>
0024 #include <linux/module.h>
0025 #include <linux/of_device.h>
0026 #include <linux/regulator/consumer.h>
0027 #include <linux/spi/spi.h>
0028
0029 #include <video/mipi_display.h>
0030
0031 #include <drm/drm_atomic_helper.h>
0032 #include <drm/drm_drv.h>
0033 #include <drm/drm_fb_helper.h>
0034 #include <drm/drm_gem_atomic_helper.h>
0035 #include <drm/drm_gem_cma_helper.h>
0036 #include <drm/drm_gem_framebuffer_helper.h>
0037 #include <drm/drm_mipi_dbi.h>
0038 #include <drm/drm_modes.h>
0039 #include <drm/drm_panel.h>
0040 #include <drm/drm_print.h>
0041
0042 #define ILI9341_RGB_INTERFACE 0xb0
0043 #define ILI9341_FRC 0xb1
0044 #define ILI9341_DFC 0xb6
0045 #define ILI9341_POWER1 0xc0
0046 #define ILI9341_POWER2 0xc1
0047 #define ILI9341_VCOM1 0xc5
0048 #define ILI9341_VCOM2 0xc7
0049 #define ILI9341_POWERA 0xcb
0050 #define ILI9341_POWERB 0xcf
0051 #define ILI9341_PGAMMA 0xe0
0052 #define ILI9341_NGAMMA 0xe1
0053 #define ILI9341_DTCA 0xe8
0054 #define ILI9341_DTCB 0xea
0055 #define ILI9341_POWER_SEQ 0xed
0056 #define ILI9341_3GAMMA_EN 0xf2
0057 #define ILI9341_INTERFACE 0xf6
0058 #define ILI9341_PRC 0xf7
0059 #define ILI9341_ETMOD 0xb7
0060
0061 #define ILI9341_MADCTL_BGR BIT(3)
0062 #define ILI9341_MADCTL_MV BIT(5)
0063 #define ILI9341_MADCTL_MX BIT(6)
0064 #define ILI9341_MADCTL_MY BIT(7)
0065
0066 #define ILI9341_POWER_B_LEN 3
0067 #define ILI9341_POWER_SEQ_LEN 4
0068 #define ILI9341_DTCA_LEN 3
0069 #define ILI9341_DTCB_LEN 2
0070 #define ILI9341_POWER_A_LEN 5
0071 #define ILI9341_DFC_1_LEN 2
0072 #define ILI9341_FRC_LEN 2
0073 #define ILI9341_VCOM_1_LEN 2
0074 #define ILI9341_DFC_2_LEN 4
0075 #define ILI9341_COLUMN_ADDR_LEN 4
0076 #define ILI9341_PAGE_ADDR_LEN 4
0077 #define ILI9341_INTERFACE_LEN 3
0078 #define ILI9341_PGAMMA_LEN 15
0079 #define ILI9341_NGAMMA_LEN 15
0080 #define ILI9341_CA_LEN 3
0081
0082 #define ILI9341_PIXEL_DPI_16_BITS (BIT(6) | BIT(4))
0083 #define ILI9341_PIXEL_DPI_18_BITS (BIT(6) | BIT(5))
0084 #define ILI9341_GAMMA_CURVE_1 BIT(0)
0085 #define ILI9341_IF_WE_MODE BIT(0)
0086 #define ILI9341_IF_BIG_ENDIAN 0x00
0087 #define ILI9341_IF_DM_RGB BIT(2)
0088 #define ILI9341_IF_DM_INTERNAL 0x00
0089 #define ILI9341_IF_DM_VSYNC BIT(3)
0090 #define ILI9341_IF_RM_RGB BIT(1)
0091 #define ILI9341_IF_RIM_RGB 0x00
0092
0093 #define ILI9341_COLUMN_ADDR 0x00ef
0094 #define ILI9341_PAGE_ADDR 0x013f
0095
0096 #define ILI9341_RGB_EPL BIT(0)
0097 #define ILI9341_RGB_DPL BIT(1)
0098 #define ILI9341_RGB_HSPL BIT(2)
0099 #define ILI9341_RGB_VSPL BIT(3)
0100 #define ILI9341_RGB_DE_MODE BIT(6)
0101 #define ILI9341_RGB_DISP_PATH_MEM BIT(7)
0102
0103 #define ILI9341_DBI_VCOMH_4P6V 0x23
0104 #define ILI9341_DBI_PWR_2_DEFAULT 0x10
0105 #define ILI9341_DBI_PRC_NORMAL 0x20
0106 #define ILI9341_DBI_VCOM_1_VMH_4P25V 0x3e
0107 #define ILI9341_DBI_VCOM_1_VML_1P5V 0x28
0108 #define ILI9341_DBI_VCOM_2_DEC_58 0x86
0109 #define ILI9341_DBI_FRC_DIVA 0x00
0110 #define ILI9341_DBI_FRC_RTNA 0x1b
0111 #define ILI9341_DBI_EMS_GAS BIT(0)
0112 #define ILI9341_DBI_EMS_DTS BIT(1)
0113 #define ILI9341_DBI_EMS_GON BIT(2)
0114
0115
0116 struct ili9341_config {
0117 u32 max_spi_speed;
0118
0119 const struct drm_display_mode mode;
0120
0121 u8 ca[ILI9341_CA_LEN];
0122
0123 u8 power_b[ILI9341_POWER_B_LEN];
0124
0125 u8 power_seq[ILI9341_POWER_SEQ_LEN];
0126
0127 u8 dtca[ILI9341_DTCA_LEN];
0128
0129 u8 dtcb[ILI9341_DTCB_LEN];
0130
0131 u8 power_a[ILI9341_POWER_A_LEN];
0132
0133 u8 frc[ILI9341_FRC_LEN];
0134
0135 u8 prc;
0136
0137 u8 dfc_1[ILI9341_DFC_1_LEN];
0138
0139 u8 power_1;
0140
0141 u8 power_2;
0142
0143 u8 vcom_1[ILI9341_VCOM_1_LEN];
0144
0145 u8 vcom_2;
0146
0147 u8 address_mode;
0148
0149 u8 g3amma_en;
0150
0151 u8 rgb_interface;
0152
0153 u8 dfc_2[ILI9341_DFC_2_LEN];
0154
0155 u8 column_addr[ILI9341_COLUMN_ADDR_LEN];
0156
0157 u8 page_addr[ILI9341_PAGE_ADDR_LEN];
0158
0159 u8 interface[ILI9341_INTERFACE_LEN];
0160
0161
0162
0163
0164 u8 pixel_format;
0165
0166
0167
0168
0169 u8 gamma_curve;
0170
0171 u8 pgamma[ILI9341_PGAMMA_LEN];
0172
0173 u8 ngamma[ILI9341_NGAMMA_LEN];
0174 };
0175
0176 struct ili9341 {
0177 struct device *dev;
0178 const struct ili9341_config *conf;
0179 struct drm_panel panel;
0180 struct gpio_desc *reset_gpio;
0181 struct gpio_desc *dc_gpio;
0182 struct mipi_dbi *dbi;
0183 u32 max_spi_speed;
0184 struct regulator_bulk_data supplies[3];
0185 };
0186
0187
0188
0189
0190 static const struct ili9341_config ili9341_stm32f429_disco_data = {
0191 .max_spi_speed = 10000000,
0192 .mode = {
0193 .clock = 6100,
0194 .hdisplay = 240,
0195 .hsync_start = 240 + 10,
0196 .hsync_end = 240 + 10 + 10,
0197 .htotal = 240 + 10 + 10 + 20,
0198 .vdisplay = 320,
0199 .vsync_start = 320 + 4,
0200 .vsync_end = 320 + 4 + 2,
0201 .vtotal = 320 + 4 + 2 + 2,
0202 .flags = 0,
0203 .width_mm = 65,
0204 .height_mm = 50,
0205 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
0206 },
0207 .ca = {0xc3, 0x08, 0x50},
0208 .power_b = {0x00, 0xc1, 0x30},
0209 .power_seq = {0x64, 0x03, 0x12, 0x81},
0210 .dtca = {0x85, 0x00, 0x78},
0211 .power_a = {0x39, 0x2c, 0x00, 0x34, 0x02},
0212 .prc = 0x20,
0213 .dtcb = {0x00, 0x00},
0214
0215 .frc = {0x00, 0x1b},
0216
0217
0218
0219
0220
0221 .dfc_1 = {0x0a, 0xa2},
0222
0223 .power_1 = 0x10,
0224
0225 .power_2 = 0x10,
0226
0227 .vcom_1 = {0x45, 0x15},
0228
0229 .vcom_2 = 0x90,
0230
0231
0232
0233
0234 .address_mode = 0xc8,
0235 .g3amma_en = 0x00,
0236
0237
0238
0239
0240
0241
0242 .rgb_interface = ILI9341_RGB_DISP_PATH_MEM |
0243 ILI9341_RGB_DE_MODE |
0244 ILI9341_RGB_DPL,
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264 .dfc_2 = {0x0a, 0xa7, 0x27, 0x04},
0265
0266 .column_addr = {0x00, 0x00, (ILI9341_COLUMN_ADDR >> 4) & 0xff,
0267 ILI9341_COLUMN_ADDR & 0xff},
0268
0269 .page_addr = {0x00, 0x00, (ILI9341_PAGE_ADDR >> 4) & 0xff,
0270 ILI9341_PAGE_ADDR & 0xff},
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280 .interface = {ILI9341_IF_WE_MODE, 0x00,
0281 ILI9341_IF_DM_RGB | ILI9341_IF_RM_RGB},
0282
0283 .pixel_format = ILI9341_PIXEL_DPI_16_BITS,
0284
0285 .gamma_curve = ILI9341_GAMMA_CURVE_1,
0286 .pgamma = {0x0f, 0x29, 0x24, 0x0c, 0x0e,
0287 0x09, 0x4e, 0x78, 0x3c, 0x09,
0288 0x13, 0x05, 0x17, 0x11, 0x00},
0289 .ngamma = {0x00, 0x16, 0x1b, 0x04, 0x11,
0290 0x07, 0x31, 0x33, 0x42, 0x05,
0291 0x0c, 0x0a, 0x28, 0x2f, 0x0f},
0292 };
0293
0294 static inline struct ili9341 *panel_to_ili9341(struct drm_panel *panel)
0295 {
0296 return container_of(panel, struct ili9341, panel);
0297 }
0298
0299 static void ili9341_dpi_init(struct ili9341 *ili)
0300 {
0301 struct device *dev = (&ili->panel)->dev;
0302 struct mipi_dbi *dbi = ili->dbi;
0303 struct ili9341_config *cfg = (struct ili9341_config *)ili->conf;
0304
0305
0306 mipi_dbi_command_stackbuf(dbi, 0xca, cfg->ca, ILI9341_CA_LEN);
0307 mipi_dbi_command_stackbuf(dbi, ILI9341_POWERB, cfg->power_b,
0308 ILI9341_POWER_B_LEN);
0309 mipi_dbi_command_stackbuf(dbi, ILI9341_POWER_SEQ, cfg->power_seq,
0310 ILI9341_POWER_SEQ_LEN);
0311 mipi_dbi_command_stackbuf(dbi, ILI9341_DTCA, cfg->dtca,
0312 ILI9341_DTCA_LEN);
0313 mipi_dbi_command_stackbuf(dbi, ILI9341_POWERA, cfg->power_a,
0314 ILI9341_POWER_A_LEN);
0315 mipi_dbi_command(ili->dbi, ILI9341_PRC, cfg->prc);
0316 mipi_dbi_command_stackbuf(dbi, ILI9341_DTCB, cfg->dtcb,
0317 ILI9341_DTCB_LEN);
0318 mipi_dbi_command_stackbuf(dbi, ILI9341_FRC, cfg->frc, ILI9341_FRC_LEN);
0319 mipi_dbi_command_stackbuf(dbi, ILI9341_DFC, cfg->dfc_1,
0320 ILI9341_DFC_1_LEN);
0321 mipi_dbi_command(dbi, ILI9341_POWER1, cfg->power_1);
0322 mipi_dbi_command(dbi, ILI9341_POWER2, cfg->power_2);
0323
0324
0325 mipi_dbi_command_stackbuf(dbi, ILI9341_VCOM1, cfg->vcom_1,
0326 ILI9341_VCOM_1_LEN);
0327 mipi_dbi_command(dbi, ILI9341_VCOM2, cfg->vcom_2);
0328 mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, cfg->address_mode);
0329
0330
0331 mipi_dbi_command(dbi, ILI9341_3GAMMA_EN, cfg->g3amma_en);
0332 mipi_dbi_command(dbi, ILI9341_RGB_INTERFACE, cfg->rgb_interface);
0333 mipi_dbi_command_stackbuf(dbi, ILI9341_DFC, cfg->dfc_2,
0334 ILI9341_DFC_2_LEN);
0335
0336
0337 mipi_dbi_command_stackbuf(dbi, MIPI_DCS_SET_COLUMN_ADDRESS,
0338 cfg->column_addr, ILI9341_COLUMN_ADDR_LEN);
0339
0340
0341 mipi_dbi_command_stackbuf(dbi, MIPI_DCS_SET_PAGE_ADDRESS,
0342 cfg->page_addr, ILI9341_PAGE_ADDR_LEN);
0343 mipi_dbi_command_stackbuf(dbi, ILI9341_INTERFACE, cfg->interface,
0344 ILI9341_INTERFACE_LEN);
0345
0346
0347 mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, cfg->pixel_format);
0348 mipi_dbi_command(dbi, MIPI_DCS_WRITE_MEMORY_START);
0349 msleep(200);
0350 mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, cfg->gamma_curve);
0351 mipi_dbi_command_stackbuf(dbi, ILI9341_PGAMMA, cfg->pgamma,
0352 ILI9341_PGAMMA_LEN);
0353 mipi_dbi_command_stackbuf(dbi, ILI9341_NGAMMA, cfg->ngamma,
0354 ILI9341_NGAMMA_LEN);
0355 mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
0356 msleep(200);
0357 mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
0358 mipi_dbi_command(dbi, MIPI_DCS_WRITE_MEMORY_START);
0359
0360 dev_info(dev, "Initialized display rgb interface\n");
0361 }
0362
0363 static int ili9341_dpi_power_on(struct ili9341 *ili)
0364 {
0365 struct device *dev = (&ili->panel)->dev;
0366 int ret = 0;
0367
0368
0369 gpiod_set_value(ili->reset_gpio, 1);
0370
0371
0372 ret = regulator_bulk_enable(ARRAY_SIZE(ili->supplies),
0373 ili->supplies);
0374 if (ret < 0) {
0375 dev_err(dev, "unable to enable vcc\n");
0376 return ret;
0377 }
0378 msleep(20);
0379
0380
0381 gpiod_set_value(ili->reset_gpio, 0);
0382 msleep(20);
0383
0384 return 0;
0385 }
0386
0387 static int ili9341_dpi_power_off(struct ili9341 *ili)
0388 {
0389
0390 gpiod_set_value(ili->reset_gpio, 1);
0391
0392
0393 return regulator_bulk_disable(ARRAY_SIZE(ili->supplies),
0394 ili->supplies);
0395 }
0396
0397 static int ili9341_dpi_disable(struct drm_panel *panel)
0398 {
0399 struct ili9341 *ili = panel_to_ili9341(panel);
0400
0401 mipi_dbi_command(ili->dbi, MIPI_DCS_SET_DISPLAY_OFF);
0402 return 0;
0403 }
0404
0405 static int ili9341_dpi_unprepare(struct drm_panel *panel)
0406 {
0407 struct ili9341 *ili = panel_to_ili9341(panel);
0408
0409 return ili9341_dpi_power_off(ili);
0410 }
0411
0412 static int ili9341_dpi_prepare(struct drm_panel *panel)
0413 {
0414 struct ili9341 *ili = panel_to_ili9341(panel);
0415 int ret;
0416
0417 ret = ili9341_dpi_power_on(ili);
0418 if (ret < 0)
0419 return ret;
0420
0421 ili9341_dpi_init(ili);
0422
0423 return ret;
0424 }
0425
0426 static int ili9341_dpi_enable(struct drm_panel *panel)
0427 {
0428 struct ili9341 *ili = panel_to_ili9341(panel);
0429
0430 mipi_dbi_command(ili->dbi, MIPI_DCS_SET_DISPLAY_ON);
0431 return 0;
0432 }
0433
0434 static int ili9341_dpi_get_modes(struct drm_panel *panel,
0435 struct drm_connector *connector)
0436 {
0437 struct ili9341 *ili = panel_to_ili9341(panel);
0438 struct drm_device *drm = connector->dev;
0439 struct drm_display_mode *mode;
0440 struct drm_display_info *info;
0441
0442 info = &connector->display_info;
0443 info->width_mm = ili->conf->mode.width_mm;
0444 info->height_mm = ili->conf->mode.height_mm;
0445
0446 if (ili->conf->rgb_interface & ILI9341_RGB_DPL)
0447 info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
0448 else
0449 info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
0450
0451 if (ili->conf->rgb_interface & ILI9341_RGB_EPL)
0452 info->bus_flags |= DRM_BUS_FLAG_DE_LOW;
0453 else
0454 info->bus_flags |= DRM_BUS_FLAG_DE_HIGH;
0455
0456 mode = drm_mode_duplicate(drm, &ili->conf->mode);
0457 if (!mode) {
0458 drm_err(drm, "bad mode or failed to add mode\n");
0459 return -EINVAL;
0460 }
0461 drm_mode_set_name(mode);
0462
0463
0464 if (ili->conf->rgb_interface & ILI9341_RGB_HSPL)
0465 mode->flags |= DRM_MODE_FLAG_PHSYNC;
0466 else
0467 mode->flags |= DRM_MODE_FLAG_NHSYNC;
0468
0469 if (ili->conf->rgb_interface & ILI9341_RGB_VSPL)
0470 mode->flags |= DRM_MODE_FLAG_PVSYNC;
0471 else
0472 mode->flags |= DRM_MODE_FLAG_NVSYNC;
0473
0474 drm_mode_probed_add(connector, mode);
0475
0476 return 1;
0477 }
0478
0479 static const struct drm_panel_funcs ili9341_dpi_funcs = {
0480 .disable = ili9341_dpi_disable,
0481 .unprepare = ili9341_dpi_unprepare,
0482 .prepare = ili9341_dpi_prepare,
0483 .enable = ili9341_dpi_enable,
0484 .get_modes = ili9341_dpi_get_modes,
0485 };
0486
0487 static void ili9341_dbi_enable(struct drm_simple_display_pipe *pipe,
0488 struct drm_crtc_state *crtc_state,
0489 struct drm_plane_state *plane_state)
0490 {
0491 struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
0492 struct mipi_dbi *dbi = &dbidev->dbi;
0493 u8 addr_mode;
0494 int ret, idx;
0495
0496 if (!drm_dev_enter(pipe->crtc.dev, &idx))
0497 return;
0498
0499 ret = mipi_dbi_poweron_conditional_reset(dbidev);
0500 if (ret < 0)
0501 goto out_exit;
0502 if (ret == 1)
0503 goto out_enable;
0504
0505 mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
0506
0507 mipi_dbi_command(dbi, ILI9341_POWERB, 0x00, 0xc1, 0x30);
0508 mipi_dbi_command(dbi, ILI9341_POWER_SEQ, 0x64, 0x03, 0x12, 0x81);
0509 mipi_dbi_command(dbi, ILI9341_DTCA, 0x85, 0x00, 0x78);
0510 mipi_dbi_command(dbi, ILI9341_POWERA, 0x39, 0x2c, 0x00, 0x34, 0x02);
0511 mipi_dbi_command(dbi, ILI9341_PRC, ILI9341_DBI_PRC_NORMAL);
0512 mipi_dbi_command(dbi, ILI9341_DTCB, 0x00, 0x00);
0513
0514
0515 mipi_dbi_command(dbi, ILI9341_POWER1, ILI9341_DBI_VCOMH_4P6V);
0516 mipi_dbi_command(dbi, ILI9341_POWER2, ILI9341_DBI_PWR_2_DEFAULT);
0517
0518 mipi_dbi_command(dbi, ILI9341_VCOM1, ILI9341_DBI_VCOM_1_VMH_4P25V,
0519 ILI9341_DBI_VCOM_1_VML_1P5V);
0520 mipi_dbi_command(dbi, ILI9341_VCOM2, ILI9341_DBI_VCOM_2_DEC_58);
0521
0522
0523 mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT,
0524 MIPI_DCS_PIXEL_FMT_16BIT);
0525
0526
0527 mipi_dbi_command(dbi, ILI9341_FRC, ILI9341_DBI_FRC_DIVA & 0x03,
0528 ILI9341_DBI_FRC_RTNA & 0x1f);
0529
0530
0531 mipi_dbi_command(dbi, ILI9341_3GAMMA_EN, 0x00);
0532 mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, ILI9341_GAMMA_CURVE_1);
0533 mipi_dbi_command(dbi, ILI9341_PGAMMA,
0534 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1,
0535 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00);
0536 mipi_dbi_command(dbi, ILI9341_NGAMMA,
0537 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1,
0538 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f);
0539
0540
0541 mipi_dbi_command(dbi, ILI9341_ETMOD, ILI9341_DBI_EMS_GAS |
0542 ILI9341_DBI_EMS_DTS |
0543 ILI9341_DBI_EMS_GON);
0544
0545
0546 mipi_dbi_command(dbi, ILI9341_DFC, 0x08, 0x82, 0x27, 0x00);
0547 mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
0548 msleep(100);
0549
0550 mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
0551 msleep(100);
0552
0553 out_enable:
0554 switch (dbidev->rotation) {
0555 default:
0556 addr_mode = ILI9341_MADCTL_MX;
0557 break;
0558 case 90:
0559 addr_mode = ILI9341_MADCTL_MV;
0560 break;
0561 case 180:
0562 addr_mode = ILI9341_MADCTL_MY;
0563 break;
0564 case 270:
0565 addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY |
0566 ILI9341_MADCTL_MX;
0567 break;
0568 }
0569
0570 addr_mode |= ILI9341_MADCTL_BGR;
0571 mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
0572 mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
0573 drm_info(&dbidev->drm, "Initialized display serial interface\n");
0574 out_exit:
0575 drm_dev_exit(idx);
0576 }
0577
0578 static const struct drm_simple_display_pipe_funcs ili9341_dbi_funcs = {
0579 .enable = ili9341_dbi_enable,
0580 .disable = mipi_dbi_pipe_disable,
0581 .update = mipi_dbi_pipe_update,
0582 .prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
0583 };
0584
0585 static const struct drm_display_mode ili9341_dbi_mode = {
0586 DRM_SIMPLE_MODE(240, 320, 37, 49),
0587 };
0588
0589 DEFINE_DRM_GEM_CMA_FOPS(ili9341_dbi_fops);
0590
0591 static struct drm_driver ili9341_dbi_driver = {
0592 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
0593 .fops = &ili9341_dbi_fops,
0594 DRM_GEM_CMA_DRIVER_OPS_VMAP,
0595 .debugfs_init = mipi_dbi_debugfs_init,
0596 .name = "ili9341",
0597 .desc = "Ilitek ILI9341",
0598 .date = "20210716",
0599 .major = 1,
0600 .minor = 0,
0601 };
0602
0603 static int ili9341_dbi_probe(struct spi_device *spi, struct gpio_desc *dc,
0604 struct gpio_desc *reset)
0605 {
0606 struct device *dev = &spi->dev;
0607 struct mipi_dbi_dev *dbidev;
0608 struct mipi_dbi *dbi;
0609 struct drm_device *drm;
0610 struct regulator *vcc;
0611 u32 rotation = 0;
0612 int ret;
0613
0614 vcc = devm_regulator_get_optional(dev, "vcc");
0615 if (IS_ERR(vcc)) {
0616 dev_err(dev, "get optional vcc failed\n");
0617 vcc = NULL;
0618 }
0619
0620 dbidev = devm_drm_dev_alloc(dev, &ili9341_dbi_driver,
0621 struct mipi_dbi_dev, drm);
0622 if (IS_ERR(dbidev))
0623 return PTR_ERR(dbidev);
0624
0625 dbi = &dbidev->dbi;
0626 drm = &dbidev->drm;
0627 dbi->reset = reset;
0628 dbidev->regulator = vcc;
0629
0630 drm_mode_config_init(drm);
0631
0632 dbidev->backlight = devm_of_find_backlight(dev);
0633 if (IS_ERR(dbidev->backlight))
0634 return PTR_ERR(dbidev->backlight);
0635
0636 device_property_read_u32(dev, "rotation", &rotation);
0637
0638 ret = mipi_dbi_spi_init(spi, dbi, dc);
0639 if (ret)
0640 return ret;
0641
0642 ret = mipi_dbi_dev_init(dbidev, &ili9341_dbi_funcs,
0643 &ili9341_dbi_mode, rotation);
0644 if (ret)
0645 return ret;
0646
0647 drm_mode_config_reset(drm);
0648
0649 ret = drm_dev_register(drm, 0);
0650 if (ret)
0651 return ret;
0652
0653 spi_set_drvdata(spi, drm);
0654
0655 drm_fbdev_generic_setup(drm, 0);
0656
0657 return 0;
0658 }
0659
0660 static int ili9341_dpi_probe(struct spi_device *spi, struct gpio_desc *dc,
0661 struct gpio_desc *reset)
0662 {
0663 struct device *dev = &spi->dev;
0664 struct ili9341 *ili;
0665 int ret;
0666
0667 ili = devm_kzalloc(dev, sizeof(struct ili9341), GFP_KERNEL);
0668 if (!ili)
0669 return -ENOMEM;
0670
0671 ili->dbi = devm_kzalloc(dev, sizeof(struct mipi_dbi),
0672 GFP_KERNEL);
0673 if (!ili->dbi)
0674 return -ENOMEM;
0675
0676 ili->supplies[0].supply = "vci";
0677 ili->supplies[1].supply = "vddi";
0678 ili->supplies[2].supply = "vddi-led";
0679 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ili->supplies),
0680 ili->supplies);
0681 if (ret < 0) {
0682 dev_err(dev, "failed to get regulators: %d\n", ret);
0683 return ret;
0684 }
0685
0686 ret = mipi_dbi_spi_init(spi, ili->dbi, dc);
0687 if (ret)
0688 return ret;
0689
0690 spi_set_drvdata(spi, ili);
0691 ili->reset_gpio = reset;
0692
0693
0694
0695
0696 ili->conf = of_device_get_match_data(dev);
0697 if (!ili->conf) {
0698 dev_err(dev, "missing device configuration\n");
0699 return -ENODEV;
0700 }
0701
0702 ili->max_spi_speed = ili->conf->max_spi_speed;
0703 drm_panel_init(&ili->panel, dev, &ili9341_dpi_funcs,
0704 DRM_MODE_CONNECTOR_DPI);
0705 drm_panel_add(&ili->panel);
0706
0707 return 0;
0708 }
0709
0710 static int ili9341_probe(struct spi_device *spi)
0711 {
0712 struct device *dev = &spi->dev;
0713 struct gpio_desc *dc;
0714 struct gpio_desc *reset;
0715 const struct spi_device_id *id = spi_get_device_id(spi);
0716
0717 reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
0718 if (IS_ERR(reset))
0719 dev_err(dev, "Failed to get gpio 'reset'\n");
0720
0721 dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
0722 if (IS_ERR(dc))
0723 dev_err(dev, "Failed to get gpio 'dc'\n");
0724
0725 if (!strcmp(id->name, "sf-tc240t-9370-t"))
0726 return ili9341_dpi_probe(spi, dc, reset);
0727 else if (!strcmp(id->name, "yx240qv29"))
0728 return ili9341_dbi_probe(spi, dc, reset);
0729
0730 return -1;
0731 }
0732
0733 static void ili9341_remove(struct spi_device *spi)
0734 {
0735 const struct spi_device_id *id = spi_get_device_id(spi);
0736 struct ili9341 *ili = spi_get_drvdata(spi);
0737 struct drm_device *drm = spi_get_drvdata(spi);
0738
0739 if (!strcmp(id->name, "sf-tc240t-9370-t")) {
0740 ili9341_dpi_power_off(ili);
0741 drm_panel_remove(&ili->panel);
0742 } else if (!strcmp(id->name, "yx240qv29")) {
0743 drm_dev_unplug(drm);
0744 drm_atomic_helper_shutdown(drm);
0745 }
0746 }
0747
0748 static void ili9341_shutdown(struct spi_device *spi)
0749 {
0750 const struct spi_device_id *id = spi_get_device_id(spi);
0751
0752 if (!strcmp(id->name, "yx240qv29"))
0753 drm_atomic_helper_shutdown(spi_get_drvdata(spi));
0754 }
0755
0756 static const struct of_device_id ili9341_of_match[] = {
0757 {
0758 .compatible = "st,sf-tc240t-9370-t",
0759 .data = &ili9341_stm32f429_disco_data,
0760 },
0761 {
0762
0763
0764
0765 .compatible = "adafruit,yx240qv29",
0766 .data = NULL,
0767 },
0768 { }
0769 };
0770 MODULE_DEVICE_TABLE(of, ili9341_of_match);
0771
0772 static const struct spi_device_id ili9341_id[] = {
0773 { "yx240qv29", 0 },
0774 { "sf-tc240t-9370-t", 0 },
0775 { }
0776 };
0777 MODULE_DEVICE_TABLE(spi, ili9341_id);
0778
0779 static struct spi_driver ili9341_driver = {
0780 .probe = ili9341_probe,
0781 .remove = ili9341_remove,
0782 .shutdown = ili9341_shutdown,
0783 .id_table = ili9341_id,
0784 .driver = {
0785 .name = "panel-ilitek-ili9341",
0786 .of_match_table = ili9341_of_match,
0787 },
0788 };
0789 module_spi_driver(ili9341_driver);
0790
0791 MODULE_AUTHOR("Dillon Min <dillon.minfei@gmail.com>");
0792 MODULE_DESCRIPTION("ILI9341 LCD panel driver");
0793 MODULE_LICENSE("GPL v2");