• 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 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 	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 
st7703_get_modes(struct drm_panel * panel,struct drm_connector * connector)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 
allpixelson_set(void * data,u64 val)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 
st7703_debugfs_init(struct st7703 * ctx)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 
st7703_debugfs_remove(struct st7703 * ctx)516 static void st7703_debugfs_remove(struct st7703 *ctx)
517 {
518 	debugfs_remove_recursive(ctx->debugfs);
519 	ctx->debugfs = NULL;
520 }
521 
st7703_probe(struct mipi_dsi_device * dsi)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 		dev_err(dev, "cannot get reset gpio\n");
535 		return PTR_ERR(ctx->reset_gpio);
536 	}
537 
538 	mipi_dsi_set_drvdata(dsi, ctx);
539 
540 	ctx->dev = dev;
541 	ctx->desc = of_device_get_match_data(dev);
542 
543 	dsi->mode_flags = ctx->desc->mode_flags;
544 	dsi->format = ctx->desc->format;
545 	dsi->lanes = ctx->desc->lanes;
546 
547 	ctx->vcc = devm_regulator_get(dev, "vcc");
548 	if (IS_ERR(ctx->vcc)) {
549 		ret = PTR_ERR(ctx->vcc);
550 		if (ret != -EPROBE_DEFER)
551 			dev_err(dev, "Failed to request vcc regulator: %d\n", ret);
552 		return ret;
553 	}
554 	ctx->iovcc = devm_regulator_get(dev, "iovcc");
555 	if (IS_ERR(ctx->iovcc)) {
556 		ret = PTR_ERR(ctx->iovcc);
557 		if (ret != -EPROBE_DEFER)
558 			dev_err(dev, "Failed to request iovcc regulator: %d\n", ret);
559 		return ret;
560 	}
561 
562 	drm_panel_init(&ctx->panel, dev, &st7703_drm_funcs,
563 		       DRM_MODE_CONNECTOR_DSI);
564 
565 	ret = drm_panel_of_backlight(&ctx->panel);
566 	if (ret)
567 		return ret;
568 
569 	drm_panel_add(&ctx->panel);
570 
571 	ret = mipi_dsi_attach(dsi);
572 	if (ret < 0) {
573 		dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);
574 		drm_panel_remove(&ctx->panel);
575 		return ret;
576 	}
577 
578 	dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
579 		 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
580 		 drm_mode_vrefresh(ctx->desc->mode),
581 		 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
582 
583 	st7703_debugfs_init(ctx);
584 	return 0;
585 }
586 
st7703_shutdown(struct mipi_dsi_device * dsi)587 static void st7703_shutdown(struct mipi_dsi_device *dsi)
588 {
589 	struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
590 	int ret;
591 
592 	ret = drm_panel_unprepare(&ctx->panel);
593 	if (ret < 0)
594 		dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
595 
596 	ret = drm_panel_disable(&ctx->panel);
597 	if (ret < 0)
598 		dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
599 }
600 
st7703_remove(struct mipi_dsi_device * dsi)601 static int st7703_remove(struct mipi_dsi_device *dsi)
602 {
603 	struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
604 	int ret;
605 
606 	st7703_shutdown(dsi);
607 
608 	ret = mipi_dsi_detach(dsi);
609 	if (ret < 0)
610 		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
611 
612 	drm_panel_remove(&ctx->panel);
613 
614 	st7703_debugfs_remove(ctx);
615 
616 	return 0;
617 }
618 
619 static const struct of_device_id st7703_of_match[] = {
620 	{ .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc },
621 	{ .compatible = "xingbangda,xbd599", .data = &xbd599_desc },
622 	{ /* sentinel */ }
623 };
624 MODULE_DEVICE_TABLE(of, st7703_of_match);
625 
626 static struct mipi_dsi_driver st7703_driver = {
627 	.probe	= st7703_probe,
628 	.remove = st7703_remove,
629 	.shutdown = st7703_shutdown,
630 	.driver = {
631 		.name = DRV_NAME,
632 		.of_match_table = st7703_of_match,
633 	},
634 };
635 module_mipi_dsi_driver(st7703_driver);
636 
637 MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>");
638 MODULE_DESCRIPTION("DRM driver for Sitronix ST7703 based MIPI DSI panels");
639 MODULE_LICENSE("GPL v2");
640