0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/debugfs.h>
0011 #include <linux/delay.h>
0012 #include <linux/gpio/consumer.h>
0013 #include <linux/media-bus-format.h>
0014 #include <linux/mod_devicetable.h>
0015 #include <linux/module.h>
0016 #include <linux/of_device.h>
0017 #include <linux/regulator/consumer.h>
0018
0019 #include <video/display_timing.h>
0020 #include <video/mipi_display.h>
0021
0022 #include <drm/drm_mipi_dsi.h>
0023 #include <drm/drm_modes.h>
0024 #include <drm/drm_panel.h>
0025
0026 #define DRV_NAME "panel-sitronix-st7703"
0027
0028
0029 #define ST7703_CMD_ALL_PIXEL_OFF 0x22
0030 #define ST7703_CMD_ALL_PIXEL_ON 0x23
0031 #define ST7703_CMD_SETDISP 0xB2
0032 #define ST7703_CMD_SETRGBIF 0xB3
0033 #define ST7703_CMD_SETCYC 0xB4
0034 #define ST7703_CMD_SETBGP 0xB5
0035 #define ST7703_CMD_SETVCOM 0xB6
0036 #define ST7703_CMD_SETOTP 0xB7
0037 #define ST7703_CMD_SETPOWER_EXT 0xB8
0038 #define ST7703_CMD_SETEXTC 0xB9
0039 #define ST7703_CMD_SETMIPI 0xBA
0040 #define ST7703_CMD_SETVDC 0xBC
0041 #define ST7703_CMD_UNKNOWN_BF 0xBF
0042 #define ST7703_CMD_SETSCR 0xC0
0043 #define ST7703_CMD_SETPOWER 0xC1
0044 #define ST7703_CMD_SETPANEL 0xCC
0045 #define ST7703_CMD_UNKNOWN_C6 0xC6
0046 #define ST7703_CMD_SETGAMMA 0xE0
0047 #define ST7703_CMD_SETEQ 0xE3
0048 #define ST7703_CMD_SETGIP1 0xE9
0049 #define ST7703_CMD_SETGIP2 0xEA
0050
0051 struct st7703 {
0052 struct device *dev;
0053 struct drm_panel panel;
0054 struct gpio_desc *reset_gpio;
0055 struct regulator *vcc;
0056 struct regulator *iovcc;
0057 bool prepared;
0058
0059 struct dentry *debugfs;
0060 const struct st7703_panel_desc *desc;
0061 };
0062
0063 struct st7703_panel_desc {
0064 const struct drm_display_mode *mode;
0065 unsigned int lanes;
0066 unsigned long mode_flags;
0067 enum mipi_dsi_pixel_format format;
0068 int (*init_sequence)(struct st7703 *ctx);
0069 };
0070
0071 static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
0072 {
0073 return container_of(panel, struct st7703, panel);
0074 }
0075
0076 #define dsi_generic_write_seq(dsi, seq...) do { \
0077 static const u8 d[] = { seq }; \
0078 int ret; \
0079 ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
0080 if (ret < 0) \
0081 return ret; \
0082 } while (0)
0083
0084 static int jh057n_init_sequence(struct st7703 *ctx)
0085 {
0086 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0087
0088
0089
0090
0091
0092
0093 dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC,
0094 0xF1, 0x12, 0x83);
0095 dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF,
0096 0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
0097 0x00, 0x00);
0098 dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR,
0099 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
0100 0x00);
0101 dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
0102 dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
0103 dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
0104 dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30);
0105 dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ,
0106 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
0107 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
0108 dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08);
0109 msleep(20);
0110
0111 dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
0112 dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
0113 dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1,
0114 0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
0115 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
0116 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
0117 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
0118 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
0119 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0120 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
0122 dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2,
0123 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0124 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
0125 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
0126 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0127 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
0128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
0130 0xA5, 0x00, 0x00, 0x00, 0x00);
0131 dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA,
0132 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
0133 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
0134 0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
0135 0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
0136 0x11, 0x18);
0137
0138 return 0;
0139 }
0140
0141 static const struct drm_display_mode jh057n00900_mode = {
0142 .hdisplay = 720,
0143 .hsync_start = 720 + 90,
0144 .hsync_end = 720 + 90 + 20,
0145 .htotal = 720 + 90 + 20 + 20,
0146 .vdisplay = 1440,
0147 .vsync_start = 1440 + 20,
0148 .vsync_end = 1440 + 20 + 4,
0149 .vtotal = 1440 + 20 + 4 + 12,
0150 .clock = 75276,
0151 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
0152 .width_mm = 65,
0153 .height_mm = 130,
0154 };
0155
0156 static const struct st7703_panel_desc jh057n00900_panel_desc = {
0157 .mode = &jh057n00900_mode,
0158 .lanes = 4,
0159 .mode_flags = MIPI_DSI_MODE_VIDEO |
0160 MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
0161 .format = MIPI_DSI_FMT_RGB888,
0162 .init_sequence = jh057n_init_sequence,
0163 };
0164
0165 #define dsi_dcs_write_seq(dsi, cmd, seq...) do { \
0166 static const u8 d[] = { seq }; \
0167 int ret; \
0168 ret = mipi_dsi_dcs_write(dsi, cmd, d, ARRAY_SIZE(d)); \
0169 if (ret < 0) \
0170 return ret; \
0171 } while (0)
0172
0173
0174 static int xbd599_init_sequence(struct st7703 *ctx)
0175 {
0176 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0177
0178
0179
0180
0181
0182
0183 dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);
0184
0185 dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI,
0186 0x33,
0187 0x81,
0188 0x05,
0189 0xF9,
0190 0x0E,
0191 0x0E,
0192
0193 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0194 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
0195 0x4F, 0x11, 0x00, 0x00, 0x37);
0196
0197 dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT,
0198 0x25,
0199 0x22,
0200 0x20,
0201 0x03 );
0202
0203
0204 dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF,
0205 0x10,
0206 0x10,
0207 0x05,
0208 0x05,
0209
0210 0x03, 0xFF,
0211 0x00, 0x00,
0212 0x00, 0x00);
0213
0214
0215 dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR,
0216 0x73,
0217 0x73,
0218 0x50,
0219 0x50,
0220 0x00,
0221 0xC0,
0222 0x08,
0223 0x70,
0224 0x00 );
0225
0226
0227 dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
0228
0229
0230
0231
0232
0233 dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
0234
0235
0236 dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
0237
0238
0239 dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP,
0240 0xF0,
0241 0x12,
0242
0243
0244 0xF0
0245
0246
0247 );
0248
0249 dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ,
0250 0x00,
0251 0x00,
0252 0x0B,
0253 0x0B,
0254 0x10,
0255 0x10,
0256 0x00,
0257 0x00,
0258 0x00,
0259 0x00,
0260 0xFF,
0261 0x00,
0262 0xC0,
0263 0x10
0264
0265
0266
0267 );
0268
0269
0270 dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_C6, 0x01, 0x00, 0xFF, 0xFF, 0x00);
0271
0272 dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,
0273 0x74,
0274 0x00,
0275 0x32,
0276 0x32,
0277 0x77,
0278 0xF1,
0279
0280
0281
0282 0xFF,
0283 0xFF,
0284 0xCC,
0285 0xCC,
0286 0x77,
0287 0x77 );
0288
0289
0290 dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
0291 0x07,
0292 0x07 );
0293 msleep(20);
0294
0295 dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
0296 0x2C,
0297 0x2C );
0298
0299
0300 dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
0301
0302
0303 dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1,
0304 0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
0305 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
0306 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
0307 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
0308 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
0309 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0310 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
0312
0313
0314 dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2,
0315 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0316 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
0317 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
0318 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0319 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
0320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
0322 0xA5, 0x00, 0x00, 0x00, 0x00);
0323
0324
0325 dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA,
0326 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
0327 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
0328 0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
0329 0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
0330 0x12, 0x18);
0331
0332 return 0;
0333 }
0334
0335 static const struct drm_display_mode xbd599_mode = {
0336 .hdisplay = 720,
0337 .hsync_start = 720 + 40,
0338 .hsync_end = 720 + 40 + 40,
0339 .htotal = 720 + 40 + 40 + 40,
0340 .vdisplay = 1440,
0341 .vsync_start = 1440 + 18,
0342 .vsync_end = 1440 + 18 + 10,
0343 .vtotal = 1440 + 18 + 10 + 17,
0344 .clock = 69000,
0345 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
0346 .width_mm = 68,
0347 .height_mm = 136,
0348 };
0349
0350 static const struct st7703_panel_desc xbd599_desc = {
0351 .mode = &xbd599_mode,
0352 .lanes = 4,
0353 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
0354 .format = MIPI_DSI_FMT_RGB888,
0355 .init_sequence = xbd599_init_sequence,
0356 };
0357
0358 static int st7703_enable(struct drm_panel *panel)
0359 {
0360 struct st7703 *ctx = panel_to_st7703(panel);
0361 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0362 int ret;
0363
0364 ret = ctx->desc->init_sequence(ctx);
0365 if (ret < 0) {
0366 dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
0367 return ret;
0368 }
0369
0370 msleep(20);
0371
0372 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
0373 if (ret < 0) {
0374 dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
0375 return ret;
0376 }
0377
0378
0379 msleep(60);
0380
0381 ret = mipi_dsi_dcs_set_display_on(dsi);
0382 if (ret)
0383 return ret;
0384
0385 dev_dbg(ctx->dev, "Panel init sequence done\n");
0386
0387 return 0;
0388 }
0389
0390 static int st7703_disable(struct drm_panel *panel)
0391 {
0392 struct st7703 *ctx = panel_to_st7703(panel);
0393 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0394 int ret;
0395
0396 ret = mipi_dsi_dcs_set_display_off(dsi);
0397 if (ret < 0)
0398 dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret);
0399
0400 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
0401 if (ret < 0)
0402 dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
0403
0404 return 0;
0405 }
0406
0407 static int st7703_unprepare(struct drm_panel *panel)
0408 {
0409 struct st7703 *ctx = panel_to_st7703(panel);
0410
0411 if (!ctx->prepared)
0412 return 0;
0413
0414 gpiod_set_value_cansleep(ctx->reset_gpio, 1);
0415 regulator_disable(ctx->iovcc);
0416 regulator_disable(ctx->vcc);
0417 ctx->prepared = false;
0418
0419 return 0;
0420 }
0421
0422 static int st7703_prepare(struct drm_panel *panel)
0423 {
0424 struct st7703 *ctx = panel_to_st7703(panel);
0425 int ret;
0426
0427 if (ctx->prepared)
0428 return 0;
0429
0430 dev_dbg(ctx->dev, "Resetting the panel\n");
0431 ret = regulator_enable(ctx->vcc);
0432 if (ret < 0) {
0433 dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
0434 return ret;
0435 }
0436 ret = regulator_enable(ctx->iovcc);
0437 if (ret < 0) {
0438 dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
0439 goto disable_vcc;
0440 }
0441
0442 gpiod_set_value_cansleep(ctx->reset_gpio, 1);
0443 usleep_range(20, 40);
0444 gpiod_set_value_cansleep(ctx->reset_gpio, 0);
0445 msleep(20);
0446
0447 ctx->prepared = true;
0448
0449 return 0;
0450
0451 disable_vcc:
0452 regulator_disable(ctx->vcc);
0453 return ret;
0454 }
0455
0456 static const u32 mantix_bus_formats[] = {
0457 MEDIA_BUS_FMT_RGB888_1X24,
0458 };
0459
0460 static int st7703_get_modes(struct drm_panel *panel,
0461 struct drm_connector *connector)
0462 {
0463 struct st7703 *ctx = panel_to_st7703(panel);
0464 struct drm_display_mode *mode;
0465
0466 mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
0467 if (!mode) {
0468 dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
0469 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
0470 drm_mode_vrefresh(ctx->desc->mode));
0471 return -ENOMEM;
0472 }
0473
0474 drm_mode_set_name(mode);
0475
0476 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
0477 connector->display_info.width_mm = mode->width_mm;
0478 connector->display_info.height_mm = mode->height_mm;
0479 drm_mode_probed_add(connector, mode);
0480
0481 drm_display_info_set_bus_formats(&connector->display_info,
0482 mantix_bus_formats,
0483 ARRAY_SIZE(mantix_bus_formats));
0484
0485 return 1;
0486 }
0487
0488 static const struct drm_panel_funcs st7703_drm_funcs = {
0489 .disable = st7703_disable,
0490 .unprepare = st7703_unprepare,
0491 .prepare = st7703_prepare,
0492 .enable = st7703_enable,
0493 .get_modes = st7703_get_modes,
0494 };
0495
0496 static int allpixelson_set(void *data, u64 val)
0497 {
0498 struct st7703 *ctx = data;
0499 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
0500
0501 dev_dbg(ctx->dev, "Setting all pixels on\n");
0502 dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
0503 msleep(val * 1000);
0504
0505 drm_panel_disable(&ctx->panel);
0506 drm_panel_unprepare(&ctx->panel);
0507 drm_panel_prepare(&ctx->panel);
0508 drm_panel_enable(&ctx->panel);
0509
0510 return 0;
0511 }
0512
0513 DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL,
0514 allpixelson_set, "%llu\n");
0515
0516 static void st7703_debugfs_init(struct st7703 *ctx)
0517 {
0518 ctx->debugfs = debugfs_create_dir(DRV_NAME, NULL);
0519
0520 debugfs_create_file("allpixelson", 0600, ctx->debugfs, ctx,
0521 &allpixelson_fops);
0522 }
0523
0524 static void st7703_debugfs_remove(struct st7703 *ctx)
0525 {
0526 debugfs_remove_recursive(ctx->debugfs);
0527 ctx->debugfs = NULL;
0528 }
0529
0530 static int st7703_probe(struct mipi_dsi_device *dsi)
0531 {
0532 struct device *dev = &dsi->dev;
0533 struct st7703 *ctx;
0534 int ret;
0535
0536 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
0537 if (!ctx)
0538 return -ENOMEM;
0539
0540 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
0541 if (IS_ERR(ctx->reset_gpio))
0542 return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n");
0543
0544 mipi_dsi_set_drvdata(dsi, ctx);
0545
0546 ctx->dev = dev;
0547 ctx->desc = of_device_get_match_data(dev);
0548
0549 dsi->mode_flags = ctx->desc->mode_flags;
0550 dsi->format = ctx->desc->format;
0551 dsi->lanes = ctx->desc->lanes;
0552
0553 ctx->vcc = devm_regulator_get(dev, "vcc");
0554 if (IS_ERR(ctx->vcc))
0555 return dev_err_probe(dev, PTR_ERR(ctx->vcc), "Failed to request vcc regulator\n");
0556
0557 ctx->iovcc = devm_regulator_get(dev, "iovcc");
0558 if (IS_ERR(ctx->iovcc))
0559 return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
0560 "Failed to request iovcc regulator\n");
0561
0562 drm_panel_init(&ctx->panel, dev, &st7703_drm_funcs,
0563 DRM_MODE_CONNECTOR_DSI);
0564
0565 ret = drm_panel_of_backlight(&ctx->panel);
0566 if (ret)
0567 return ret;
0568
0569 drm_panel_add(&ctx->panel);
0570
0571 ret = mipi_dsi_attach(dsi);
0572 if (ret < 0) {
0573 dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);
0574 drm_panel_remove(&ctx->panel);
0575 return ret;
0576 }
0577
0578 dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
0579 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
0580 drm_mode_vrefresh(ctx->desc->mode),
0581 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
0582
0583 st7703_debugfs_init(ctx);
0584 return 0;
0585 }
0586
0587 static void st7703_shutdown(struct mipi_dsi_device *dsi)
0588 {
0589 struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
0590 int ret;
0591
0592 ret = drm_panel_unprepare(&ctx->panel);
0593 if (ret < 0)
0594 dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
0595
0596 ret = drm_panel_disable(&ctx->panel);
0597 if (ret < 0)
0598 dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
0599 }
0600
0601 static int st7703_remove(struct mipi_dsi_device *dsi)
0602 {
0603 struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
0604 int ret;
0605
0606 st7703_shutdown(dsi);
0607
0608 ret = mipi_dsi_detach(dsi);
0609 if (ret < 0)
0610 dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
0611
0612 drm_panel_remove(&ctx->panel);
0613
0614 st7703_debugfs_remove(ctx);
0615
0616 return 0;
0617 }
0618
0619 static const struct of_device_id st7703_of_match[] = {
0620 { .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc },
0621 { .compatible = "xingbangda,xbd599", .data = &xbd599_desc },
0622 { }
0623 };
0624 MODULE_DEVICE_TABLE(of, st7703_of_match);
0625
0626 static struct mipi_dsi_driver st7703_driver = {
0627 .probe = st7703_probe,
0628 .remove = st7703_remove,
0629 .shutdown = st7703_shutdown,
0630 .driver = {
0631 .name = DRV_NAME,
0632 .of_match_table = st7703_of_match,
0633 },
0634 };
0635 module_mipi_dsi_driver(st7703_driver);
0636
0637 MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>");
0638 MODULE_DESCRIPTION("DRM driver for Sitronix ST7703 based MIPI DSI panels");
0639 MODULE_LICENSE("GPL v2");