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