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