]> Git Repo - linux.git/blob - drivers/gpu/drm/panel/panel-sitronix-st7703.c
Merge tag 'rpmsg-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc...
[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         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 st7703_enable(struct drm_panel *panel)
616 {
617         struct st7703 *ctx = panel_to_st7703(panel);
618         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
619         int ret;
620
621         ret = ctx->desc->init_sequence(ctx);
622         if (ret < 0) {
623                 dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
624                 return ret;
625         }
626
627         ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
628         if (ret < 0) {
629                 dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
630                 return ret;
631         }
632
633         /* It takes the controller 120 msec to wake up after sleep. */
634         msleep(120);
635
636         ret = mipi_dsi_dcs_set_display_on(dsi);
637         if (ret)
638                 return ret;
639
640         dev_dbg(ctx->dev, "Panel init sequence done\n");
641
642         return 0;
643 }
644
645 static int st7703_disable(struct drm_panel *panel)
646 {
647         struct st7703 *ctx = panel_to_st7703(panel);
648         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
649         int ret;
650
651         ret = mipi_dsi_dcs_set_display_off(dsi);
652         if (ret < 0)
653                 dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret);
654
655         ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
656         if (ret < 0)
657                 dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
658
659         /* It takes the controller 120 msec to enter sleep mode. */
660         msleep(120);
661
662         return 0;
663 }
664
665 static int st7703_unprepare(struct drm_panel *panel)
666 {
667         struct st7703 *ctx = panel_to_st7703(panel);
668
669         if (!ctx->prepared)
670                 return 0;
671
672         gpiod_set_value_cansleep(ctx->reset_gpio, 1);
673         regulator_disable(ctx->iovcc);
674         regulator_disable(ctx->vcc);
675         ctx->prepared = false;
676
677         return 0;
678 }
679
680 static int st7703_prepare(struct drm_panel *panel)
681 {
682         struct st7703 *ctx = panel_to_st7703(panel);
683         int ret;
684
685         if (ctx->prepared)
686                 return 0;
687
688         dev_dbg(ctx->dev, "Resetting the panel\n");
689         gpiod_set_value_cansleep(ctx->reset_gpio, 1);
690
691         ret = regulator_enable(ctx->iovcc);
692         if (ret < 0) {
693                 dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
694                 return ret;
695         }
696
697         ret = regulator_enable(ctx->vcc);
698         if (ret < 0) {
699                 dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
700                 regulator_disable(ctx->iovcc);
701                 return ret;
702         }
703
704         /* Give power supplies time to stabilize before deasserting reset. */
705         usleep_range(10000, 20000);
706
707         gpiod_set_value_cansleep(ctx->reset_gpio, 0);
708         usleep_range(15000, 20000);
709
710         ctx->prepared = true;
711
712         return 0;
713 }
714
715 static const u32 mantix_bus_formats[] = {
716         MEDIA_BUS_FMT_RGB888_1X24,
717 };
718
719 static int st7703_get_modes(struct drm_panel *panel,
720                             struct drm_connector *connector)
721 {
722         struct st7703 *ctx = panel_to_st7703(panel);
723         struct drm_display_mode *mode;
724
725         mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
726         if (!mode) {
727                 dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
728                         ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
729                         drm_mode_vrefresh(ctx->desc->mode));
730                 return -ENOMEM;
731         }
732
733         drm_mode_set_name(mode);
734
735         mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
736         connector->display_info.width_mm = mode->width_mm;
737         connector->display_info.height_mm = mode->height_mm;
738         drm_mode_probed_add(connector, mode);
739
740         drm_display_info_set_bus_formats(&connector->display_info,
741                                          mantix_bus_formats,
742                                          ARRAY_SIZE(mantix_bus_formats));
743
744         return 1;
745 }
746
747 static enum drm_panel_orientation st7703_get_orientation(struct drm_panel *panel)
748 {
749         struct st7703 *st7703 = panel_to_st7703(panel);
750
751         return st7703->orientation;
752 }
753
754 static const struct drm_panel_funcs st7703_drm_funcs = {
755         .disable   = st7703_disable,
756         .unprepare = st7703_unprepare,
757         .prepare   = st7703_prepare,
758         .enable    = st7703_enable,
759         .get_modes = st7703_get_modes,
760         .get_orientation = st7703_get_orientation,
761 };
762
763 static int allpixelson_set(void *data, u64 val)
764 {
765         struct st7703 *ctx = data;
766         struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
767
768         dev_dbg(ctx->dev, "Setting all pixels on\n");
769         mipi_dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
770         msleep(val * 1000);
771         /* Reset the panel to get video back */
772         drm_panel_disable(&ctx->panel);
773         drm_panel_unprepare(&ctx->panel);
774         drm_panel_prepare(&ctx->panel);
775         drm_panel_enable(&ctx->panel);
776
777         return 0;
778 }
779
780 DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL,
781                         allpixelson_set, "%llu\n");
782
783 static void st7703_debugfs_init(struct st7703 *ctx)
784 {
785         ctx->debugfs = debugfs_create_dir(DRV_NAME, NULL);
786
787         debugfs_create_file("allpixelson", 0600, ctx->debugfs, ctx,
788                             &allpixelson_fops);
789 }
790
791 static void st7703_debugfs_remove(struct st7703 *ctx)
792 {
793         debugfs_remove_recursive(ctx->debugfs);
794         ctx->debugfs = NULL;
795 }
796
797 static int st7703_probe(struct mipi_dsi_device *dsi)
798 {
799         struct device *dev = &dsi->dev;
800         struct st7703 *ctx;
801         int ret;
802
803         ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
804         if (!ctx)
805                 return -ENOMEM;
806
807         ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
808         if (IS_ERR(ctx->reset_gpio))
809                 return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n");
810
811         mipi_dsi_set_drvdata(dsi, ctx);
812
813         ctx->dev = dev;
814         ctx->desc = of_device_get_match_data(dev);
815
816         dsi->mode_flags = ctx->desc->mode_flags;
817         dsi->format = ctx->desc->format;
818         dsi->lanes = ctx->desc->lanes;
819
820         ctx->vcc = devm_regulator_get(dev, "vcc");
821         if (IS_ERR(ctx->vcc))
822                 return dev_err_probe(dev, PTR_ERR(ctx->vcc), "Failed to request vcc regulator\n");
823
824         ctx->iovcc = devm_regulator_get(dev, "iovcc");
825         if (IS_ERR(ctx->iovcc))
826                 return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
827                                      "Failed to request iovcc regulator\n");
828
829         ret = of_drm_get_panel_orientation(dsi->dev.of_node, &ctx->orientation);
830         if (ret < 0)
831                 return dev_err_probe(&dsi->dev, ret, "Failed to get orientation\n");
832
833         drm_panel_init(&ctx->panel, dev, &st7703_drm_funcs,
834                        DRM_MODE_CONNECTOR_DSI);
835
836         ret = drm_panel_of_backlight(&ctx->panel);
837         if (ret)
838                 return ret;
839
840         drm_panel_add(&ctx->panel);
841
842         ret = mipi_dsi_attach(dsi);
843         if (ret < 0) {
844                 dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);
845                 drm_panel_remove(&ctx->panel);
846                 return ret;
847         }
848
849         dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
850                  ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
851                  drm_mode_vrefresh(ctx->desc->mode),
852                  mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
853
854         st7703_debugfs_init(ctx);
855         return 0;
856 }
857
858 static void st7703_shutdown(struct mipi_dsi_device *dsi)
859 {
860         struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
861         int ret;
862
863         ret = drm_panel_unprepare(&ctx->panel);
864         if (ret < 0)
865                 dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
866
867         ret = drm_panel_disable(&ctx->panel);
868         if (ret < 0)
869                 dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
870 }
871
872 static void st7703_remove(struct mipi_dsi_device *dsi)
873 {
874         struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
875         int ret;
876
877         st7703_shutdown(dsi);
878
879         ret = mipi_dsi_detach(dsi);
880         if (ret < 0)
881                 dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
882
883         drm_panel_remove(&ctx->panel);
884
885         st7703_debugfs_remove(ctx);
886 }
887
888 static const struct of_device_id st7703_of_match[] = {
889         { .compatible = "anbernic,rg353v-panel-v2", .data = &rg353v2_desc },
890         { .compatible = "powkiddy,rgb10max3-panel", .data = &rgb10max3_panel_desc },
891         { .compatible = "powkiddy,rgb30-panel", .data = &rgb30panel_desc },
892         { .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc },
893         { .compatible = "xingbangda,xbd599", .data = &xbd599_desc },
894         { /* sentinel */ }
895 };
896 MODULE_DEVICE_TABLE(of, st7703_of_match);
897
898 static struct mipi_dsi_driver st7703_driver = {
899         .probe  = st7703_probe,
900         .remove = st7703_remove,
901         .shutdown = st7703_shutdown,
902         .driver = {
903                 .name = DRV_NAME,
904                 .of_match_table = st7703_of_match,
905         },
906 };
907 module_mipi_dsi_driver(st7703_driver);
908
909 MODULE_AUTHOR("Guido Günther <[email protected]>");
910 MODULE_DESCRIPTION("DRM driver for Sitronix ST7703 based MIPI DSI panels");
911 MODULE_LICENSE("GPL v2");
This page took 0.09001 seconds and 4 git commands to generate.