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