Linux Audio

Check our new training course

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