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