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