1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for panels based on Sitronix ST7703 controller, souch as:
5 * - Rocktech jh057n00900 5.5" MIPI-DSI panel
7 * Copyright (C) Purism SPC 2019
10 #include <linux/debugfs.h>
11 #include <linux/delay.h>
12 #include <linux/gpio/consumer.h>
13 #include <linux/media-bus-format.h>
14 #include <linux/mod_devicetable.h>
15 #include <linux/module.h>
16 #include <linux/of_device.h>
17 #include <linux/regulator/consumer.h>
19 #include <video/display_timing.h>
20 #include <video/mipi_display.h>
22 #include <drm/drm_mipi_dsi.h>
23 #include <drm/drm_modes.h>
24 #include <drm/drm_panel.h>
26 #define DRV_NAME "panel-sitronix-st7703"
28 /* Manufacturer specific Commands send via DSI */
29 #define ST7703_CMD_ALL_PIXEL_OFF 0x22
30 #define ST7703_CMD_ALL_PIXEL_ON 0x23
31 #define ST7703_CMD_SETDISP 0xB2
32 #define ST7703_CMD_SETRGBIF 0xB3
33 #define ST7703_CMD_SETCYC 0xB4
34 #define ST7703_CMD_SETBGP 0xB5
35 #define ST7703_CMD_SETVCOM 0xB6
36 #define ST7703_CMD_SETOTP 0xB7
37 #define ST7703_CMD_SETPOWER_EXT 0xB8
38 #define ST7703_CMD_SETEXTC 0xB9
39 #define ST7703_CMD_SETMIPI 0xBA
40 #define ST7703_CMD_SETVDC 0xBC
41 #define ST7703_CMD_UNKNOWN_BF 0xBF
42 #define ST7703_CMD_SETSCR 0xC0
43 #define ST7703_CMD_SETPOWER 0xC1
44 #define ST7703_CMD_SETPANEL 0xCC
45 #define ST7703_CMD_UNKNOWN_C6 0xC6
46 #define ST7703_CMD_SETGAMMA 0xE0
47 #define ST7703_CMD_SETEQ 0xE3
48 #define ST7703_CMD_SETGIP1 0xE9
49 #define ST7703_CMD_SETGIP2 0xEA
53 struct drm_panel panel
;
54 struct gpio_desc
*reset_gpio
;
55 struct regulator
*vcc
;
56 struct regulator
*iovcc
;
59 struct dentry
*debugfs
;
60 const struct st7703_panel_desc
*desc
;
63 struct st7703_panel_desc
{
64 const struct drm_display_mode
*mode
;
66 unsigned long mode_flags
;
67 enum mipi_dsi_pixel_format format
;
68 int (*init_sequence
)(struct st7703
*ctx
);
71 static inline struct st7703
*panel_to_st7703(struct drm_panel
*panel
)
73 return container_of(panel
, struct st7703
, panel
);
76 #define dsi_generic_write_seq(dsi, seq...) do { \
77 static const u8 d[] = { seq }; \
79 ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
84 static int jh057n_init_sequence(struct st7703
*ctx
)
86 struct mipi_dsi_device
*dsi
= to_mipi_dsi_device(ctx
->dev
);
89 * Init sequence was supplied by the panel vendor. Most of the commands
90 * resemble the ST7703 but the number of parameters often don't match
91 * so it's likely a clone.
93 dsi_generic_write_seq(dsi
, ST7703_CMD_SETEXTC
,
95 dsi_generic_write_seq(dsi
, ST7703_CMD_SETRGBIF
,
96 0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
98 dsi_generic_write_seq(dsi
, ST7703_CMD_SETSCR
,
99 0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
101 dsi_generic_write_seq(dsi
, ST7703_CMD_SETVDC
, 0x4E);
102 dsi_generic_write_seq(dsi
, ST7703_CMD_SETPANEL
, 0x0B);
103 dsi_generic_write_seq(dsi
, ST7703_CMD_SETCYC
, 0x80);
104 dsi_generic_write_seq(dsi
, ST7703_CMD_SETDISP
, 0xF0, 0x12, 0x30);
105 dsi_generic_write_seq(dsi
, ST7703_CMD_SETEQ
,
106 0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
107 0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
108 dsi_generic_write_seq(dsi
, ST7703_CMD_SETBGP
, 0x08, 0x08);
111 dsi_generic_write_seq(dsi
, ST7703_CMD_SETVCOM
, 0x3F, 0x3F);
112 dsi_generic_write_seq(dsi
, ST7703_CMD_UNKNOWN_BF
, 0x02, 0x11, 0x00);
113 dsi_generic_write_seq(dsi
, ST7703_CMD_SETGIP1
,
114 0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
115 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
116 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
117 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
118 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
119 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
120 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
122 dsi_generic_write_seq(dsi
, ST7703_CMD_SETGIP2
,
123 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
125 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
126 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
127 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
130 0xA5, 0x00, 0x00, 0x00, 0x00);
131 dsi_generic_write_seq(dsi
, ST7703_CMD_SETGAMMA
,
132 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
133 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
134 0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
135 0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
141 static const struct drm_display_mode jh057n00900_mode
= {
143 .hsync_start
= 720 + 90,
144 .hsync_end
= 720 + 90 + 20,
145 .htotal
= 720 + 90 + 20 + 20,
147 .vsync_start
= 1440 + 20,
148 .vsync_end
= 1440 + 20 + 4,
149 .vtotal
= 1440 + 20 + 4 + 12,
151 .flags
= DRM_MODE_FLAG_NHSYNC
| DRM_MODE_FLAG_NVSYNC
,
156 static const struct st7703_panel_desc jh057n00900_panel_desc
= {
157 .mode
= &jh057n00900_mode
,
159 .mode_flags
= MIPI_DSI_MODE_VIDEO
|
160 MIPI_DSI_MODE_VIDEO_BURST
| MIPI_DSI_MODE_VIDEO_SYNC_PULSE
,
161 .format
= MIPI_DSI_FMT_RGB888
,
162 .init_sequence
= jh057n_init_sequence
,
165 #define dsi_dcs_write_seq(dsi, cmd, seq...) do { \
166 static const u8 d[] = { seq }; \
168 ret = mipi_dsi_dcs_write(dsi, cmd, d, ARRAY_SIZE(d)); \
174 static int xbd599_init_sequence(struct st7703
*ctx
)
176 struct mipi_dsi_device
*dsi
= to_mipi_dsi_device(ctx
->dev
);
179 * Init sequence was supplied by the panel vendor.
182 /* Magic sequence to unlock user commands below. */
183 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETEXTC
, 0xF1, 0x12, 0x83);
185 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETMIPI
,
186 0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */
187 0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */
188 0x05, /* IHSRX = x6 (Low High Speed driving ability) */
189 0xF9, /* TX_CLK_SEL = fDSICLK/16 */
190 0x0E, /* HFP_OSC (min. HFP number in DSI mode) */
191 0x0E, /* HBP_OSC (min. HBP number in DSI mode) */
192 /* The rest is undocumented in ST7703 datasheet */
193 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
195 0x4F, 0x11, 0x00, 0x00, 0x37);
197 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETPOWER_EXT
,
198 0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */
199 0x22, /* DT = 15ms XDK_ECP = x2 */
200 0x20, /* PFM_DC_DIV = /1 */
201 0x03 /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */);
203 /* RGB I/F porch timing */
204 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETRGBIF
,
205 0x10, /* VBP_RGB_GEN */
206 0x10, /* VFP_RGB_GEN */
207 0x05, /* DE_BP_RGB_GEN */
208 0x05, /* DE_FP_RGB_GEN */
209 /* The rest is undocumented in ST7703 datasheet */
214 /* Source driving settings. */
215 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETSCR
,
220 0x00, /* SCR[31,24] */
221 0xC0, /* SCR[23,16] */
222 0x08, /* SCR[15,8] */
224 0x00 /* Undocumented */);
226 /* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */
227 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETVDC
, 0x4E);
230 * SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan)
231 * REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR)
233 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETPANEL
, 0x0B);
235 /* Zig-Zag Type C column inversion. */
236 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETCYC
, 0x80);
238 /* Set display resolution. */
239 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETDISP
,
241 0x12, /* RES_V_LSB = 0, BLK_CON = VSSD,
244 0xF0 /* WHITE_GND_EN = 1 (GND),
245 * WHITE_FRAME_SEL = 7 frames,
249 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETEQ
,
262 0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */
263 0x10 /* SLPIN_OPTION = 1 (no need vsync after sleep-in)
264 * VEDIO_NO_CHECK_EN = 0
265 * ESD_WHITE_GND_EN = 0
266 * ESD_DET_TIME_SEL = 0 frames
269 /* Undocumented command. */
270 dsi_dcs_write_seq(dsi
, ST7703_CMD_UNKNOWN_C6
, 0x01, 0x00, 0xFF, 0xFF, 0x00);
272 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETPOWER
,
273 0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
274 0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */
278 0xF1, /* APS = 1 (small),
279 * VGL_DET_EN = 1, VGH_DET_EN = 1,
280 * VGL_TURBO = 1, VGH_TURBO = 1
282 0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */
283 0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */
284 0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */
285 0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */
286 0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */
287 0x77 /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);
289 /* Reference voltage. */
290 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETBGP
,
291 0x07, /* VREF_SEL = 4.2V */
292 0x07 /* NVREF_SEL = 4.2V */);
295 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETVCOM
,
296 0x2C, /* VCOMDC_F = -0.67V */
297 0x2C /* VCOMDC_B = -0.67V */);
299 /* Undocumented command. */
300 dsi_dcs_write_seq(dsi
, ST7703_CMD_UNKNOWN_BF
, 0x02, 0x11, 0x00);
302 /* This command is to set forward GIP timing. */
303 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETGIP1
,
304 0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
305 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
306 0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
307 0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
308 0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
309 0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
310 0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
313 /* This command is to set backward GIP timing. */
314 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETGIP2
,
315 0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
317 0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
318 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
319 0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
322 0xA5, 0x00, 0x00, 0x00, 0x00);
324 /* Adjust the gamma characteristics of the panel. */
325 dsi_dcs_write_seq(dsi
, ST7703_CMD_SETGAMMA
,
326 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
327 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
328 0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
329 0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
335 static const struct drm_display_mode xbd599_mode
= {
337 .hsync_start
= 720 + 40,
338 .hsync_end
= 720 + 40 + 40,
339 .htotal
= 720 + 40 + 40 + 40,
341 .vsync_start
= 1440 + 18,
342 .vsync_end
= 1440 + 18 + 10,
343 .vtotal
= 1440 + 18 + 10 + 17,
345 .flags
= DRM_MODE_FLAG_NHSYNC
| DRM_MODE_FLAG_NVSYNC
,
350 static const struct st7703_panel_desc xbd599_desc
= {
351 .mode
= &xbd599_mode
,
353 .mode_flags
= MIPI_DSI_MODE_VIDEO
| MIPI_DSI_MODE_VIDEO_SYNC_PULSE
,
354 .format
= MIPI_DSI_FMT_RGB888
,
355 .init_sequence
= xbd599_init_sequence
,
358 static int st7703_enable(struct drm_panel
*panel
)
360 struct st7703
*ctx
= panel_to_st7703(panel
);
361 struct mipi_dsi_device
*dsi
= to_mipi_dsi_device(ctx
->dev
);
364 ret
= ctx
->desc
->init_sequence(ctx
);
366 dev_err(ctx
->dev
, "Panel init sequence failed: %d\n", ret
);
372 ret
= mipi_dsi_dcs_exit_sleep_mode(dsi
);
374 dev_err(ctx
->dev
, "Failed to exit sleep mode: %d\n", ret
);
378 /* Panel is operational 120 msec after reset */
381 ret
= mipi_dsi_dcs_set_display_on(dsi
);
385 dev_dbg(ctx
->dev
, "Panel init sequence done\n");
390 static int st7703_disable(struct drm_panel
*panel
)
392 struct st7703
*ctx
= panel_to_st7703(panel
);
393 struct mipi_dsi_device
*dsi
= to_mipi_dsi_device(ctx
->dev
);
396 ret
= mipi_dsi_dcs_set_display_off(dsi
);
398 dev_err(ctx
->dev
, "Failed to turn off the display: %d\n", ret
);
400 ret
= mipi_dsi_dcs_enter_sleep_mode(dsi
);
402 dev_err(ctx
->dev
, "Failed to enter sleep mode: %d\n", ret
);
407 static int st7703_unprepare(struct drm_panel
*panel
)
409 struct st7703
*ctx
= panel_to_st7703(panel
);
414 gpiod_set_value_cansleep(ctx
->reset_gpio
, 1);
415 regulator_disable(ctx
->iovcc
);
416 regulator_disable(ctx
->vcc
);
417 ctx
->prepared
= false;
422 static int st7703_prepare(struct drm_panel
*panel
)
424 struct st7703
*ctx
= panel_to_st7703(panel
);
430 dev_dbg(ctx
->dev
, "Resetting the panel\n");
431 ret
= regulator_enable(ctx
->vcc
);
433 dev_err(ctx
->dev
, "Failed to enable vcc supply: %d\n", ret
);
436 ret
= regulator_enable(ctx
->iovcc
);
438 dev_err(ctx
->dev
, "Failed to enable iovcc supply: %d\n", ret
);
442 gpiod_set_value_cansleep(ctx
->reset_gpio
, 1);
443 usleep_range(20, 40);
444 gpiod_set_value_cansleep(ctx
->reset_gpio
, 0);
447 ctx
->prepared
= true;
452 regulator_disable(ctx
->vcc
);
456 static int st7703_get_modes(struct drm_panel
*panel
,
457 struct drm_connector
*connector
)
459 struct st7703
*ctx
= panel_to_st7703(panel
);
460 struct drm_display_mode
*mode
;
462 mode
= drm_mode_duplicate(connector
->dev
, ctx
->desc
->mode
);
464 dev_err(ctx
->dev
, "Failed to add mode %ux%u@%u\n",
465 ctx
->desc
->mode
->hdisplay
, ctx
->desc
->mode
->vdisplay
,
466 drm_mode_vrefresh(ctx
->desc
->mode
));
470 drm_mode_set_name(mode
);
472 mode
->type
= DRM_MODE_TYPE_DRIVER
| DRM_MODE_TYPE_PREFERRED
;
473 connector
->display_info
.width_mm
= mode
->width_mm
;
474 connector
->display_info
.height_mm
= mode
->height_mm
;
475 drm_mode_probed_add(connector
, mode
);
480 static const struct drm_panel_funcs st7703_drm_funcs
= {
481 .disable
= st7703_disable
,
482 .unprepare
= st7703_unprepare
,
483 .prepare
= st7703_prepare
,
484 .enable
= st7703_enable
,
485 .get_modes
= st7703_get_modes
,
488 static int allpixelson_set(void *data
, u64 val
)
490 struct st7703
*ctx
= data
;
491 struct mipi_dsi_device
*dsi
= to_mipi_dsi_device(ctx
->dev
);
493 dev_dbg(ctx
->dev
, "Setting all pixels on\n");
494 dsi_generic_write_seq(dsi
, ST7703_CMD_ALL_PIXEL_ON
);
496 /* Reset the panel to get video back */
497 drm_panel_disable(&ctx
->panel
);
498 drm_panel_unprepare(&ctx
->panel
);
499 drm_panel_prepare(&ctx
->panel
);
500 drm_panel_enable(&ctx
->panel
);
505 DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops
, NULL
,
506 allpixelson_set
, "%llu\n");
508 static void st7703_debugfs_init(struct st7703
*ctx
)
510 ctx
->debugfs
= debugfs_create_dir(DRV_NAME
, NULL
);
512 debugfs_create_file("allpixelson", 0600, ctx
->debugfs
, ctx
,
516 static void st7703_debugfs_remove(struct st7703
*ctx
)
518 debugfs_remove_recursive(ctx
->debugfs
);
522 static int st7703_probe(struct mipi_dsi_device
*dsi
)
524 struct device
*dev
= &dsi
->dev
;
528 ctx
= devm_kzalloc(dev
, sizeof(*ctx
), GFP_KERNEL
);
532 ctx
->reset_gpio
= devm_gpiod_get(dev
, "reset", GPIOD_OUT_LOW
);
533 if (IS_ERR(ctx
->reset_gpio
)) {
534 dev_err(dev
, "cannot get reset gpio\n");
535 return PTR_ERR(ctx
->reset_gpio
);
538 mipi_dsi_set_drvdata(dsi
, ctx
);
541 ctx
->desc
= of_device_get_match_data(dev
);
543 dsi
->mode_flags
= ctx
->desc
->mode_flags
;
544 dsi
->format
= ctx
->desc
->format
;
545 dsi
->lanes
= ctx
->desc
->lanes
;
547 ctx
->vcc
= devm_regulator_get(dev
, "vcc");
548 if (IS_ERR(ctx
->vcc
)) {
549 ret
= PTR_ERR(ctx
->vcc
);
550 if (ret
!= -EPROBE_DEFER
)
551 dev_err(dev
, "Failed to request vcc regulator: %d\n", ret
);
554 ctx
->iovcc
= devm_regulator_get(dev
, "iovcc");
555 if (IS_ERR(ctx
->iovcc
)) {
556 ret
= PTR_ERR(ctx
->iovcc
);
557 if (ret
!= -EPROBE_DEFER
)
558 dev_err(dev
, "Failed to request iovcc regulator: %d\n", ret
);
562 drm_panel_init(&ctx
->panel
, dev
, &st7703_drm_funcs
,
563 DRM_MODE_CONNECTOR_DSI
);
565 ret
= drm_panel_of_backlight(&ctx
->panel
);
569 drm_panel_add(&ctx
->panel
);
571 ret
= mipi_dsi_attach(dsi
);
573 dev_err(dev
, "mipi_dsi_attach failed (%d). Is host ready?\n", ret
);
574 drm_panel_remove(&ctx
->panel
);
578 dev_info(dev
, "%ux%u@%u %ubpp dsi %udl - ready\n",
579 ctx
->desc
->mode
->hdisplay
, ctx
->desc
->mode
->vdisplay
,
580 drm_mode_vrefresh(ctx
->desc
->mode
),
581 mipi_dsi_pixel_format_to_bpp(dsi
->format
), dsi
->lanes
);
583 st7703_debugfs_init(ctx
);
587 static void st7703_shutdown(struct mipi_dsi_device
*dsi
)
589 struct st7703
*ctx
= mipi_dsi_get_drvdata(dsi
);
592 ret
= drm_panel_unprepare(&ctx
->panel
);
594 dev_err(&dsi
->dev
, "Failed to unprepare panel: %d\n", ret
);
596 ret
= drm_panel_disable(&ctx
->panel
);
598 dev_err(&dsi
->dev
, "Failed to disable panel: %d\n", ret
);
601 static int st7703_remove(struct mipi_dsi_device
*dsi
)
603 struct st7703
*ctx
= mipi_dsi_get_drvdata(dsi
);
606 st7703_shutdown(dsi
);
608 ret
= mipi_dsi_detach(dsi
);
610 dev_err(&dsi
->dev
, "Failed to detach from DSI host: %d\n", ret
);
612 drm_panel_remove(&ctx
->panel
);
614 st7703_debugfs_remove(ctx
);
619 static const struct of_device_id st7703_of_match
[] = {
620 { .compatible
= "rocktech,jh057n00900", .data
= &jh057n00900_panel_desc
},
621 { .compatible
= "xingbangda,xbd599", .data
= &xbd599_desc
},
624 MODULE_DEVICE_TABLE(of
, st7703_of_match
);
626 static struct mipi_dsi_driver st7703_driver
= {
627 .probe
= st7703_probe
,
628 .remove
= st7703_remove
,
629 .shutdown
= st7703_shutdown
,
632 .of_match_table
= st7703_of_match
,
635 module_mipi_dsi_driver(st7703_driver
);
637 MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>");
638 MODULE_DESCRIPTION("DRM driver for Sitronix ST7703 based MIPI DSI panels");
639 MODULE_LICENSE("GPL v2");