• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 
jh057n_init_sequence(struct st7703 * ctx)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 
xbd599_init_sequence(struct st7703 * ctx)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 
st7703_enable(struct drm_panel * panel)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 
st7703_disable(struct drm_panel * panel)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 
st7703_unprepare(struct drm_panel * panel)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 
st7703_prepare(struct drm_panel * panel)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 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
432 
433 	ret = regulator_enable(ctx->iovcc);
434 	if (ret < 0) {
435 		dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
436 		return ret;
437 	}
438 
439 	ret = regulator_enable(ctx->vcc);
440 	if (ret < 0) {
441 		dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
442 		regulator_disable(ctx->iovcc);
443 		return ret;
444 	}
445 
446 	/* Give power supplies time to stabilize before deasserting reset. */
447 	usleep_range(10000, 20000);
448 
449 	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
450 	usleep_range(15000, 20000);
451 
452 	ctx->prepared = true;
453 
454 	return 0;
455 }
456 
457 static const u32 mantix_bus_formats[] = {
458 	MEDIA_BUS_FMT_RGB888_1X24,
459 };
460 
st7703_get_modes(struct drm_panel * panel,struct drm_connector * connector)461 static int st7703_get_modes(struct drm_panel *panel,
462 			    struct drm_connector *connector)
463 {
464 	struct st7703 *ctx = panel_to_st7703(panel);
465 	struct drm_display_mode *mode;
466 
467 	mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
468 	if (!mode) {
469 		dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
470 			ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
471 			drm_mode_vrefresh(ctx->desc->mode));
472 		return -ENOMEM;
473 	}
474 
475 	drm_mode_set_name(mode);
476 
477 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
478 	connector->display_info.width_mm = mode->width_mm;
479 	connector->display_info.height_mm = mode->height_mm;
480 	drm_mode_probed_add(connector, mode);
481 
482 	drm_display_info_set_bus_formats(&connector->display_info,
483 					 mantix_bus_formats,
484 					 ARRAY_SIZE(mantix_bus_formats));
485 
486 	return 1;
487 }
488 
489 static const struct drm_panel_funcs st7703_drm_funcs = {
490 	.disable   = st7703_disable,
491 	.unprepare = st7703_unprepare,
492 	.prepare   = st7703_prepare,
493 	.enable	   = st7703_enable,
494 	.get_modes = st7703_get_modes,
495 };
496 
allpixelson_set(void * data,u64 val)497 static int allpixelson_set(void *data, u64 val)
498 {
499 	struct st7703 *ctx = data;
500 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
501 
502 	dev_dbg(ctx->dev, "Setting all pixels on\n");
503 	dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON);
504 	msleep(val * 1000);
505 	/* Reset the panel to get video back */
506 	drm_panel_disable(&ctx->panel);
507 	drm_panel_unprepare(&ctx->panel);
508 	drm_panel_prepare(&ctx->panel);
509 	drm_panel_enable(&ctx->panel);
510 
511 	return 0;
512 }
513 
514 DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL,
515 			allpixelson_set, "%llu\n");
516 
st7703_debugfs_init(struct st7703 * ctx)517 static void st7703_debugfs_init(struct st7703 *ctx)
518 {
519 	ctx->debugfs = debugfs_create_dir(DRV_NAME, NULL);
520 
521 	debugfs_create_file("allpixelson", 0600, ctx->debugfs, ctx,
522 			    &allpixelson_fops);
523 }
524 
st7703_debugfs_remove(struct st7703 * ctx)525 static void st7703_debugfs_remove(struct st7703 *ctx)
526 {
527 	debugfs_remove_recursive(ctx->debugfs);
528 	ctx->debugfs = NULL;
529 }
530 
st7703_probe(struct mipi_dsi_device * dsi)531 static int st7703_probe(struct mipi_dsi_device *dsi)
532 {
533 	struct device *dev = &dsi->dev;
534 	struct st7703 *ctx;
535 	int ret;
536 
537 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
538 	if (!ctx)
539 		return -ENOMEM;
540 
541 	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
542 	if (IS_ERR(ctx->reset_gpio))
543 		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n");
544 
545 	mipi_dsi_set_drvdata(dsi, ctx);
546 
547 	ctx->dev = dev;
548 	ctx->desc = of_device_get_match_data(dev);
549 
550 	dsi->mode_flags = ctx->desc->mode_flags;
551 	dsi->format = ctx->desc->format;
552 	dsi->lanes = ctx->desc->lanes;
553 
554 	ctx->vcc = devm_regulator_get(dev, "vcc");
555 	if (IS_ERR(ctx->vcc))
556 		return dev_err_probe(dev, PTR_ERR(ctx->vcc), "Failed to request vcc regulator\n");
557 
558 	ctx->iovcc = devm_regulator_get(dev, "iovcc");
559 	if (IS_ERR(ctx->iovcc))
560 		return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
561 				     "Failed to request iovcc regulator\n");
562 
563 	drm_panel_init(&ctx->panel, dev, &st7703_drm_funcs,
564 		       DRM_MODE_CONNECTOR_DSI);
565 
566 	ret = drm_panel_of_backlight(&ctx->panel);
567 	if (ret)
568 		return ret;
569 
570 	drm_panel_add(&ctx->panel);
571 
572 	ret = mipi_dsi_attach(dsi);
573 	if (ret < 0) {
574 		dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);
575 		drm_panel_remove(&ctx->panel);
576 		return ret;
577 	}
578 
579 	dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
580 		 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
581 		 drm_mode_vrefresh(ctx->desc->mode),
582 		 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
583 
584 	st7703_debugfs_init(ctx);
585 	return 0;
586 }
587 
st7703_shutdown(struct mipi_dsi_device * dsi)588 static void st7703_shutdown(struct mipi_dsi_device *dsi)
589 {
590 	struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
591 	int ret;
592 
593 	ret = drm_panel_unprepare(&ctx->panel);
594 	if (ret < 0)
595 		dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
596 
597 	ret = drm_panel_disable(&ctx->panel);
598 	if (ret < 0)
599 		dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
600 }
601 
st7703_remove(struct mipi_dsi_device * dsi)602 static void st7703_remove(struct mipi_dsi_device *dsi)
603 {
604 	struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
605 	int ret;
606 
607 	st7703_shutdown(dsi);
608 
609 	ret = mipi_dsi_detach(dsi);
610 	if (ret < 0)
611 		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
612 
613 	drm_panel_remove(&ctx->panel);
614 
615 	st7703_debugfs_remove(ctx);
616 }
617 
618 static const struct of_device_id st7703_of_match[] = {
619 	{ .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc },
620 	{ .compatible = "xingbangda,xbd599", .data = &xbd599_desc },
621 	{ /* sentinel */ }
622 };
623 MODULE_DEVICE_TABLE(of, st7703_of_match);
624 
625 static struct mipi_dsi_driver st7703_driver = {
626 	.probe	= st7703_probe,
627 	.remove = st7703_remove,
628 	.shutdown = st7703_shutdown,
629 	.driver = {
630 		.name = DRV_NAME,
631 		.of_match_table = st7703_of_match,
632 	},
633 };
634 module_mipi_dsi_driver(st7703_driver);
635 
636 MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>");
637 MODULE_DESCRIPTION("DRM driver for Sitronix ST7703 based MIPI DSI panels");
638 MODULE_LICENSE("GPL v2");
639