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
51struct 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
63struct 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
71static 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
84static 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
141static 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
156struct 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
174static 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
335static 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
350static 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
358static 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
390static 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
407static 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
422static 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
457static 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
481static 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
489static 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
506DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL,
507			allpixelson_set, "%llu\n");
508
509static 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
517static void st7703_debugfs_remove(struct st7703 *ctx)
518{
519	debugfs_remove_recursive(ctx->debugfs);
520	ctx->debugfs = NULL;
521}
522
523static 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		dev_err(dev, "cannot get reset gpio\n");
536		return PTR_ERR(ctx->reset_gpio);
537	}
538
539	mipi_dsi_set_drvdata(dsi, ctx);
540
541	ctx->dev = dev;
542	ctx->desc = of_device_get_match_data(dev);
543
544	dsi->mode_flags = ctx->desc->mode_flags;
545	dsi->format = ctx->desc->format;
546	dsi->lanes = ctx->desc->lanes;
547
548	ctx->vcc = devm_regulator_get(dev, "vcc");
549	if (IS_ERR(ctx->vcc)) {
550		ret = PTR_ERR(ctx->vcc);
551		if (ret != -EPROBE_DEFER)
552			dev_err(dev, "Failed to request vcc regulator: %d\n", ret);
553		return ret;
554	}
555	ctx->iovcc = devm_regulator_get(dev, "iovcc");
556	if (IS_ERR(ctx->iovcc)) {
557		ret = PTR_ERR(ctx->iovcc);
558		if (ret != -EPROBE_DEFER)
559			dev_err(dev, "Failed to request iovcc regulator: %d\n", ret);
560		return ret;
561	}
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
588static 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
602static int 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	return 0;
618}
619
620static const struct of_device_id st7703_of_match[] = {
621	{ .compatible = "rocktech,jh057n00900", .data = &jh057n00900_panel_desc },
622	{ .compatible = "xingbangda,xbd599", .data = &xbd599_desc },
623	{ /* sentinel */ }
624};
625MODULE_DEVICE_TABLE(of, st7703_of_match);
626
627static struct mipi_dsi_driver st7703_driver = {
628	.probe	= st7703_probe,
629	.remove = st7703_remove,
630	.shutdown = st7703_shutdown,
631	.driver = {
632		.name = DRV_NAME,
633		.of_match_table = st7703_of_match,
634	},
635};
636module_mipi_dsi_driver(st7703_driver);
637
638MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>");
639MODULE_DESCRIPTION("DRM driver for Sitronix ST7703 based MIPI DSI panels");
640MODULE_LICENSE("GPL v2");
641