Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Ilitek ILI9341 TFT LCD drm_panel driver.
  4 *
  5 * This panel can be configured to support:
  6 * - 16-bit parallel RGB interface
  7 * - 18-bit parallel RGB interface
  8 * - 4-line serial spi interface
  9 *
 10 * Copyright (C) 2021 Dillon Min <dillon.minfei@gmail.com>
 11 *
 12 * For dbi+dpi part:
 13 * Derived from drivers/drm/gpu/panel/panel-ilitek-ili9322.c
 14 * the reuse of DBI abstraction part referred from Linus's patch
 15 * "drm/panel: s6e63m0: Switch to DBI abstraction for SPI"
 16 *
 17 * For only-dbi part, copy from David's code (drm/tiny/ili9341.c)
 18 * Copyright 2018 David Lechner <david@lechnology.com>
 19 */
 20
 21#include <linux/backlight.h>
 22#include <linux/bitops.h>
 23#include <linux/delay.h>
 24#include <linux/gpio/consumer.h>
 25#include <linux/module.h>
 26#include <linux/of_device.h>
 27#include <linux/regulator/consumer.h>
 28#include <linux/spi/spi.h>
 29
 30#include <video/mipi_display.h>
 31
 32#include <drm/drm_atomic_helper.h>
 33#include <drm/drm_drv.h>
 34#include <drm/drm_fbdev_generic.h>
 35#include <drm/drm_gem_atomic_helper.h>
 36#include <drm/drm_gem_dma_helper.h>
 37#include <drm/drm_gem_framebuffer_helper.h>
 38#include <drm/drm_mipi_dbi.h>
 39#include <drm/drm_modes.h>
 40#include <drm/drm_panel.h>
 41#include <drm/drm_print.h>
 42
 43#define ILI9341_RGB_INTERFACE  0xb0   /* RGB Interface Signal Control */
 44#define ILI9341_FRC            0xb1   /* Frame Rate Control register */
 45#define ILI9341_DFC            0xb6   /* Display Function Control register */
 46#define ILI9341_POWER1         0xc0   /* Power Control 1 register */
 47#define ILI9341_POWER2         0xc1   /* Power Control 2 register */
 48#define ILI9341_VCOM1          0xc5   /* VCOM Control 1 register */
 49#define ILI9341_VCOM2          0xc7   /* VCOM Control 2 register */
 50#define ILI9341_POWERA         0xcb   /* Power control A register */
 51#define ILI9341_POWERB         0xcf   /* Power control B register */
 52#define ILI9341_PGAMMA         0xe0   /* Positive Gamma Correction register */
 53#define ILI9341_NGAMMA         0xe1   /* Negative Gamma Correction register */
 54#define ILI9341_DTCA           0xe8   /* Driver timing control A */
 55#define ILI9341_DTCB           0xea   /* Driver timing control B */
 56#define ILI9341_POWER_SEQ      0xed   /* Power on sequence register */
 57#define ILI9341_3GAMMA_EN      0xf2   /* 3 Gamma enable register */
 58#define ILI9341_INTERFACE      0xf6   /* Interface control register */
 59#define ILI9341_PRC            0xf7   /* Pump ratio control register */
 60#define ILI9341_ETMOD	       0xb7   /* Entry mode set */
 61
 62#define ILI9341_MADCTL_BGR	BIT(3)
 63#define ILI9341_MADCTL_MV	BIT(5)
 64#define ILI9341_MADCTL_MX	BIT(6)
 65#define ILI9341_MADCTL_MY	BIT(7)
 66
 67#define ILI9341_POWER_B_LEN	3
 68#define ILI9341_POWER_SEQ_LEN	4
 69#define ILI9341_DTCA_LEN	3
 70#define ILI9341_DTCB_LEN	2
 71#define ILI9341_POWER_A_LEN	5
 72#define ILI9341_DFC_1_LEN	2
 73#define ILI9341_FRC_LEN		2
 74#define ILI9341_VCOM_1_LEN	2
 75#define ILI9341_DFC_2_LEN	4
 76#define ILI9341_COLUMN_ADDR_LEN	4
 77#define ILI9341_PAGE_ADDR_LEN	4
 78#define ILI9341_INTERFACE_LEN	3
 79#define ILI9341_PGAMMA_LEN	15
 80#define ILI9341_NGAMMA_LEN	15
 81#define ILI9341_CA_LEN		3
 82
 83#define ILI9341_PIXEL_DPI_16_BITS	(BIT(6) | BIT(4))
 84#define ILI9341_PIXEL_DPI_18_BITS	(BIT(6) | BIT(5))
 85#define ILI9341_GAMMA_CURVE_1		BIT(0)
 86#define ILI9341_IF_WE_MODE		BIT(0)
 87#define ILI9341_IF_BIG_ENDIAN		0x00
 88#define ILI9341_IF_DM_RGB		BIT(2)
 89#define ILI9341_IF_DM_INTERNAL		0x00
 90#define ILI9341_IF_DM_VSYNC		BIT(3)
 91#define ILI9341_IF_RM_RGB		BIT(1)
 92#define ILI9341_IF_RIM_RGB		0x00
 93
 94#define ILI9341_COLUMN_ADDR		0x00ef
 95#define ILI9341_PAGE_ADDR		0x013f
 96
 97#define ILI9341_RGB_EPL			BIT(0)
 98#define ILI9341_RGB_DPL			BIT(1)
 99#define ILI9341_RGB_HSPL		BIT(2)
100#define ILI9341_RGB_VSPL		BIT(3)
101#define ILI9341_RGB_DE_MODE		BIT(6)
102#define ILI9341_RGB_DISP_PATH_MEM	BIT(7)
103
104#define ILI9341_DBI_VCOMH_4P6V		0x23
105#define ILI9341_DBI_PWR_2_DEFAULT	0x10
106#define ILI9341_DBI_PRC_NORMAL		0x20
107#define ILI9341_DBI_VCOM_1_VMH_4P25V	0x3e
108#define ILI9341_DBI_VCOM_1_VML_1P5V	0x28
109#define ILI9341_DBI_VCOM_2_DEC_58	0x86
110#define ILI9341_DBI_FRC_DIVA		0x00
111#define ILI9341_DBI_FRC_RTNA		0x1b
112#define ILI9341_DBI_EMS_GAS		BIT(0)
113#define ILI9341_DBI_EMS_DTS		BIT(1)
114#define ILI9341_DBI_EMS_GON		BIT(2)
115
116/* struct ili9341_config - the system specific ILI9341 configuration */
117struct ili9341_config {
118	u32 max_spi_speed;
119	/* mode: the drm display mode */
120	const struct drm_display_mode mode;
121	/* ca: TODO: need comments for this register */
122	u8 ca[ILI9341_CA_LEN];
123	/* power_b: TODO: need comments for this register */
124	u8 power_b[ILI9341_POWER_B_LEN];
125	/* power_seq: TODO: need comments for this register */
126	u8 power_seq[ILI9341_POWER_SEQ_LEN];
127	/* dtca: TODO: need comments for this register */
128	u8 dtca[ILI9341_DTCA_LEN];
129	/* dtcb: TODO: need comments for this register */
130	u8 dtcb[ILI9341_DTCB_LEN];
131	/* power_a: TODO: need comments for this register */
132	u8 power_a[ILI9341_POWER_A_LEN];
133	/* frc: Frame Rate Control (In Normal Mode/Full Colors) (B1h) */
134	u8 frc[ILI9341_FRC_LEN];
135	/* prc: TODO: need comments for this register */
136	u8 prc;
137	/* dfc_1: B6h DISCTRL (Display Function Control) */
138	u8 dfc_1[ILI9341_DFC_1_LEN];
139	/* power_1: Power Control 1 (C0h) */
140	u8 power_1;
141	/* power_2: Power Control 2 (C1h) */
142	u8 power_2;
143	/* vcom_1: VCOM Control 1(C5h) */
144	u8 vcom_1[ILI9341_VCOM_1_LEN];
145	/* vcom_2: VCOM Control 2(C7h) */
146	u8 vcom_2;
147	/* address_mode: Memory Access Control (36h) */
148	u8 address_mode;
149	/* g3amma_en: TODO: need comments for this register */
150	u8 g3amma_en;
151	/* rgb_interface: RGB Interface Signal Control (B0h) */
152	u8 rgb_interface;
153	/* dfc_2: refer to dfc_1 */
154	u8 dfc_2[ILI9341_DFC_2_LEN];
155	/* column_addr: Column Address Set (2Ah) */
156	u8 column_addr[ILI9341_COLUMN_ADDR_LEN];
157	/* page_addr: Page Address Set (2Bh) */
158	u8 page_addr[ILI9341_PAGE_ADDR_LEN];
159	/* interface: Interface Control (F6h) */
160	u8 interface[ILI9341_INTERFACE_LEN];
161	/*
162	 * pixel_format: This command sets the pixel format for the RGB
163	 * image data used by
164	 */
165	u8 pixel_format;
166	/*
167	 * gamma_curve: This command is used to select the desired Gamma
168	 * curve for the
169	 */
170	u8 gamma_curve;
171	/* pgamma: Positive Gamma Correction (E0h) */
172	u8 pgamma[ILI9341_PGAMMA_LEN];
173	/* ngamma: Negative Gamma Correction (E1h) */
174	u8 ngamma[ILI9341_NGAMMA_LEN];
175};
176
177struct ili9341 {
178	struct device *dev;
179	const struct ili9341_config *conf;
180	struct drm_panel panel;
181	struct gpio_desc *reset_gpio;
182	struct gpio_desc *dc_gpio;
183	struct mipi_dbi *dbi;
184	u32 max_spi_speed;
185	struct regulator_bulk_data supplies[3];
186};
187
188/*
189 * The Stm32f429-disco board has a panel ili9341 connected to ltdc controller
190 */
191static const struct ili9341_config ili9341_stm32f429_disco_data = {
192	.max_spi_speed = 10000000,
193	.mode = {
194		.clock = 6100,
195		.hdisplay = 240,
196		.hsync_start = 240 + 10,/* hfp 10 */
197		.hsync_end = 240 + 10 + 10,/* hsync 10 */
198		.htotal = 240 + 10 + 10 + 20,/* hbp 20 */
199		.vdisplay = 320,
200		.vsync_start = 320 + 4,/* vfp 4 */
201		.vsync_end = 320 + 4 + 2,/* vsync 2 */
202		.vtotal = 320 + 4 + 2 + 2,/* vbp 2 */
203		.flags = 0,
204		.width_mm = 65,
205		.height_mm = 50,
206		.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
207	},
208	.ca = {0xc3, 0x08, 0x50},
209	.power_b = {0x00, 0xc1, 0x30},
210	.power_seq = {0x64, 0x03, 0x12, 0x81},
211	.dtca = {0x85, 0x00, 0x78},
212	.power_a = {0x39, 0x2c, 0x00, 0x34, 0x02},
213	.prc = 0x20,
214	.dtcb = {0x00, 0x00},
215	/* 0x00 fosc, 0x1b 70hz */
216	.frc = {0x00, 0x1b},
217	/*
218	 * 0x0a Interval scan, AGND AGND AGND AGND
219	 * 0xa2 Normally white, G1 -> G320, S720 -> S1,
220	 *	Scan Cycle 5 frames,85ms
221	 */
222	.dfc_1 = {0x0a, 0xa2},
223	/* 0x10 3.65v */
224	.power_1 = 0x10,
225	/* 0x10 AVDD=vci*2, VGH=vci*7, VGL=-vci*4 */
226	.power_2 = 0x10,
227	/* 0x45 VCOMH 4.425v, 0x15 VCOML -1.975*/
228	.vcom_1 = {0x45, 0x15},
229	/* 0x90 offset voltage, VMH-48, VML-48 */
230	.vcom_2 = 0x90,
231	/*
232	 * 0xc8 Row Address Order, Column Address Order
233	 * BGR 1
234	 */
235	.address_mode = 0xc8,
236	.g3amma_en = 0x00,
237	/*
238	 * 0xc2
239	 * Display Data Path: Memory
240	 * RGB: DE mode
241	 * DOTCLK polarity set (data fetched at the falling time)
242	 */
243	.rgb_interface = ILI9341_RGB_DISP_PATH_MEM |
244			ILI9341_RGB_DE_MODE |
245			ILI9341_RGB_DPL,
246	/*
247	 * 0x0a
248	 * Gate outputs in non-display area: Interval scan
249	 * Determine source/VCOM output in a non-display area in the partial
250	 * display mode: AGND AGND AGND AGND
251	 *
252	 * 0xa7
253	 * Scan Cycle: 15 frames
254	 * fFLM = 60Hz: 255ms
255	 * Liquid crystal type: Normally white
256	 * Gate Output Scan Direction: G1 -> G320
257	 * Source Output Scan Direction: S720 -> S1
258	 *
259	 * 0x27
260	 * LCD Driver Line: 320 lines
261	 *
262	 * 0x04
263	 * PCDIV: 4
264	 */
265	.dfc_2 = {0x0a, 0xa7, 0x27, 0x04},
266	/* column address: 240 */
267	.column_addr = {0x00, 0x00, (ILI9341_COLUMN_ADDR >> 4) & 0xff,
268				ILI9341_COLUMN_ADDR & 0xff},
269	/* page address: 320 */
270	.page_addr = {0x00, 0x00, (ILI9341_PAGE_ADDR >> 4) & 0xff,
271				ILI9341_PAGE_ADDR & 0xff},
272	/*
273	 * Memory write control: When the transfer number of data exceeds
274	 * (EC-SC+1)*(EP-SP+1), the column and page number will be
275	 * reset, and the exceeding data will be written into the following
276	 * column and page.
277	 * Display Operation Mode: RGB Interface Mode
278	 * Interface for RAM Access: RGB interface
279	 * 16- bit RGB interface (1 transfer/pixel)
280	 */
281	.interface = {ILI9341_IF_WE_MODE, 0x00,
282			ILI9341_IF_DM_RGB | ILI9341_IF_RM_RGB},
283	/* DPI: 16 bits / pixel */
284	.pixel_format = ILI9341_PIXEL_DPI_16_BITS,
285	/* Curve Selected: Gamma curve 1 (G2.2) */
286	.gamma_curve = ILI9341_GAMMA_CURVE_1,
287	.pgamma = {0x0f, 0x29, 0x24, 0x0c, 0x0e,
288			0x09, 0x4e, 0x78, 0x3c, 0x09,
289			0x13, 0x05, 0x17, 0x11, 0x00},
290	.ngamma = {0x00, 0x16, 0x1b, 0x04, 0x11,
291			0x07, 0x31, 0x33, 0x42, 0x05,
292			0x0c, 0x0a, 0x28, 0x2f, 0x0f},
293};
294
295static inline struct ili9341 *panel_to_ili9341(struct drm_panel *panel)
296{
297	return container_of(panel, struct ili9341, panel);
298}
299
300static void ili9341_dpi_init(struct ili9341 *ili)
301{
302	struct device *dev = (&ili->panel)->dev;
303	struct mipi_dbi *dbi = ili->dbi;
304	struct ili9341_config *cfg = (struct ili9341_config *)ili->conf;
305
306	/* Power Control */
307	mipi_dbi_command_stackbuf(dbi, 0xca, cfg->ca, ILI9341_CA_LEN);
308	mipi_dbi_command_stackbuf(dbi, ILI9341_POWERB, cfg->power_b,
309				  ILI9341_POWER_B_LEN);
310	mipi_dbi_command_stackbuf(dbi, ILI9341_POWER_SEQ, cfg->power_seq,
311				  ILI9341_POWER_SEQ_LEN);
312	mipi_dbi_command_stackbuf(dbi, ILI9341_DTCA, cfg->dtca,
313				  ILI9341_DTCA_LEN);
314	mipi_dbi_command_stackbuf(dbi, ILI9341_POWERA, cfg->power_a,
315				  ILI9341_POWER_A_LEN);
316	mipi_dbi_command(ili->dbi, ILI9341_PRC, cfg->prc);
317	mipi_dbi_command_stackbuf(dbi, ILI9341_DTCB, cfg->dtcb,
318				  ILI9341_DTCB_LEN);
319	mipi_dbi_command_stackbuf(dbi, ILI9341_FRC, cfg->frc, ILI9341_FRC_LEN);
320	mipi_dbi_command_stackbuf(dbi, ILI9341_DFC, cfg->dfc_1,
321				  ILI9341_DFC_1_LEN);
322	mipi_dbi_command(dbi, ILI9341_POWER1, cfg->power_1);
323	mipi_dbi_command(dbi, ILI9341_POWER2, cfg->power_2);
324
325	/* VCOM */
326	mipi_dbi_command_stackbuf(dbi, ILI9341_VCOM1, cfg->vcom_1,
327				  ILI9341_VCOM_1_LEN);
328	mipi_dbi_command(dbi, ILI9341_VCOM2, cfg->vcom_2);
329	mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, cfg->address_mode);
330
331	/* Gamma */
332	mipi_dbi_command(dbi, ILI9341_3GAMMA_EN, cfg->g3amma_en);
333	mipi_dbi_command(dbi, ILI9341_RGB_INTERFACE, cfg->rgb_interface);
334	mipi_dbi_command_stackbuf(dbi, ILI9341_DFC, cfg->dfc_2,
335				  ILI9341_DFC_2_LEN);
336
337	/* Colomn address set */
338	mipi_dbi_command_stackbuf(dbi, MIPI_DCS_SET_COLUMN_ADDRESS,
339				  cfg->column_addr, ILI9341_COLUMN_ADDR_LEN);
340
341	/* Page address set */
342	mipi_dbi_command_stackbuf(dbi, MIPI_DCS_SET_PAGE_ADDRESS,
343				  cfg->page_addr, ILI9341_PAGE_ADDR_LEN);
344	mipi_dbi_command_stackbuf(dbi, ILI9341_INTERFACE, cfg->interface,
345				  ILI9341_INTERFACE_LEN);
346
347	/* Format */
348	mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, cfg->pixel_format);
349	mipi_dbi_command(dbi, MIPI_DCS_WRITE_MEMORY_START);
350	msleep(200);
351	mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, cfg->gamma_curve);
352	mipi_dbi_command_stackbuf(dbi, ILI9341_PGAMMA, cfg->pgamma,
353				  ILI9341_PGAMMA_LEN);
354	mipi_dbi_command_stackbuf(dbi, ILI9341_NGAMMA, cfg->ngamma,
355				  ILI9341_NGAMMA_LEN);
356	mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
357	msleep(200);
358	mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
359	mipi_dbi_command(dbi, MIPI_DCS_WRITE_MEMORY_START);
360
361	dev_info(dev, "Initialized display rgb interface\n");
362}
363
364static int ili9341_dpi_power_on(struct ili9341 *ili)
365{
366	struct device *dev = (&ili->panel)->dev;
367	int ret = 0;
368
369	/* Assert RESET */
370	gpiod_set_value(ili->reset_gpio, 1);
371
372	/* Enable power */
373	ret = regulator_bulk_enable(ARRAY_SIZE(ili->supplies),
374				    ili->supplies);
375	if (ret < 0) {
376		dev_err(dev, "unable to enable vcc\n");
377		return ret;
378	}
379	msleep(20);
380
381	/* De-assert RESET */
382	gpiod_set_value(ili->reset_gpio, 0);
383	msleep(20);
384
385	return 0;
386}
387
388static int ili9341_dpi_power_off(struct ili9341 *ili)
389{
390	/* Assert RESET */
391	gpiod_set_value(ili->reset_gpio, 1);
392
393	/* Disable power */
394	return regulator_bulk_disable(ARRAY_SIZE(ili->supplies),
395				      ili->supplies);
396}
397
398static int ili9341_dpi_disable(struct drm_panel *panel)
399{
400	struct ili9341 *ili = panel_to_ili9341(panel);
401
402	mipi_dbi_command(ili->dbi, MIPI_DCS_SET_DISPLAY_OFF);
403	return 0;
404}
405
406static int ili9341_dpi_unprepare(struct drm_panel *panel)
407{
408	struct ili9341 *ili = panel_to_ili9341(panel);
409
410	return ili9341_dpi_power_off(ili);
411}
412
413static int ili9341_dpi_prepare(struct drm_panel *panel)
414{
415	struct ili9341 *ili = panel_to_ili9341(panel);
416	int ret;
417
418	ret = ili9341_dpi_power_on(ili);
419	if (ret < 0)
420		return ret;
421
422	ili9341_dpi_init(ili);
423
424	return ret;
425}
426
427static int ili9341_dpi_enable(struct drm_panel *panel)
428{
429	struct ili9341 *ili = panel_to_ili9341(panel);
430
431	mipi_dbi_command(ili->dbi, MIPI_DCS_SET_DISPLAY_ON);
432	return 0;
433}
434
435static int ili9341_dpi_get_modes(struct drm_panel *panel,
436				 struct drm_connector *connector)
437{
438	struct ili9341 *ili = panel_to_ili9341(panel);
439	struct drm_device *drm = connector->dev;
440	struct drm_display_mode *mode;
441	struct drm_display_info *info;
442
443	info = &connector->display_info;
444	info->width_mm = ili->conf->mode.width_mm;
445	info->height_mm = ili->conf->mode.height_mm;
446
447	if (ili->conf->rgb_interface & ILI9341_RGB_DPL)
448		info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
449	else
450		info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
451
452	if (ili->conf->rgb_interface & ILI9341_RGB_EPL)
453		info->bus_flags |= DRM_BUS_FLAG_DE_LOW;
454	else
455		info->bus_flags |= DRM_BUS_FLAG_DE_HIGH;
456
457	mode = drm_mode_duplicate(drm, &ili->conf->mode);
458	if (!mode) {
459		drm_err(drm, "bad mode or failed to add mode\n");
460		return -EINVAL;
461	}
462	drm_mode_set_name(mode);
463
464	/* Set up the polarity */
465	if (ili->conf->rgb_interface & ILI9341_RGB_HSPL)
466		mode->flags |= DRM_MODE_FLAG_PHSYNC;
467	else
468		mode->flags |= DRM_MODE_FLAG_NHSYNC;
469
470	if (ili->conf->rgb_interface & ILI9341_RGB_VSPL)
471		mode->flags |= DRM_MODE_FLAG_PVSYNC;
472	else
473		mode->flags |= DRM_MODE_FLAG_NVSYNC;
474
475	drm_mode_probed_add(connector, mode);
476
477	return 1; /* Number of modes */
478}
479
480static const struct drm_panel_funcs ili9341_dpi_funcs = {
481	.disable = ili9341_dpi_disable,
482	.unprepare = ili9341_dpi_unprepare,
483	.prepare = ili9341_dpi_prepare,
484	.enable = ili9341_dpi_enable,
485	.get_modes = ili9341_dpi_get_modes,
486};
487
488static void ili9341_dbi_enable(struct drm_simple_display_pipe *pipe,
489			       struct drm_crtc_state *crtc_state,
490			       struct drm_plane_state *plane_state)
491{
492	struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
493	struct mipi_dbi *dbi = &dbidev->dbi;
494	u8 addr_mode;
495	int ret, idx;
496
497	if (!drm_dev_enter(pipe->crtc.dev, &idx))
498		return;
499
500	ret = mipi_dbi_poweron_conditional_reset(dbidev);
501	if (ret < 0)
502		goto out_exit;
503	if (ret == 1)
504		goto out_enable;
505
506	mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
507
508	mipi_dbi_command(dbi, ILI9341_POWERB, 0x00, 0xc1, 0x30);
509	mipi_dbi_command(dbi, ILI9341_POWER_SEQ, 0x64, 0x03, 0x12, 0x81);
510	mipi_dbi_command(dbi, ILI9341_DTCA, 0x85, 0x00, 0x78);
511	mipi_dbi_command(dbi, ILI9341_POWERA, 0x39, 0x2c, 0x00, 0x34, 0x02);
512	mipi_dbi_command(dbi, ILI9341_PRC, ILI9341_DBI_PRC_NORMAL);
513	mipi_dbi_command(dbi, ILI9341_DTCB, 0x00, 0x00);
514
515	/* Power Control */
516	mipi_dbi_command(dbi, ILI9341_POWER1, ILI9341_DBI_VCOMH_4P6V);
517	mipi_dbi_command(dbi, ILI9341_POWER2, ILI9341_DBI_PWR_2_DEFAULT);
518	/* VCOM */
519	mipi_dbi_command(dbi, ILI9341_VCOM1, ILI9341_DBI_VCOM_1_VMH_4P25V,
520			 ILI9341_DBI_VCOM_1_VML_1P5V);
521	mipi_dbi_command(dbi, ILI9341_VCOM2, ILI9341_DBI_VCOM_2_DEC_58);
522
523	/* Memory Access Control */
524	mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT,
525			 MIPI_DCS_PIXEL_FMT_16BIT);
526
527	/* Frame Rate */
528	mipi_dbi_command(dbi, ILI9341_FRC, ILI9341_DBI_FRC_DIVA & 0x03,
529			 ILI9341_DBI_FRC_RTNA & 0x1f);
530
531	/* Gamma */
532	mipi_dbi_command(dbi, ILI9341_3GAMMA_EN, 0x00);
533	mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, ILI9341_GAMMA_CURVE_1);
534	mipi_dbi_command(dbi, ILI9341_PGAMMA,
535			 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1,
536			 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00);
537	mipi_dbi_command(dbi, ILI9341_NGAMMA,
538			 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1,
539			 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f);
540
541	/* DDRAM */
542	mipi_dbi_command(dbi, ILI9341_ETMOD, ILI9341_DBI_EMS_GAS |
543			 ILI9341_DBI_EMS_DTS |
544			 ILI9341_DBI_EMS_GON);
545
546	/* Display */
547	mipi_dbi_command(dbi, ILI9341_DFC, 0x08, 0x82, 0x27, 0x00);
548	mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
549	msleep(100);
550
551	mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
552	msleep(100);
553
554out_enable:
555	switch (dbidev->rotation) {
556	default:
557		addr_mode = ILI9341_MADCTL_MX;
558		break;
559	case 90:
560		addr_mode = ILI9341_MADCTL_MV;
561		break;
562	case 180:
563		addr_mode = ILI9341_MADCTL_MY;
564		break;
565	case 270:
566		addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY |
567			    ILI9341_MADCTL_MX;
568		break;
569	}
570
571	addr_mode |= ILI9341_MADCTL_BGR;
572	mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
573	mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
574	drm_info(&dbidev->drm, "Initialized display serial interface\n");
575out_exit:
576	drm_dev_exit(idx);
577}
578
579static const struct drm_simple_display_pipe_funcs ili9341_dbi_funcs = {
580	.mode_valid = mipi_dbi_pipe_mode_valid,
581	.enable = ili9341_dbi_enable,
582	.disable = mipi_dbi_pipe_disable,
583	.update = mipi_dbi_pipe_update,
584	.prepare_fb = drm_gem_simple_display_pipe_prepare_fb,
585};
586
587static const struct drm_display_mode ili9341_dbi_mode = {
588	DRM_SIMPLE_MODE(240, 320, 37, 49),
589};
590
591DEFINE_DRM_GEM_DMA_FOPS(ili9341_dbi_fops);
592
593static struct drm_driver ili9341_dbi_driver = {
594	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
595	.fops			= &ili9341_dbi_fops,
596	DRM_GEM_DMA_DRIVER_OPS_VMAP,
597	.debugfs_init		= mipi_dbi_debugfs_init,
598	.name			= "ili9341",
599	.desc			= "Ilitek ILI9341",
600	.date			= "20210716",
601	.major			= 1,
602	.minor			= 0,
603};
604
605static int ili9341_dbi_probe(struct spi_device *spi, struct gpio_desc *dc,
606			     struct gpio_desc *reset)
607{
608	struct device *dev = &spi->dev;
609	struct mipi_dbi_dev *dbidev;
610	struct mipi_dbi *dbi;
611	struct drm_device *drm;
612	struct regulator *vcc;
613	u32 rotation = 0;
614	int ret;
615
616	vcc = devm_regulator_get_optional(dev, "vcc");
617	if (IS_ERR(vcc)) {
618		dev_err(dev, "get optional vcc failed\n");
619		vcc = NULL;
620	}
621
622	dbidev = devm_drm_dev_alloc(dev, &ili9341_dbi_driver,
623				    struct mipi_dbi_dev, drm);
624	if (IS_ERR(dbidev))
625		return PTR_ERR(dbidev);
626
627	dbi = &dbidev->dbi;
628	drm = &dbidev->drm;
629	dbi->reset = reset;
630	dbidev->regulator = vcc;
631
632	drm_mode_config_init(drm);
633
634	dbidev->backlight = devm_of_find_backlight(dev);
635	if (IS_ERR(dbidev->backlight))
636		return PTR_ERR(dbidev->backlight);
637
638	device_property_read_u32(dev, "rotation", &rotation);
639
640	ret = mipi_dbi_spi_init(spi, dbi, dc);
641	if (ret)
642		return ret;
643
644	ret = mipi_dbi_dev_init(dbidev, &ili9341_dbi_funcs,
645				&ili9341_dbi_mode, rotation);
646	if (ret)
647		return ret;
648
649	drm_mode_config_reset(drm);
650
651	ret = drm_dev_register(drm, 0);
652	if (ret)
653		return ret;
654
655	spi_set_drvdata(spi, drm);
656
657	drm_fbdev_generic_setup(drm, 0);
658
659	return 0;
660}
661
662static int ili9341_dpi_probe(struct spi_device *spi, struct gpio_desc *dc,
663			     struct gpio_desc *reset)
664{
665	struct device *dev = &spi->dev;
666	struct ili9341 *ili;
667	int ret;
668
669	ili = devm_kzalloc(dev, sizeof(struct ili9341), GFP_KERNEL);
670	if (!ili)
671		return -ENOMEM;
672
673	ili->dbi = devm_kzalloc(dev, sizeof(struct mipi_dbi),
674				GFP_KERNEL);
675	if (!ili->dbi)
676		return -ENOMEM;
677
678	ili->supplies[0].supply = "vci";
679	ili->supplies[1].supply = "vddi";
680	ili->supplies[2].supply = "vddi-led";
681	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ili->supplies),
682				      ili->supplies);
683	if (ret < 0) {
684		dev_err(dev, "failed to get regulators: %d\n", ret);
685		return ret;
686	}
687
688	ret = mipi_dbi_spi_init(spi, ili->dbi, dc);
689	if (ret)
690		return ret;
691
692	spi_set_drvdata(spi, ili);
693	ili->reset_gpio = reset;
694	/*
695	 * Every new incarnation of this display must have a unique
696	 * data entry for the system in this driver.
697	 */
698	ili->conf = of_device_get_match_data(dev);
699	if (!ili->conf) {
700		dev_err(dev, "missing device configuration\n");
701		return -ENODEV;
702	}
703
704	ili->max_spi_speed = ili->conf->max_spi_speed;
705	drm_panel_init(&ili->panel, dev, &ili9341_dpi_funcs,
706		       DRM_MODE_CONNECTOR_DPI);
707	drm_panel_add(&ili->panel);
708
709	return 0;
710}
711
712static int ili9341_probe(struct spi_device *spi)
713{
714	struct device *dev = &spi->dev;
715	struct gpio_desc *dc;
716	struct gpio_desc *reset;
717	const struct spi_device_id *id = spi_get_device_id(spi);
718
719	reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
720	if (IS_ERR(reset))
721		dev_err(dev, "Failed to get gpio 'reset'\n");
722
723	dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
724	if (IS_ERR(dc))
725		dev_err(dev, "Failed to get gpio 'dc'\n");
726
727	if (!strcmp(id->name, "sf-tc240t-9370-t"))
728		return ili9341_dpi_probe(spi, dc, reset);
729	else if (!strcmp(id->name, "yx240qv29"))
730		return ili9341_dbi_probe(spi, dc, reset);
731
732	return -1;
733}
734
735static void ili9341_remove(struct spi_device *spi)
736{
737	const struct spi_device_id *id = spi_get_device_id(spi);
738	struct ili9341 *ili = spi_get_drvdata(spi);
739	struct drm_device *drm = spi_get_drvdata(spi);
740
741	if (!strcmp(id->name, "sf-tc240t-9370-t")) {
742		ili9341_dpi_power_off(ili);
743		drm_panel_remove(&ili->panel);
744	} else if (!strcmp(id->name, "yx240qv29")) {
745		drm_dev_unplug(drm);
746		drm_atomic_helper_shutdown(drm);
747	}
748}
749
750static void ili9341_shutdown(struct spi_device *spi)
751{
752	const struct spi_device_id *id = spi_get_device_id(spi);
753
754	if (!strcmp(id->name, "yx240qv29"))
755		drm_atomic_helper_shutdown(spi_get_drvdata(spi));
756}
757
758static const struct of_device_id ili9341_of_match[] = {
759	{
760		.compatible = "st,sf-tc240t-9370-t",
761		.data = &ili9341_stm32f429_disco_data,
762	},
763	{
764		/* porting from tiny/ili9341.c
765		 * for original mipi dbi compitable
766		 */
767		.compatible = "adafruit,yx240qv29",
768		.data = NULL,
769	},
770	{ }
771};
772MODULE_DEVICE_TABLE(of, ili9341_of_match);
773
774static const struct spi_device_id ili9341_id[] = {
775	{ "yx240qv29", 0 },
776	{ "sf-tc240t-9370-t", 0 },
777	{ }
778};
779MODULE_DEVICE_TABLE(spi, ili9341_id);
780
781static struct spi_driver ili9341_driver = {
782	.probe = ili9341_probe,
783	.remove = ili9341_remove,
784	.shutdown = ili9341_shutdown,
785	.id_table = ili9341_id,
786	.driver = {
787		.name = "panel-ilitek-ili9341",
788		.of_match_table = ili9341_of_match,
789	},
790};
791module_spi_driver(ili9341_driver);
792
793MODULE_AUTHOR("Dillon Min <dillon.minfei@gmail.com>");
794MODULE_DESCRIPTION("ILI9341 LCD panel driver");
795MODULE_LICENSE("GPL v2");