xref: /linux/drivers/gpu/drm/panel/panel-sitronix-st7703.c (revision 90d32e92011eaae8e70a9169b4e7acf4ca8f9d3a)
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 	enum drm_panel_orientation orientation;
66 };
67 
68 struct st7703_panel_desc {
69 	const struct drm_display_mode *mode;
70 	unsigned int lanes;
71 	unsigned long mode_flags;
72 	enum mipi_dsi_pixel_format format;
73 	int (*init_sequence)(struct st7703 *ctx);
74 };
75 
76 static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
77 {
78 	return container_of(panel, struct st7703, panel);
79 }
80 
81 static int jh057n_init_sequence(struct st7703 *ctx)
82 {
83 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
84 
85 	/*
86 	 * Init sequence was supplied by the panel vendor. Most of the commands
87 	 * resemble the ST7703 but the number of parameters often don't match
88 	 * so it's likely a clone.
89 	 */
90 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEXTC,
91 				   0xF1, 0x12, 0x83);
92 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETRGBIF,
93 				   0x10, 0x10, 0x05, 0x05, 0x03, 0xFF, 0x00, 0x00,
94 				   0x00, 0x00);
95 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETSCR,
96 				   0x73, 0x73, 0x50, 0x50, 0x00, 0x00, 0x08, 0x70,
97 				   0x00);
98 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
99 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
100 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
101 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETDISP, 0xF0, 0x12, 0x30);
102 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETEQ,
103 				   0x07, 0x07, 0x0B, 0x0B, 0x03, 0x0B, 0x00, 0x00,
104 				   0x00, 0x00, 0xFF, 0x00, 0xC0, 0x10);
105 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETBGP, 0x08, 0x08);
106 	msleep(20);
107 
108 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F);
109 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
110 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1,
111 				   0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12,
112 				   0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
113 				   0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
114 				   0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
115 				   0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
116 				   0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
117 				   0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118 				   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
119 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP2,
120 				   0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 				   0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
122 				   0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
123 				   0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
124 				   0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
125 				   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 				   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A,
127 				   0xA5, 0x00, 0x00, 0x00, 0x00);
128 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_SETGAMMA,
129 				   0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41, 0x37,
130 				   0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10, 0x11,
131 				   0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 0x41,
132 				   0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 0x10,
133 				   0x11, 0x18);
134 	msleep(20);
135 
136 	return 0;
137 }
138 
139 static const struct drm_display_mode jh057n00900_mode = {
140 	.hdisplay    = 720,
141 	.hsync_start = 720 + 90,
142 	.hsync_end   = 720 + 90 + 20,
143 	.htotal	     = 720 + 90 + 20 + 20,
144 	.vdisplay    = 1440,
145 	.vsync_start = 1440 + 20,
146 	.vsync_end   = 1440 + 20 + 4,
147 	.vtotal	     = 1440 + 20 + 4 + 12,
148 	.clock	     = 75276,
149 	.flags	     = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
150 	.width_mm    = 65,
151 	.height_mm   = 130,
152 };
153 
154 static const struct st7703_panel_desc jh057n00900_panel_desc = {
155 	.mode = &jh057n00900_mode,
156 	.lanes = 4,
157 	.mode_flags = MIPI_DSI_MODE_VIDEO |
158 		MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
159 	.format = MIPI_DSI_FMT_RGB888,
160 	.init_sequence = jh057n_init_sequence,
161 };
162 
163 static int xbd599_init_sequence(struct st7703 *ctx)
164 {
165 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
166 
167 	/*
168 	 * Init sequence was supplied by the panel vendor.
169 	 */
170 
171 	/* Magic sequence to unlock user commands below. */
172 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xF1, 0x12, 0x83);
173 
174 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI,
175 			       0x33, /* VC_main = 0, Lane_Number = 3 (4 lanes) */
176 			       0x81, /* DSI_LDO_SEL = 1.7V, RTERM = 90 Ohm */
177 			       0x05, /* IHSRX = x6 (Low High Speed driving ability) */
178 			       0xF9, /* TX_CLK_SEL = fDSICLK/16 */
179 			       0x0E, /* HFP_OSC (min. HFP number in DSI mode) */
180 			       0x0E, /* HBP_OSC (min. HBP number in DSI mode) */
181 			       /* The rest is undocumented in ST7703 datasheet */
182 			       0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 			       0x44, 0x25, 0x00, 0x91, 0x0a, 0x00, 0x00, 0x02,
184 			       0x4F, 0x11, 0x00, 0x00, 0x37);
185 
186 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT,
187 			       0x25, /* PCCS = 2, ECP_DC_DIV = 1/4 HSYNC */
188 			       0x22, /* DT = 15ms XDK_ECP = x2 */
189 			       0x20, /* PFM_DC_DIV = /1 */
190 			       0x03  /* ECP_SYNC_EN = 1, VGX_SYNC_EN = 1 */);
191 
192 	/* RGB I/F porch timing */
193 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF,
194 			       0x10, /* VBP_RGB_GEN */
195 			       0x10, /* VFP_RGB_GEN */
196 			       0x05, /* DE_BP_RGB_GEN */
197 			       0x05, /* DE_FP_RGB_GEN */
198 			       /* The rest is undocumented in ST7703 datasheet */
199 			       0x03, 0xFF,
200 			       0x00, 0x00,
201 			       0x00, 0x00);
202 
203 	/* Source driving settings. */
204 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR,
205 			       0x73, /* N_POPON */
206 			       0x73, /* N_NOPON */
207 			       0x50, /* I_POPON */
208 			       0x50, /* I_NOPON */
209 			       0x00, /* SCR[31,24] */
210 			       0xC0, /* SCR[23,16] */
211 			       0x08, /* SCR[15,8] */
212 			       0x70, /* SCR[7,0] */
213 			       0x00  /* Undocumented */);
214 
215 	/* NVDDD_SEL = -1.8V, VDDD_SEL = out of range (possibly 1.9V?) */
216 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x4E);
217 
218 	/*
219 	 * SS_PANEL = 1 (reverse scan), GS_PANEL = 0 (normal scan)
220 	 * REV_PANEL = 1 (normally black panel), BGR_PANEL = 1 (BGR)
221 	 */
222 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0B);
223 
224 	/* Zig-Zag Type C column inversion. */
225 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
226 
227 	/* Set display resolution. */
228 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP,
229 			       0xF0, /* NL = 240 */
230 			       0x12, /* RES_V_LSB = 0, BLK_CON = VSSD,
231 				      * RESO_SEL = 720RGB
232 				      */
233 			       0xF0  /* WHITE_GND_EN = 1 (GND),
234 				      * WHITE_FRAME_SEL = 7 frames,
235 				      * ISC = 0 frames
236 				      */);
237 
238 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ,
239 			       0x00, /* PNOEQ */
240 			       0x00, /* NNOEQ */
241 			       0x0B, /* PEQGND */
242 			       0x0B, /* NEQGND */
243 			       0x10, /* PEQVCI */
244 			       0x10, /* NEQVCI */
245 			       0x00, /* PEQVCI1 */
246 			       0x00, /* NEQVCI1 */
247 			       0x00, /* reserved */
248 			       0x00, /* reserved */
249 			       0xFF, /* reserved */
250 			       0x00, /* reserved */
251 			       0xC0, /* ESD_DET_DATA_WHITE = 1, ESD_WHITE_EN = 1 */
252 			       0x10  /* SLPIN_OPTION = 1 (no need vsync after sleep-in)
253 				      * VEDIO_NO_CHECK_EN = 0
254 				      * ESD_WHITE_GND_EN = 0
255 				      * ESD_DET_TIME_SEL = 0 frames
256 				      */);
257 
258 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x01, 0x00, 0xFF, 0xFF, 0x00);
259 
260 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,
261 			       0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
262 			       0x00, /* FBOFF_VGH = 0, FBOFF_VGL = 0 */
263 			       0x32, /* VRP  */
264 			       0x32, /* VRN */
265 			       0x77, /* reserved */
266 			       0xF1, /* APS = 1 (small),
267 				      * VGL_DET_EN = 1, VGH_DET_EN = 1,
268 				      * VGL_TURBO = 1, VGH_TURBO = 1
269 				      */
270 			       0xFF, /* VGH1_L_DIV, VGL1_L_DIV (1.5MHz) */
271 			       0xFF, /* VGH1_R_DIV, VGL1_R_DIV (1.5MHz) */
272 			       0xCC, /* VGH2_L_DIV, VGL2_L_DIV (2.6MHz) */
273 			       0xCC, /* VGH2_R_DIV, VGL2_R_DIV (2.6MHz) */
274 			       0x77, /* VGH3_L_DIV, VGL3_L_DIV (4.5MHz) */
275 			       0x77  /* VGH3_R_DIV, VGL3_R_DIV (4.5MHz) */);
276 
277 	/* Reference voltage. */
278 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
279 			       0x07, /* VREF_SEL = 4.2V */
280 			       0x07  /* NVREF_SEL = 4.2V */);
281 
282 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
283 			       0x2C, /* VCOMDC_F = -0.67V */
284 			       0x2C  /* VCOMDC_B = -0.67V */);
285 
286 	/* Undocumented command. */
287 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
288 
289 	/* This command is to set forward GIP timing. */
290 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1,
291 			       0x82, 0x10, 0x06, 0x05, 0xA2, 0x0A, 0xA5, 0x12,
292 			       0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38,
293 			       0x0C, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00,
294 			       0x03, 0x00, 0x00, 0x00, 0x75, 0x75, 0x31, 0x88,
295 			       0x88, 0x88, 0x88, 0x88, 0x88, 0x13, 0x88, 0x64,
296 			       0x64, 0x20, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
297 			       0x02, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
299 
300 	/* This command is to set backward GIP timing. */
301 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2,
302 			       0x02, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 			       0x00, 0x00, 0x00, 0x00, 0x02, 0x46, 0x02, 0x88,
304 			       0x88, 0x88, 0x88, 0x88, 0x88, 0x64, 0x88, 0x13,
305 			       0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
306 			       0x75, 0x88, 0x23, 0x14, 0x00, 0x00, 0x02, 0x00,
307 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A,
309 			       0xA5, 0x00, 0x00, 0x00, 0x00);
310 
311 	/* Adjust the gamma characteristics of the panel. */
312 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA,
313 			       0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41, 0x35,
314 			       0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12, 0x12,
315 			       0x18, 0x00, 0x09, 0x0D, 0x23, 0x27, 0x3C, 0x41,
316 			       0x35, 0x07, 0x0D, 0x0E, 0x12, 0x13, 0x10, 0x12,
317 			       0x12, 0x18);
318 
319 	return 0;
320 }
321 
322 static const struct drm_display_mode xbd599_mode = {
323 	.hdisplay    = 720,
324 	.hsync_start = 720 + 40,
325 	.hsync_end   = 720 + 40 + 40,
326 	.htotal	     = 720 + 40 + 40 + 40,
327 	.vdisplay    = 1440,
328 	.vsync_start = 1440 + 18,
329 	.vsync_end   = 1440 + 18 + 10,
330 	.vtotal	     = 1440 + 18 + 10 + 17,
331 	.clock	     = 69000,
332 	.flags	     = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
333 	.width_mm    = 68,
334 	.height_mm   = 136,
335 };
336 
337 static const struct st7703_panel_desc xbd599_desc = {
338 	.mode = &xbd599_mode,
339 	.lanes = 4,
340 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
341 	.format = MIPI_DSI_FMT_RGB888,
342 	.init_sequence = xbd599_init_sequence,
343 };
344 
345 static int rg353v2_init_sequence(struct st7703 *ctx)
346 {
347 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
348 
349 	/*
350 	 * Init sequence was supplied by the panel vendor.
351 	 */
352 
353 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
354 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00,
355 			       0xda, 0x80);
356 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x00, 0x13, 0x70);
357 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
358 			       0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
359 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
360 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x0a, 0x0a);
361 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x92, 0x92);
362 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22,
363 			       0xf0, 0x63);
364 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05,
365 			       0xf9, 0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00,
366 			       0x00, 0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a,
367 			       0x00, 0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
368 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x47);
369 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
370 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
371 			       0x00, 0x00, 0x12, 0x50, 0x00);
372 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x53, 0xc0, 0x32,
373 			       0x32, 0x77, 0xe1, 0xdd, 0xdd, 0x77, 0x77, 0x33,
374 			       0x33);
375 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff,
376 			       0x00, 0xff);
377 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00,
378 			       0x00, 0x00);
379 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e,
380 			       0x02);
381 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
382 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0d,
383 			       0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c, 0x0d,
384 			       0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a, 0x00, 0x07,
385 			       0x0d, 0x37, 0x35, 0x3f, 0x41, 0x44, 0x06, 0x0c,
386 			       0x0d, 0x0f, 0x11, 0x10, 0x12, 0x14, 0x1a);
387 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
388 			       0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
389 			       0xc0, 0x10);
390 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x02, 0x00,
391 			       0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x80,
392 			       0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
393 			       0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
394 			       0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,
395 			       0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,
396 			       0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
397 			       0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398 			       0x00, 0x00, 0x00);
399 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,
400 			       0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401 			       0x81, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,
402 			       0x88, 0x88, 0x88, 0x80, 0x88, 0xba, 0x06, 0x42,
403 			       0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
404 			       0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
405 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
407 			       0x00);
408 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01);
409 
410 	return 0;
411 }
412 
413 static const struct drm_display_mode rg353v2_mode = {
414 	.hdisplay	= 640,
415 	.hsync_start	= 640 + 40,
416 	.hsync_end	= 640 + 40 + 2,
417 	.htotal		= 640 + 40 + 2 + 80,
418 	.vdisplay	= 480,
419 	.vsync_start	= 480 + 18,
420 	.vsync_end	= 480 + 18 + 2,
421 	.vtotal		= 480 + 18 + 2 + 28,
422 	.clock		= 24150,
423 	.flags		= DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
424 	.width_mm	= 70,
425 	.height_mm	= 57,
426 };
427 
428 static const struct st7703_panel_desc rg353v2_desc = {
429 	.mode = &rg353v2_mode,
430 	.lanes = 4,
431 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
432 		      MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM,
433 	.format = MIPI_DSI_FMT_RGB888,
434 	.init_sequence = rg353v2_init_sequence,
435 };
436 
437 static int rgb30panel_init_sequence(struct st7703 *ctx)
438 {
439 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
440 
441 	/* Init sequence extracted from Powkiddy RGB30 BSP kernel. */
442 
443 	/*
444 	 * For some reason this specific panel must be taken out of sleep
445 	 * before the full init sequence, or else it will not display.
446 	 */
447 	mipi_dsi_dcs_exit_sleep_mode(dsi);
448 	msleep(250);
449 
450 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
451 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9,
452 			       0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
453 			       0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00,
454 			       0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
455 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0,
456 			       0x63);
457 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
458 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
459 			       0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
460 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
461 			       0x00, 0x00, 0x12, 0x70, 0x00);
462 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x46);
463 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
464 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
465 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x3c, 0x12, 0x30);
466 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
467 			       0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
468 			       0xc0, 0x10);
469 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x36, 0x00, 0x32,
470 			       0x32, 0x77, 0xf1, 0xcc, 0xcc, 0x77, 0x77, 0x33,
471 			       0x33);
472 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x0a, 0x0a);
473 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x88, 0x88);
474 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x0a, 0x10,
475 			       0x0f, 0xa1, 0x80, 0x12, 0x31, 0x23, 0x47, 0x86,
476 			       0xa1, 0x80, 0x47, 0x08, 0x00, 0x00, 0x0d, 0x00,
477 			       0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
478 			       0x48, 0x02, 0x8b, 0xaf, 0x46, 0x02, 0x88, 0x88,
479 			       0x88, 0x88, 0x88, 0x48, 0x13, 0x8b, 0xaf, 0x57,
480 			       0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
481 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482 			       0x00, 0x00, 0x00);
483 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x96, 0x12, 0x01, 0x01,
484 			       0x01, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
485 			       0x4f, 0x31, 0x8b, 0xa8, 0x31, 0x75, 0x88, 0x88,
486 			       0x88, 0x88, 0x88, 0x4f, 0x20, 0x8b, 0xa8, 0x20,
487 			       0x64, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00,
488 			       0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
489 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 			       0x00, 0x00, 0x40, 0xa1, 0x80, 0x00, 0x00, 0x00,
491 			       0x00);
492 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x0a, 0x0f,
493 			       0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d, 0x10,
494 			       0x13, 0x15, 0x14, 0x15, 0x10, 0x17, 0x00, 0x0a,
495 			       0x0f, 0x29, 0x3b, 0x3f, 0x42, 0x39, 0x06, 0x0d,
496 			       0x10, 0x13, 0x15, 0x14, 0x15, 0x10, 0x17);
497 
498 	return 0;
499 }
500 
501 static const struct drm_display_mode rgb30panel_mode = {
502 	.hdisplay	= 720,
503 	.hsync_start	= 720 + 45,
504 	.hsync_end	= 720 + 45 + 4,
505 	.htotal		= 720 + 45 + 4 + 45,
506 	.vdisplay	= 720,
507 	.vsync_start	= 720 + 15,
508 	.vsync_end	= 720 + 15 + 3,
509 	.vtotal		= 720 + 15 + 3 + 11,
510 	.clock		= 36570,
511 	.flags		= DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
512 	.width_mm	= 76,
513 	.height_mm	= 76,
514 };
515 
516 static const struct st7703_panel_desc rgb30panel_desc = {
517 	.mode = &rgb30panel_mode,
518 	.lanes = 4,
519 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
520 		      MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM,
521 	.format = MIPI_DSI_FMT_RGB888,
522 	.init_sequence = rgb30panel_init_sequence,
523 };
524 
525 static int rgb10max3_panel_init_sequence(struct st7703 *ctx)
526 {
527 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
528 
529 	/* Init sequence extracted from Powkiddy RGB10MAX3 BSP kernel. */
530 
531 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
532 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETAPID, 0x00, 0x00, 0x00, 0xda,
533 			       0x80);
534 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0xc8, 0x02, 0x30);
535 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x10, 0x10, 0x28,
536 			       0x28, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
537 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
538 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x04, 0x04);
539 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x78, 0x78);
540 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25, 0x22, 0xf0,
541 			       0x63);
542 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x33, 0x81, 0x05, 0xf9,
543 			       0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
544 			       0x00, 0x00, 0x44, 0x25, 0x00, 0x90, 0x0a, 0x00,
545 			       0x00, 0x01, 0x4f, 0x01, 0x00, 0x00, 0x37);
546 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x47);
547 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
548 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
549 			       0x00, 0x00, 0x12, 0x70, 0x00);
550 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x25, 0x00, 0x32,
551 			       0x32, 0x77, 0xe1, 0xff, 0xff, 0xcc, 0xcc, 0x77,
552 			       0x77);
553 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x82, 0x00, 0xbf, 0xff,
554 			       0x00, 0xff);
555 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETIO, 0xb8, 0x00, 0x0a, 0x00,
556 			       0x00, 0x00);
557 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCABC, 0x10, 0x40, 0x1e,
558 			       0x02);
559 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
560 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x04, 0x07,
561 			       0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b, 0x0e,
562 			       0x12, 0x14, 0x12, 0x13, 0x0f, 0x17, 0x00, 0x04,
563 			       0x07, 0x2a, 0x39, 0x3f, 0x36, 0x31, 0x06, 0x0b,
564 			       0x0e, 0x12, 0x14, 0x12, 0x13, 0x0f, 0x17);
565 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x03, 0x03, 0x03, 0x03,
566 			       0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80,
567 			       0xc0, 0x10);
568 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0xc8, 0x10, 0x08, 0x00,
569 			       0x00, 0x41, 0xf8, 0x12, 0x31, 0x23, 0x37, 0x86,
570 			       0x11, 0xc8, 0x37, 0x2a, 0x00, 0x00, 0x0c, 0x00,
571 			       0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
572 			       0x88, 0x20, 0x46, 0x02, 0x88, 0x88, 0x88, 0x88,
573 			       0x88, 0x88, 0xff, 0x88, 0x31, 0x57, 0x13, 0x88,
574 			       0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0x00, 0x00,
575 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 			       0x00, 0x00, 0x00);
577 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x00, 0x1a, 0x00, 0x00,
578 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 			       0x8f, 0x13, 0x31, 0x75, 0x88, 0x88, 0x88, 0x88,
580 			       0x88, 0x88, 0xf8, 0x8f, 0x02, 0x20, 0x64, 0x88,
581 			       0x88, 0x88, 0x88, 0x88, 0x88, 0xf8, 0x00, 0x00,
582 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585 			       0x00);
586 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_EF, 0xff, 0xff, 0x01);
587 
588 	return 0;
589 }
590 
591 static const struct drm_display_mode rgb10max3_panel_mode = {
592 	.hdisplay	= 720,
593 	.hsync_start	= 720 + 40,
594 	.hsync_end	= 720 + 40 + 10,
595 	.htotal		= 720 + 40 + 10 + 40,
596 	.vdisplay	= 1280,
597 	.vsync_start	= 1280 + 16,
598 	.vsync_end	= 1280 + 16 + 4,
599 	.vtotal		= 1280 + 16 + 4 + 14,
600 	.clock		= 63800,
601 	.flags		= DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
602 	.width_mm	= 62,
603 	.height_mm	= 109,
604 };
605 
606 static const struct st7703_panel_desc rgb10max3_panel_desc = {
607 	.mode = &rgb10max3_panel_mode,
608 	.lanes = 4,
609 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
610 		      MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM,
611 	.format = MIPI_DSI_FMT_RGB888,
612 	.init_sequence = rgb10max3_panel_init_sequence,
613 };
614 
615 static int gameforcechi_init_sequence(struct st7703 *ctx)
616 {
617 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
618 
619 	/*
620 	 * Init sequence was supplied by the panel vendor. Panel will not
621 	 * respond to commands until it is brought out of sleep mode first.
622 	 */
623 
624 	mipi_dsi_dcs_exit_sleep_mode(dsi);
625 	msleep(250);
626 
627 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEXTC, 0xf1, 0x12, 0x83);
628 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETMIPI, 0x31, 0x81, 0x05, 0xf9,
629 			       0x0e, 0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
630 			       0x00, 0x00, 0x44, 0x25, 0x00, 0x91, 0x0a, 0x00,
631 			       0x00, 0x02, 0x4f, 0xd1, 0x00, 0x00, 0x37);
632 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER_EXT, 0x25);
633 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_BF, 0x02, 0x11, 0x00);
634 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETRGBIF, 0x0c, 0x10, 0x0a,
635 			       0x50, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00);
636 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETSCR, 0x73, 0x73, 0x50, 0x50,
637 			       0x00, 0x00, 0x08, 0x70, 0x00);
638 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVDC, 0x46);
639 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPANEL, 0x0b);
640 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETCYC, 0x80);
641 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETDISP, 0x00, 0x13, 0xf0);
642 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETEQ, 0x07, 0x07, 0x0b, 0x0b,
643 			       0x03, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
644 			       0xc0, 0x10);
645 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER, 0x53, 0x00, 0x1e,
646 			       0x1e, 0x77, 0xe1, 0xcc, 0xdd, 0x67, 0x77, 0x33,
647 			       0x33);
648 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP, 0x10, 0x10);
649 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM, 0x6c, 0x7c);
650 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP1, 0x08, 0x00, 0x0e, 0x00,
651 			       0x00, 0xb0, 0xb1, 0x11, 0x31, 0x23, 0x28, 0x10,
652 			       0xb0, 0xb1, 0x27, 0x08, 0x00, 0x04, 0x02, 0x00,
653 			       0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00,
654 			       0x88, 0x88, 0xba, 0x60, 0x24, 0x08, 0x88, 0x88,
655 			       0x88, 0x88, 0x88, 0x88, 0x88, 0xba, 0x71, 0x35,
656 			       0x18, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
657 			       0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 			       0x00, 0x00, 0x00);
659 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGIP2, 0x97, 0x0a, 0x82, 0x02,
660 			       0x13, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 			       0x80, 0x88, 0xba, 0x17, 0x53, 0x88, 0x88, 0x88,
662 			       0x88, 0x88, 0x88, 0x81, 0x88, 0xba, 0x06, 0x42,
663 			       0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x10,
664 			       0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
665 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 			       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 			       0x00);
668 	mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETGAMMA, 0x00, 0x07, 0x0b,
669 			       0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0x0a, 0x0b,
670 			       0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18, 0x00, 0x07,
671 			       0x0b, 0x27, 0x2d, 0x3f, 0x3b, 0x37, 0x05, 0xa0,
672 			       0x0b, 0x0f, 0x11, 0x0f, 0x12, 0x12, 0x18);
673 
674 	return 0;
675 }
676 
677 static const struct drm_display_mode gameforcechi_mode = {
678 	.hdisplay	= 640,
679 	.hsync_start	= 640 + 40,
680 	.hsync_end	= 640 + 40 + 2,
681 	.htotal		= 640 + 40 + 2 + 80,
682 	.vdisplay	= 480,
683 	.vsync_start	= 480 + 17,
684 	.vsync_end	= 480 + 17 + 5,
685 	.vtotal		= 480 + 17 + 5 + 13,
686 	.clock		= 23546,
687 	.flags		= DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
688 	.width_mm	= 71,
689 	.height_mm	= 53,
690 };
691 
692 static const struct st7703_panel_desc gameforcechi_desc = {
693 	.mode = &gameforcechi_mode,
694 	.lanes = 2,
695 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
696 		      MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_LPM,
697 	.format = MIPI_DSI_FMT_RGB888,
698 	.init_sequence = gameforcechi_init_sequence,
699 };
700 
701 static int st7703_enable(struct drm_panel *panel)
702 {
703 	struct st7703 *ctx = panel_to_st7703(panel);
704 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
705 	int ret;
706 
707 	ret = ctx->desc->init_sequence(ctx);
708 	if (ret < 0) {
709 		dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
710 		return ret;
711 	}
712 
713 	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
714 	if (ret < 0) {
715 		dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
716 		return ret;
717 	}
718 
719 	/* It takes the controller 120 msec to wake up after sleep. */
720 	msleep(120);
721 
722 	ret = mipi_dsi_dcs_set_display_on(dsi);
723 	if (ret)
724 		return ret;
725 
726 	dev_dbg(ctx->dev, "Panel init sequence done\n");
727 
728 	return 0;
729 }
730 
731 static int st7703_disable(struct drm_panel *panel)
732 {
733 	struct st7703 *ctx = panel_to_st7703(panel);
734 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
735 	int ret;
736 
737 	ret = mipi_dsi_dcs_set_display_off(dsi);
738 	if (ret < 0)
739 		dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret);
740 
741 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
742 	if (ret < 0)
743 		dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
744 
745 	/* It takes the controller 120 msec to enter sleep mode. */
746 	msleep(120);
747 
748 	return 0;
749 }
750 
751 static int st7703_unprepare(struct drm_panel *panel)
752 {
753 	struct st7703 *ctx = panel_to_st7703(panel);
754 
755 	if (!ctx->prepared)
756 		return 0;
757 
758 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
759 	regulator_disable(ctx->iovcc);
760 	regulator_disable(ctx->vcc);
761 	ctx->prepared = false;
762 
763 	return 0;
764 }
765 
766 static int st7703_prepare(struct drm_panel *panel)
767 {
768 	struct st7703 *ctx = panel_to_st7703(panel);
769 	int ret;
770 
771 	if (ctx->prepared)
772 		return 0;
773 
774 	dev_dbg(ctx->dev, "Resetting the panel\n");
775 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
776 
777 	ret = regulator_enable(ctx->iovcc);
778 	if (ret < 0) {
779 		dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
780 		return ret;
781 	}
782 
783 	ret = regulator_enable(ctx->vcc);
784 	if (ret < 0) {
785 		dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
786 		regulator_disable(ctx->iovcc);
787 		return ret;
788 	}
789 
790 	/* Give power supplies time to stabilize before deasserting reset. */
791 	usleep_range(10000, 20000);
792 
793 	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
794 	usleep_range(15000, 20000);
795 
796 	ctx->prepared = true;
797 
798 	return 0;
799 }
800 
801 static const u32 mantix_bus_formats[] = {
802 	MEDIA_BUS_FMT_RGB888_1X24,
803 };
804 
805 static int st7703_get_modes(struct drm_panel *panel,
806 			    struct drm_connector *connector)
807 {
808 	struct st7703 *ctx = panel_to_st7703(panel);
809 	struct drm_display_mode *mode;
810 
811 	mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
812 	if (!mode) {
813 		dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
814 			ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
815 			drm_mode_vrefresh(ctx->desc->mode));
816 		return -ENOMEM;
817 	}
818 
819 	drm_mode_set_name(mode);
820 
821 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
822 	connector->display_info.width_mm = mode->width_mm;
823 	connector->display_info.height_mm = mode->height_mm;
824 	drm_mode_probed_add(connector, mode);
825 
826 	drm_display_info_set_bus_formats(&connector->display_info,
827 					 mantix_bus_formats,
828 					 ARRAY_SIZE(mantix_bus_formats));
829 
830 	return 1;
831 }
832 
833 static enum drm_panel_orientation st7703_get_orientation(struct drm_panel *panel)
834 {
835 	struct st7703 *st7703 = panel_to_st7703(panel);
836 
837 	return st7703->orientation;
838 }
839 
840 static const struct drm_panel_funcs st7703_drm_funcs = {
841 	.disable   = st7703_disable,
842 	.unprepare = st7703_unprepare,
843 	.prepare   = st7703_prepare,
844 	.enable	   = st7703_enable,
845 	.get_modes = st7703_get_modes,
846 	.get_orientation = st7703_get_orientation,
847 };
848 
849 static int allpixelson_set(void *data, u64 val)
850 {
851 	struct st7703 *ctx = data;
852 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
853 
854 	dev_dbg(ctx->dev, "Setting all pixels on\n");
855 	mipi_dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
856 	msleep(val * 1000);
857 	/* Reset the panel to get video back */
858 	drm_panel_disable(&ctx->panel);
859 	drm_panel_unprepare(&ctx->panel);
860 	drm_panel_prepare(&ctx->panel);
861 	drm_panel_enable(&ctx->panel);
862 
863 	return 0;
864 }
865 
866 DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL,
867 			allpixelson_set, "%llu\n");
868 
869 static void st7703_debugfs_init(struct st7703 *ctx)
870 {
871 	ctx->debugfs = debugfs_create_dir(DRV_NAME, NULL);
872 
873 	debugfs_create_file("allpixelson", 0600, ctx->debugfs, ctx,
874 			    &allpixelson_fops);
875 }
876 
877 static void st7703_debugfs_remove(struct st7703 *ctx)
878 {
879 	debugfs_remove_recursive(ctx->debugfs);
880 	ctx->debugfs = NULL;
881 }
882 
883 static int st7703_probe(struct mipi_dsi_device *dsi)
884 {
885 	struct device *dev = &dsi->dev;
886 	struct st7703 *ctx;
887 	int ret;
888 
889 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
890 	if (!ctx)
891 		return -ENOMEM;
892 
893 	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
894 	if (IS_ERR(ctx->reset_gpio))
895 		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n");
896 
897 	mipi_dsi_set_drvdata(dsi, ctx);
898 
899 	ctx->dev = dev;
900 	ctx->desc = of_device_get_match_data(dev);
901 
902 	dsi->mode_flags = ctx->desc->mode_flags;
903 	dsi->format = ctx->desc->format;
904 	dsi->lanes = ctx->desc->lanes;
905 
906 	ctx->vcc = devm_regulator_get(dev, "vcc");
907 	if (IS_ERR(ctx->vcc))
908 		return dev_err_probe(dev, PTR_ERR(ctx->vcc), "Failed to request vcc regulator\n");
909 
910 	ctx->iovcc = devm_regulator_get(dev, "iovcc");
911 	if (IS_ERR(ctx->iovcc))
912 		return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
913 				     "Failed to request iovcc regulator\n");
914 
915 	ret = of_drm_get_panel_orientation(dsi->dev.of_node, &ctx->orientation);
916 	if (ret < 0)
917 		return dev_err_probe(&dsi->dev, ret, "Failed to get orientation\n");
918 
919 	drm_panel_init(&ctx->panel, dev, &st7703_drm_funcs,
920 		       DRM_MODE_CONNECTOR_DSI);
921 
922 	ret = drm_panel_of_backlight(&ctx->panel);
923 	if (ret)
924 		return ret;
925 
926 	drm_panel_add(&ctx->panel);
927 
928 	ret = mipi_dsi_attach(dsi);
929 	if (ret < 0) {
930 		dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);
931 		drm_panel_remove(&ctx->panel);
932 		return ret;
933 	}
934 
935 	dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
936 		 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
937 		 drm_mode_vrefresh(ctx->desc->mode),
938 		 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
939 
940 	st7703_debugfs_init(ctx);
941 	return 0;
942 }
943 
944 static void st7703_shutdown(struct mipi_dsi_device *dsi)
945 {
946 	struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
947 	int ret;
948 
949 	ret = drm_panel_unprepare(&ctx->panel);
950 	if (ret < 0)
951 		dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
952 
953 	ret = drm_panel_disable(&ctx->panel);
954 	if (ret < 0)
955 		dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
956 }
957 
958 static void st7703_remove(struct mipi_dsi_device *dsi)
959 {
960 	struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
961 	int ret;
962 
963 	st7703_shutdown(dsi);
964 
965 	ret = mipi_dsi_detach(dsi);
966 	if (ret < 0)
967 		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
968 
969 	drm_panel_remove(&ctx->panel);
970 
971 	st7703_debugfs_remove(ctx);
972 }
973 
974 static const struct of_device_id st7703_of_match[] = {
975 	{ .compatible = "anbernic,rg353v-panel-v2", .data = &rg353v2_desc },
976 	{ .compatible = "gameforce,chi-panel", .data = &gameforcechi_desc },
977 	{ .compatible = "powkiddy,rgb10max3-panel", .data = &rgb10max3_panel_desc },
978 	{ .compatible = "powkiddy,rgb30-panel", .data = &rgb30panel_desc },
979 	{ .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc },
980 	{ .compatible = "xingbangda,xbd599", .data = &xbd599_desc },
981 	{ /* sentinel */ }
982 };
983 MODULE_DEVICE_TABLE(of, st7703_of_match);
984 
985 static struct mipi_dsi_driver st7703_driver = {
986 	.probe	= st7703_probe,
987 	.remove = st7703_remove,
988 	.shutdown = st7703_shutdown,
989 	.driver = {
990 		.name = DRV_NAME,
991 		.of_match_table = st7703_of_match,
992 	},
993 };
994 module_mipi_dsi_driver(st7703_driver);
995 
996 MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>");
997 MODULE_DESCRIPTION("DRM driver for Sitronix ST7703 based MIPI DSI panels");
998 MODULE_LICENSE("GPL v2");
999