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