1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Driver for panels based on Sitronix ST7703 controller, souch as:
4  *
5  * - Rocktech jh057n00900 5.5" MIPI-DSI panel
6  *
7  * Copyright (C) Purism SPC 2019
8  */
9 
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>
18 
19 #include <video/display_timing.h>
20 #include <video/mipi_display.h>
21 
22 #include <drm/drm_mipi_dsi.h>
23 #include <drm/drm_modes.h>
24 #include <drm/drm_panel.h>
25 
26 #define DRV_NAME "panel-sitronix-st7703"
27 
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
50 
51 struct st7703 {
52 	struct device *dev;
53 	struct drm_panel panel;
54 	struct gpio_desc *reset_gpio;
55 	struct regulator *vcc;
56 	struct regulator *iovcc;
57 	bool prepared;
58 
59 	struct dentry *debugfs;
60 	const struct st7703_panel_desc *desc;
61 };
62 
63 struct st7703_panel_desc {
64 	const struct drm_display_mode *mode;
65 	unsigned int lanes;
66 	unsigned long mode_flags;
67 	enum mipi_dsi_pixel_format format;
68 	int (*init_sequence)(struct st7703 *ctx);
69 };
70 
71 static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
72 {
73 	return container_of(panel, struct st7703, panel);
74 }
75 
76 static int jh057n_init_sequence(struct st7703 *ctx)
77 {
78 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
79 
80 	/*
81 	 * Init sequence was supplied by the panel vendor. Most of the commands
82 	 * resemble the ST7703 but the number of parameters often don't match
83 	 * so it's likely a clone.
84 	 */
85 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC,
86 				   0xF1, 0x12, 0x83);
87 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF,
88 				   0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
89 				   0x00, 0x00);
90 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR,
91 				   0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
92 				   0x00);
93 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
94 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
95 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
96 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30);
97 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ,
98 				   0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
99 				   0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
100 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08);
101 	msleep(20);
102 
103 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
104 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
105 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1,
106 				   0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
107 				   0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
108 				   0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
109 				   0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
110 				   0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
111 				   0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
112 				   0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 				   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
114 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2,
115 				   0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 				   0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
117 				   0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
118 				   0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
119 				   0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
120 				   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 				   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
122 				   0xA5, 0x00, 0x00, 0x00, 0x00);
123 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA,
124 				   0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
125 				   0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
126 				   0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
127 				   0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
128 				   0x11, 0x18);
129 
130 	return 0;
131 }
132 
133 static const struct drm_display_mode jh057n00900_mode = {
134 	.hdisplay    = 720,
135 	.hsync_start = 720 + 90,
136 	.hsync_end   = 720 + 90 + 20,
137 	.htotal	     = 720 + 90 + 20 + 20,
138 	.vdisplay    = 1440,
139 	.vsync_start = 1440 + 20,
140 	.vsync_end   = 1440 + 20 + 4,
141 	.vtotal	     = 1440 + 20 + 4 + 12,
142 	.clock	     = 75276,
143 	.flags	     = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
144 	.width_mm    = 65,
145 	.height_mm   = 130,
146 };
147 
148 static const struct st7703_panel_desc jh057n00900_panel_desc = {
149 	.mode = &jh057n00900_mode,
150 	.lanes = 4,
151 	.mode_flags = MIPI_DSI_MODE_VIDEO |
152 		MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
153 	.format = MIPI_DSI_FMT_RGB888,
154 	.init_sequence = jh057n_init_sequence,
155 };
156 
157 static int xbd599_init_sequence(struct st7703 *ctx)
158 {
159 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
160 
161 	/*
162 	 * Init sequence was supplied by the panel vendor.
163 	 */
164 
165 	/* Magic sequence to unlock user commands below. */
166 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);
167 
168 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI,
169 			       0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */
170 			       0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */
171 			       0x05, /* IHSRX = x6 (Low High Speed driving ability) */
172 			       0xF9, /* TX_CLK_SEL = fDSICLK/16 */
173 			       0x0E, /* HFP_OSC (min. HFP number in DSI mode) */
174 			       0x0E, /* HBP_OSC (min. HBP number in DSI mode) */
175 			       /* The rest is undocumented in ST7703 datasheet */
176 			       0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 			       0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
178 			       0x4F, 0x11, 0x00, 0x00, 0x37);
179 
180 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT,
181 			       0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */
182 			       0x22, /* DT = 15ms XDK_ECP = x2 */
183 			       0x20, /* PFM_DC_DIV = /1 */
184 			       0x03  /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */);
185 
186 	/* RGB I/F porch timing */
187 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF,
188 			       0x10, /* VBP_RGB_GEN */
189 			       0x10, /* VFP_RGB_GEN */
190 			       0x05, /* DE_BP_RGB_GEN */
191 			       0x05, /* DE_FP_RGB_GEN */
192 			       /* The rest is undocumented in ST7703 datasheet */
193 			       0x03, 0xFF,
194 			       0x00, 0x00,
195 			       0x00, 0x00);
196 
197 	/* Source driving settings. */
198 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR,
199 			       0x73, /* N_POPON */
200 			       0x73, /* N_NOPON */
201 			       0x50, /* I_POPON */
202 			       0x50, /* I_NOPON */
203 			       0x00, /* SCR[31,24] */
204 			       0xC0, /* SCR[23,16] */
205 			       0x08, /* SCR[15,8] */
206 			       0x70, /* SCR[7,0] */
207 			       0x00  /* Undocumented */);
208 
209 	/* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */
210 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
211 
212 	/*
213 	 * SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan)
214 	 * REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR)
215 	 */
216 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
217 
218 	/* Zig-Zag Type C column inversion. */
219 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
220 
221 	/* Set display resolution. */
222 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP,
223 			       0xF0, /* NL = 240 */
224 			       0x12, /* RES_V_LSB = 0, BLK_CON = VSSD,
225 				      * RESO_SEL = 720RGB
226 				      */
227 			       0xF0  /* WHITE_GND_EN = 1 (GND),
228 				      * WHITE_FRAME_SEL = 7 frames,
229 				      * ISC = 0 frames
230 				      */);
231 
232 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ,
233 			       0x00, /* PNOEQ */
234 			       0x00, /* NNOEQ */
235 			       0x0B, /* PEQGND */
236 			       0x0B, /* NEQGND */
237 			       0x10, /* PEQVCI */
238 			       0x10, /* NEQVCI */
239 			       0x00, /* PEQVCI1 */
240 			       0x00, /* NEQVCI1 */
241 			       0x00, /* reserved */
242 			       0x00, /* reserved */
243 			       0xFF, /* reserved */
244 			       0x00, /* reserved */
245 			       0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */
246 			       0x10  /* SLPIN_OPTION = 1 (no need vsync after sleep-in)
247 				      * VEDIO_NO_CHECK_EN = 0
248 				      * ESD_WHITE_GND_EN = 0
249 				      * ESD_DET_TIME_SEL = 0 frames
250 				      */);
251 
252 	/* Undocumented command. */
253 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_C6, 0x01, 0x00, 0xFF, 0xFF, 0x00);
254 
255 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,
256 			       0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
257 			       0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */
258 			       0x32, /* VRP  */
259 			       0x32, /* VRN */
260 			       0x77, /* reserved */
261 			       0xF1, /* APS = 1 (small),
262 				      * VGL_DET_EN = 1, VGH_DET_EN = 1,
263 				      * VGL_TURBO = 1, VGH_TURBO = 1
264 				      */
265 			       0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */
266 			       0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */
267 			       0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */
268 			       0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */
269 			       0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */
270 			       0x77  /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);
271 
272 	/* Reference voltage. */
273 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
274 			       0x07, /* VREF_SEL = 4.2V */
275 			       0x07  /* NVREF_SEL = 4.2V */);
276 	msleep(20);
277 
278 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
279 			       0x2C, /* VCOMDC_F = -0.67V */
280 			       0x2C  /* VCOMDC_B = -0.67V */);
281 
282 	/* Undocumented command. */
283 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
284 
285 	/* This command is to set forward GIP timing. */
286 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1,
287 			       0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
288 			       0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
289 			       0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
290 			       0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
291 			       0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
292 			       0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
293 			       0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
295 
296 	/* This command is to set backward GIP timing. */
297 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2,
298 			       0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 			       0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
300 			       0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
301 			       0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
302 			       0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
303 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
305 			       0xA5, 0x00, 0x00, 0x00, 0x00);
306 
307 	/* Adjust the gamma characteristics of the panel. */
308 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA,
309 			       0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
310 			       0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
311 			       0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
312 			       0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
313 			       0x12, 0x18);
314 
315 	return 0;
316 }
317 
318 static const struct drm_display_mode xbd599_mode = {
319 	.hdisplay    = 720,
320 	.hsync_start = 720 + 40,
321 	.hsync_end   = 720 + 40 + 40,
322 	.htotal	     = 720 + 40 + 40 + 40,
323 	.vdisplay    = 1440,
324 	.vsync_start = 1440 + 18,
325 	.vsync_end   = 1440 + 18 + 10,
326 	.vtotal	     = 1440 + 18 + 10 + 17,
327 	.clock	     = 69000,
328 	.flags	     = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
329 	.width_mm    = 68,
330 	.height_mm   = 136,
331 };
332 
333 static const struct st7703_panel_desc xbd599_desc = {
334 	.mode = &xbd599_mode,
335 	.lanes = 4,
336 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
337 	.format = MIPI_DSI_FMT_RGB888,
338 	.init_sequence = xbd599_init_sequence,
339 };
340 
341 static int st7703_enable(struct drm_panel *panel)
342 {
343 	struct st7703 *ctx = panel_to_st7703(panel);
344 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
345 	int ret;
346 
347 	ret = ctx->desc->init_sequence(ctx);
348 	if (ret < 0) {
349 		dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
350 		return ret;
351 	}
352 
353 	msleep(20);
354 
355 	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
356 	if (ret < 0) {
357 		dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
358 		return ret;
359 	}
360 
361 	/* Panel is operational 120 msec after reset */
362 	msleep(60);
363 
364 	ret = mipi_dsi_dcs_set_display_on(dsi);
365 	if (ret)
366 		return ret;
367 
368 	dev_dbg(ctx->dev, "Panel init sequence done\n");
369 
370 	return 0;
371 }
372 
373 static int st7703_disable(struct drm_panel *panel)
374 {
375 	struct st7703 *ctx = panel_to_st7703(panel);
376 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
377 	int ret;
378 
379 	ret = mipi_dsi_dcs_set_display_off(dsi);
380 	if (ret < 0)
381 		dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret);
382 
383 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
384 	if (ret < 0)
385 		dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
386 
387 	return 0;
388 }
389 
390 static int st7703_unprepare(struct drm_panel *panel)
391 {
392 	struct st7703 *ctx = panel_to_st7703(panel);
393 
394 	if (!ctx->prepared)
395 		return 0;
396 
397 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
398 	regulator_disable(ctx->iovcc);
399 	regulator_disable(ctx->vcc);
400 	ctx->prepared = false;
401 
402 	return 0;
403 }
404 
405 static int st7703_prepare(struct drm_panel *panel)
406 {
407 	struct st7703 *ctx = panel_to_st7703(panel);
408 	int ret;
409 
410 	if (ctx->prepared)
411 		return 0;
412 
413 	dev_dbg(ctx->dev, "Resetting the panel\n");
414 	ret = regulator_enable(ctx->vcc);
415 	if (ret < 0) {
416 		dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
417 		return ret;
418 	}
419 	ret = regulator_enable(ctx->iovcc);
420 	if (ret < 0) {
421 		dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
422 		goto disable_vcc;
423 	}
424 
425 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
426 	usleep_range(20, 40);
427 	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
428 	msleep(20);
429 
430 	ctx->prepared = true;
431 
432 	return 0;
433 
434 disable_vcc:
435 	regulator_disable(ctx->vcc);
436 	return ret;
437 }
438 
439 static const u32 mantix_bus_formats[] = {
440 	MEDIA_BUS_FMT_RGB888_1X24,
441 };
442 
443 static int st7703_get_modes(struct drm_panel *panel,
444 			    struct drm_connector *connector)
445 {
446 	struct st7703 *ctx = panel_to_st7703(panel);
447 	struct drm_display_mode *mode;
448 
449 	mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
450 	if (!mode) {
451 		dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
452 			ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
453 			drm_mode_vrefresh(ctx->desc->mode));
454 		return -ENOMEM;
455 	}
456 
457 	drm_mode_set_name(mode);
458 
459 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
460 	connector->display_info.width_mm = mode->width_mm;
461 	connector->display_info.height_mm = mode->height_mm;
462 	drm_mode_probed_add(connector, mode);
463 
464 	drm_display_info_set_bus_formats(&connector->display_info,
465 					 mantix_bus_formats,
466 					 ARRAY_SIZE(mantix_bus_formats));
467 
468 	return 1;
469 }
470 
471 static const struct drm_panel_funcs st7703_drm_funcs = {
472 	.disable   = st7703_disable,
473 	.unprepare = st7703_unprepare,
474 	.prepare   = st7703_prepare,
475 	.enable	   = st7703_enable,
476 	.get_modes = st7703_get_modes,
477 };
478 
479 static int allpixelson_set(void *data, u64 val)
480 {
481 	struct st7703 *ctx = data;
482 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
483 
484 	dev_dbg(ctx->dev, "Setting all pixels on\n");
485 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
486 	msleep(val * 1000);
487 	/* Reset the panel to get video back */
488 	drm_panel_disable(&ctx->panel);
489 	drm_panel_unprepare(&ctx->panel);
490 	drm_panel_prepare(&ctx->panel);
491 	drm_panel_enable(&ctx->panel);
492 
493 	return 0;
494 }
495 
496 DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL,
497 			allpixelson_set, "%llu\n");
498 
499 static void st7703_debugfs_init(struct st7703 *ctx)
500 {
501 	ctx->debugfs = debugfs_create_dir(DRV_NAME, NULL);
502 
503 	debugfs_create_file("allpixelson", 0600, ctx->debugfs, ctx,
504 			    &allpixelson_fops);
505 }
506 
507 static void st7703_debugfs_remove(struct st7703 *ctx)
508 {
509 	debugfs_remove_recursive(ctx->debugfs);
510 	ctx->debugfs = NULL;
511 }
512 
513 static int st7703_probe(struct mipi_dsi_device *dsi)
514 {
515 	struct device *dev = &dsi->dev;
516 	struct st7703 *ctx;
517 	int ret;
518 
519 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
520 	if (!ctx)
521 		return -ENOMEM;
522 
523 	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
524 	if (IS_ERR(ctx->reset_gpio))
525 		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n");
526 
527 	mipi_dsi_set_drvdata(dsi, ctx);
528 
529 	ctx->dev = dev;
530 	ctx->desc = of_device_get_match_data(dev);
531 
532 	dsi->mode_flags = ctx->desc->mode_flags;
533 	dsi->format = ctx->desc->format;
534 	dsi->lanes = ctx->desc->lanes;
535 
536 	ctx->vcc = devm_regulator_get(dev, "vcc");
537 	if (IS_ERR(ctx->vcc))
538 		return dev_err_probe(dev, PTR_ERR(ctx->vcc), "Failed to request vcc regulator\n");
539 
540 	ctx->iovcc = devm_regulator_get(dev, "iovcc");
541 	if (IS_ERR(ctx->iovcc))
542 		return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
543 				     "Failed to request iovcc regulator\n");
544 
545 	drm_panel_init(&ctx->panel, dev, &st7703_drm_funcs,
546 		       DRM_MODE_CONNECTOR_DSI);
547 
548 	ret = drm_panel_of_backlight(&ctx->panel);
549 	if (ret)
550 		return ret;
551 
552 	drm_panel_add(&ctx->panel);
553 
554 	ret = mipi_dsi_attach(dsi);
555 	if (ret < 0) {
556 		dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);
557 		drm_panel_remove(&ctx->panel);
558 		return ret;
559 	}
560 
561 	dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
562 		 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
563 		 drm_mode_vrefresh(ctx->desc->mode),
564 		 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
565 
566 	st7703_debugfs_init(ctx);
567 	return 0;
568 }
569 
570 static void st7703_shutdown(struct mipi_dsi_device *dsi)
571 {
572 	struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
573 	int ret;
574 
575 	ret = drm_panel_unprepare(&ctx->panel);
576 	if (ret < 0)
577 		dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
578 
579 	ret = drm_panel_disable(&ctx->panel);
580 	if (ret < 0)
581 		dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
582 }
583 
584 static void st7703_remove(struct mipi_dsi_device *dsi)
585 {
586 	struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
587 	int ret;
588 
589 	st7703_shutdown(dsi);
590 
591 	ret = mipi_dsi_detach(dsi);
592 	if (ret < 0)
593 		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
594 
595 	drm_panel_remove(&ctx->panel);
596 
597 	st7703_debugfs_remove(ctx);
598 }
599 
600 static const struct of_device_id st7703_of_match[] = {
601 	{ .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc },
602 	{ .compatible = "xingbangda,xbd599", .data = &xbd599_desc },
603 	{ /* sentinel */ }
604 };
605 MODULE_DEVICE_TABLE(of, st7703_of_match);
606 
607 static struct mipi_dsi_driver st7703_driver = {
608 	.probe	= st7703_probe,
609 	.remove = st7703_remove,
610 	.shutdown = st7703_shutdown,
611 	.driver = {
612 		.name = DRV_NAME,
613 		.of_match_table = st7703_of_match,
614 	},
615 };
616 module_mipi_dsi_driver(st7703_driver);
617 
618 MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>");
619 MODULE_DESCRIPTION("DRM driver for Sitronix ST7703 based MIPI DSI panels");
620 MODULE_LICENSE("GPL v2");
621