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