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