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