xref: /linux/drivers/gpu/drm/panel/panel-ilitek-ili9322.c (revision 95298d63c67673c654c08952672d016212b26054)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Ilitek ILI9322 TFT LCD drm_panel driver.
4  *
5  * This panel can be configured to support:
6  * - 8-bit serial RGB interface
7  * - 24-bit parallel RGB interface
8  * - 8-bit ITU-R BT.601 interface
9  * - 8-bit ITU-R BT.656 interface
10  * - Up to 320RGBx240 dots resolution TFT LCD displays
11  * - Scaling, brightness and contrast
12  *
13  * The scaling means that the display accepts a 640x480 or 720x480
14  * input and rescales it to fit to the 320x240 display. So what we
15  * present to the system is something else than what comes out on the
16  * actual display.
17  *
18  * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
19  * Derived from drivers/drm/gpu/panel/panel-samsung-ld9040.c
20  */
21 
22 #include <linux/bitops.h>
23 #include <linux/gpio/consumer.h>
24 #include <linux/module.h>
25 #include <linux/of_device.h>
26 #include <linux/regmap.h>
27 #include <linux/regulator/consumer.h>
28 #include <linux/spi/spi.h>
29 
30 #include <video/mipi_display.h>
31 #include <video/of_videomode.h>
32 #include <video/videomode.h>
33 
34 #include <drm/drm_modes.h>
35 #include <drm/drm_panel.h>
36 #include <drm/drm_print.h>
37 
38 #define ILI9322_CHIP_ID			0x00
39 #define ILI9322_CHIP_ID_MAGIC		0x96
40 
41 /*
42  * Voltage on the communication interface, from 0.7 (0x00)
43  * to 1.32 (0x1f) times the VREG1OUT voltage in 2% increments.
44  * 1.00 (0x0f) is the default.
45  */
46 #define ILI9322_VCOM_AMP		0x01
47 
48 /*
49  * High voltage on the communication signals, from 0.37 (0x00) to
50  * 1.0 (0x3f) times the VREGOUT1 voltage in 1% increments.
51  * 0.83 (0x2e) is the default.
52  */
53 #define ILI9322_VCOM_HIGH		0x02
54 
55 /*
56  * VREG1 voltage regulator from 3.6V (0x00) to 6.0V (0x18) in 0.1V
57  * increments. 5.4V (0x12) is the default. This is the reference
58  * voltage for the VCOM levels and the greyscale level.
59  */
60 #define ILI9322_VREG1_VOLTAGE		0x03
61 
62 /* Describes the incoming signal */
63 #define ILI9322_ENTRY			0x06
64 /* 0 = right-to-left, 1 = left-to-right (default), horizontal flip */
65 #define ILI9322_ENTRY_HDIR		BIT(0)
66 /* 0 = down-to-up, 1 = up-to-down (default), vertical flip  */
67 #define ILI9322_ENTRY_VDIR		BIT(1)
68 /* NTSC, PAL or autodetect */
69 #define ILI9322_ENTRY_NTSC		(0 << 2)
70 #define ILI9322_ENTRY_PAL		(1 << 2)
71 #define ILI9322_ENTRY_AUTODETECT	(3 << 2)
72 /* Input format */
73 #define ILI9322_ENTRY_SERIAL_RGB_THROUGH (0 << 4)
74 #define ILI9322_ENTRY_SERIAL_RGB_ALIGNED (1 << 4)
75 #define ILI9322_ENTRY_SERIAL_RGB_DUMMY_320X240 (2 << 4)
76 #define ILI9322_ENTRY_SERIAL_RGB_DUMMY_360X240 (3 << 4)
77 #define ILI9322_ENTRY_DISABLE_1		(4 << 4)
78 #define ILI9322_ENTRY_PARALLEL_RGB_THROUGH (5 << 4)
79 #define ILI9322_ENTRY_PARALLEL_RGB_ALIGNED (6 << 4)
80 #define ILI9322_ENTRY_YUV_640Y_320CBCR_25_54_MHZ (7 << 4)
81 #define ILI9322_ENTRY_YUV_720Y_360CBCR_27_MHZ (8 << 4)
82 #define ILI9322_ENTRY_DISABLE_2		(9 << 4)
83 #define ILI9322_ENTRY_ITU_R_BT_656_720X360 (10 << 4)
84 #define ILI9322_ENTRY_ITU_R_BT_656_640X320 (11 << 4)
85 
86 /* Power control */
87 #define ILI9322_POW_CTRL		0x07
88 #define ILI9322_POW_CTRL_STB		BIT(0) /* 0 = standby, 1 = normal */
89 #define ILI9322_POW_CTRL_VGL		BIT(1) /* 0 = off, 1 = on  */
90 #define ILI9322_POW_CTRL_VGH		BIT(2) /* 0 = off, 1 = on  */
91 #define ILI9322_POW_CTRL_DDVDH		BIT(3) /* 0 = off, 1 = on  */
92 #define ILI9322_POW_CTRL_VCOM		BIT(4) /* 0 = off, 1 = on  */
93 #define ILI9322_POW_CTRL_VCL		BIT(5) /* 0 = off, 1 = on  */
94 #define ILI9322_POW_CTRL_AUTO		BIT(6) /* 0 = interactive, 1 = auto */
95 #define ILI9322_POW_CTRL_STANDBY	(ILI9322_POW_CTRL_VGL | \
96 					 ILI9322_POW_CTRL_VGH | \
97 					 ILI9322_POW_CTRL_DDVDH | \
98 					 ILI9322_POW_CTRL_VCL | \
99 					 ILI9322_POW_CTRL_AUTO | \
100 					 BIT(7))
101 #define ILI9322_POW_CTRL_DEFAULT	(ILI9322_POW_CTRL_STANDBY | \
102 					 ILI9322_POW_CTRL_STB)
103 
104 /* Vertical back porch bits 0..5 */
105 #define ILI9322_VBP			0x08
106 
107 /* Horizontal back porch, 8 bits */
108 #define ILI9322_HBP			0x09
109 
110 /*
111  * Polarity settings:
112  * 1 = positive polarity
113  * 0 = negative polarity
114  */
115 #define ILI9322_POL			0x0a
116 #define ILI9322_POL_DCLK		BIT(0) /* 1 default */
117 #define ILI9322_POL_HSYNC		BIT(1) /* 0 default */
118 #define ILI9322_POL_VSYNC		BIT(2) /* 0 default */
119 #define ILI9322_POL_DE			BIT(3) /* 1 default */
120 /*
121  * 0 means YCBCR are ordered Cb0,Y0,Cr0,Y1,Cb2,Y2,Cr2,Y3 (default)
122  *   in RGB mode this means RGB comes in RGBRGB
123  * 1 means YCBCR are ordered Cr0,Y0,Cb0,Y1,Cr2,Y2,Cb2,Y3
124  *   in RGB mode this means RGB comes in BGRBGR
125  */
126 #define ILI9322_POL_YCBCR_MODE		BIT(4)
127 /* Formula A for YCbCR->RGB = 0, Formula B = 1 */
128 #define ILI9322_POL_FORMULA		BIT(5)
129 /* Reverse polarity: 0 = 0..255, 1 = 255..0 */
130 #define ILI9322_POL_REV			BIT(6)
131 
132 #define ILI9322_IF_CTRL			0x0b
133 #define ILI9322_IF_CTRL_HSYNC_VSYNC	0x00
134 #define ILI9322_IF_CTRL_HSYNC_VSYNC_DE	BIT(2)
135 #define ILI9322_IF_CTRL_DE_ONLY		BIT(3)
136 #define ILI9322_IF_CTRL_SYNC_DISABLED	(BIT(2) | BIT(3))
137 #define ILI9322_IF_CTRL_LINE_INVERSION	BIT(0) /* Not set means frame inv */
138 
139 #define ILI9322_GLOBAL_RESET		0x04
140 #define ILI9322_GLOBAL_RESET_ASSERT	0x00 /* bit 0 = 0 -> reset */
141 
142 /*
143  * 4+4 bits of negative and positive gamma correction
144  * Upper nybble, bits 4-7 are negative gamma
145  * Lower nybble, bits 0-3 are positive gamma
146  */
147 #define ILI9322_GAMMA_1			0x10
148 #define ILI9322_GAMMA_2			0x11
149 #define ILI9322_GAMMA_3			0x12
150 #define ILI9322_GAMMA_4			0x13
151 #define ILI9322_GAMMA_5			0x14
152 #define ILI9322_GAMMA_6			0x15
153 #define ILI9322_GAMMA_7			0x16
154 #define ILI9322_GAMMA_8			0x17
155 
156 /**
157  * enum ili9322_input - the format of the incoming signal to the panel
158  *
159  * The panel can be connected to various input streams and four of them can
160  * be selected by electronic straps on the display. However it is possible
161  * to select another mode or override the electronic default with this
162  * setting.
163  */
164 enum ili9322_input {
165 	ILI9322_INPUT_SRGB_THROUGH = 0x0,
166 	ILI9322_INPUT_SRGB_ALIGNED = 0x1,
167 	ILI9322_INPUT_SRGB_DUMMY_320X240 = 0x2,
168 	ILI9322_INPUT_SRGB_DUMMY_360X240 = 0x3,
169 	ILI9322_INPUT_DISABLED_1 = 0x4,
170 	ILI9322_INPUT_PRGB_THROUGH = 0x5,
171 	ILI9322_INPUT_PRGB_ALIGNED = 0x6,
172 	ILI9322_INPUT_YUV_640X320_YCBCR = 0x7,
173 	ILI9322_INPUT_YUV_720X360_YCBCR = 0x8,
174 	ILI9322_INPUT_DISABLED_2 = 0x9,
175 	ILI9322_INPUT_ITU_R_BT656_720X360_YCBCR = 0xa,
176 	ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR = 0xb,
177 	ILI9322_INPUT_UNKNOWN = 0xc,
178 };
179 
180 static const char * const ili9322_inputs[] = {
181 	"8 bit serial RGB through",
182 	"8 bit serial RGB aligned",
183 	"8 bit serial RGB dummy 320x240",
184 	"8 bit serial RGB dummy 360x240",
185 	"disabled 1",
186 	"24 bit parallel RGB through",
187 	"24 bit parallel RGB aligned",
188 	"24 bit YUV 640Y 320CbCr",
189 	"24 bit YUV 720Y 360CbCr",
190 	"disabled 2",
191 	"8 bit ITU-R BT.656 720Y 360CbCr",
192 	"8 bit ITU-R BT.656 640Y 320CbCr",
193 };
194 
195 /**
196  * struct ili9322_config - the system specific ILI9322 configuration
197  * @width_mm: physical panel width [mm]
198  * @height_mm: physical panel height [mm]
199  * @flip_horizontal: flip the image horizontally (right-to-left scan)
200  * (only in RGB and YUV modes)
201  * @flip_vertical: flip the image vertically (down-to-up scan)
202  * (only in RGB and YUV modes)
203  * @input: the input/entry type used in this system, if this is set to
204  * ILI9322_INPUT_UNKNOWN the driver will try to figure it out by probing
205  * the hardware
206  * @vreg1out_mv: the output in microvolts for the VREGOUT1 regulator used
207  * to drive the physical display. Valid ranges are 3600 thru 6000 in 100
208  * microvolt increments. If not specified, hardware defaults will be
209  * used (4.5V).
210  * @vcom_high_percent: the percentage of VREGOUT1 used for the peak
211  * voltage on the communications link. Valid ranges are 37 thru 100
212  * percent. If not specified, hardware defaults will be used (91%).
213  * @vcom_amplitude_percent: the percentage of VREGOUT1 used for the
214  * peak-to-peak amplitude of the communcation signals to the physical
215  * display. Valid ranges are 70 thru 132 percent in increments if two
216  * percent. Odd percentages will be truncated. If not specified, hardware
217  * defaults will be used (114%).
218  * @dclk_active_high: data/pixel clock active high, data will be clocked
219  * in on the rising edge of the DCLK (this is usually the case).
220  * @syncmode: The synchronization mode, what sync signals are emitted.
221  * See the enum for details.
222  * @de_active_high: DE (data entry) is active high
223  * @hsync_active_high: HSYNC is active high
224  * @vsync_active_high: VSYNC is active high
225  * @gamma_corr_pos: a set of 8 nybbles describing positive
226  * gamma correction for voltages V1 thru V8. Valid range 0..15
227  * @gamma_corr_neg: a set of 8 nybbles describing negative
228  * gamma correction for voltages V1 thru V8. Valid range 0..15
229  *
230  * These adjust what grayscale voltage will be output for input data V1 = 0,
231  * V2 = 16, V3 = 48, V4 = 96, V5 = 160, V6 = 208, V7 = 240 and V8 = 255.
232  * The curve is shaped like this:
233  *
234  *  ^
235  *  |                                                        V8
236  *  |                                                   V7
237  *  |                                          V6
238  *  |                               V5
239  *  |                    V4
240  *  |            V3
241  *  |     V2
242  *  | V1
243  *  +----------------------------------------------------------->
244  *    0   16     48      96         160        208      240  255
245  *
246  * The negative and postive gamma values adjust the V1 thru V8 up/down
247  * according to the datasheet specifications. This is a property of the
248  * physical display connected to the display controller and may vary.
249  * If defined, both arrays must be supplied in full. If the properties
250  * are not supplied, hardware defaults will be used.
251  */
252 struct ili9322_config {
253 	u32 width_mm;
254 	u32 height_mm;
255 	bool flip_horizontal;
256 	bool flip_vertical;
257 	enum ili9322_input input;
258 	u32 vreg1out_mv;
259 	u32 vcom_high_percent;
260 	u32 vcom_amplitude_percent;
261 	bool dclk_active_high;
262 	bool de_active_high;
263 	bool hsync_active_high;
264 	bool vsync_active_high;
265 	u8 syncmode;
266 	u8 gamma_corr_pos[8];
267 	u8 gamma_corr_neg[8];
268 };
269 
270 struct ili9322 {
271 	struct device *dev;
272 	const struct ili9322_config *conf;
273 	struct drm_panel panel;
274 	struct regmap *regmap;
275 	struct regulator_bulk_data supplies[3];
276 	struct gpio_desc *reset_gpio;
277 	enum ili9322_input input;
278 	struct videomode vm;
279 	u8 gamma[8];
280 	u8 vreg1out;
281 	u8 vcom_high;
282 	u8 vcom_amplitude;
283 };
284 
285 static inline struct ili9322 *panel_to_ili9322(struct drm_panel *panel)
286 {
287 	return container_of(panel, struct ili9322, panel);
288 }
289 
290 static int ili9322_regmap_spi_write(void *context, const void *data,
291 				    size_t count)
292 {
293 	struct device *dev = context;
294 	struct spi_device *spi = to_spi_device(dev);
295 	u8 buf[2];
296 
297 	/* Clear bit 7 to write */
298 	memcpy(buf, data, 2);
299 	buf[0] &= ~0x80;
300 
301 	dev_dbg(dev, "WRITE: %02x %02x\n", buf[0], buf[1]);
302 	return spi_write_then_read(spi, buf, 2, NULL, 0);
303 }
304 
305 static int ili9322_regmap_spi_read(void *context, const void *reg,
306 				   size_t reg_size, void *val, size_t val_size)
307 {
308 	struct device *dev = context;
309 	struct spi_device *spi = to_spi_device(dev);
310 	u8 buf[1];
311 
312 	/* Set bit 7 to 1 to read */
313 	memcpy(buf, reg, 1);
314 	dev_dbg(dev, "READ: %02x reg size = %zu, val size = %zu\n",
315 		buf[0], reg_size, val_size);
316 	buf[0] |= 0x80;
317 
318 	return spi_write_then_read(spi, buf, 1, val, 1);
319 }
320 
321 static struct regmap_bus ili9322_regmap_bus = {
322 	.write = ili9322_regmap_spi_write,
323 	.read = ili9322_regmap_spi_read,
324 	.reg_format_endian_default = REGMAP_ENDIAN_BIG,
325 	.val_format_endian_default = REGMAP_ENDIAN_BIG,
326 };
327 
328 static bool ili9322_volatile_reg(struct device *dev, unsigned int reg)
329 {
330 	return false;
331 }
332 
333 static bool ili9322_writeable_reg(struct device *dev, unsigned int reg)
334 {
335 	/* Just register 0 is read-only */
336 	if (reg == 0x00)
337 		return false;
338 	return true;
339 }
340 
341 static const struct regmap_config ili9322_regmap_config = {
342 	.reg_bits = 8,
343 	.val_bits = 8,
344 	.max_register = 0x44,
345 	.cache_type = REGCACHE_RBTREE,
346 	.volatile_reg = ili9322_volatile_reg,
347 	.writeable_reg = ili9322_writeable_reg,
348 };
349 
350 static int ili9322_init(struct drm_panel *panel, struct ili9322 *ili)
351 {
352 	u8 reg;
353 	int ret;
354 	int i;
355 
356 	/* Reset display */
357 	ret = regmap_write(ili->regmap, ILI9322_GLOBAL_RESET,
358 			   ILI9322_GLOBAL_RESET_ASSERT);
359 	if (ret) {
360 		dev_err(ili->dev, "can't issue GRESET (%d)\n", ret);
361 		return ret;
362 	}
363 
364 	/* Set up the main voltage regulator */
365 	if (ili->vreg1out != U8_MAX) {
366 		ret = regmap_write(ili->regmap, ILI9322_VREG1_VOLTAGE,
367 				   ili->vreg1out);
368 		if (ret) {
369 			dev_err(ili->dev, "can't set up VREG1OUT (%d)\n", ret);
370 			return ret;
371 		}
372 	}
373 
374 	if (ili->vcom_amplitude != U8_MAX) {
375 		ret = regmap_write(ili->regmap, ILI9322_VCOM_AMP,
376 				   ili->vcom_amplitude);
377 		if (ret) {
378 			dev_err(ili->dev,
379 				"can't set up VCOM amplitude (%d)\n", ret);
380 			return ret;
381 		}
382 	}
383 
384 	if (ili->vcom_high != U8_MAX) {
385 		ret = regmap_write(ili->regmap, ILI9322_VCOM_HIGH,
386 				   ili->vcom_high);
387 		if (ret) {
388 			dev_err(ili->dev, "can't set up VCOM high (%d)\n", ret);
389 			return ret;
390 		}
391 	}
392 
393 	/* Set up gamma correction */
394 	for (i = 0; i < ARRAY_SIZE(ili->gamma); i++) {
395 		ret = regmap_write(ili->regmap, ILI9322_GAMMA_1 + i,
396 				   ili->gamma[i]);
397 		if (ret) {
398 			dev_err(ili->dev,
399 				"can't write gamma V%d to 0x%02x (%d)\n",
400 				i + 1, ILI9322_GAMMA_1 + i, ret);
401 			return ret;
402 		}
403 	}
404 
405 	/*
406 	 * Polarity and inverted color order for RGB input.
407 	 * None of this applies in the BT.656 mode.
408 	 */
409 	reg = 0;
410 	if (ili->conf->dclk_active_high)
411 		reg = ILI9322_POL_DCLK;
412 	if (ili->conf->de_active_high)
413 		reg |= ILI9322_POL_DE;
414 	if (ili->conf->hsync_active_high)
415 		reg |= ILI9322_POL_HSYNC;
416 	if (ili->conf->vsync_active_high)
417 		reg |= ILI9322_POL_VSYNC;
418 	ret = regmap_write(ili->regmap, ILI9322_POL, reg);
419 	if (ret) {
420 		dev_err(ili->dev, "can't write POL register (%d)\n", ret);
421 		return ret;
422 	}
423 
424 	/*
425 	 * Set up interface control.
426 	 * This is not used in the BT.656 mode (no H/Vsync or DE signals).
427 	 */
428 	reg = ili->conf->syncmode;
429 	reg |= ILI9322_IF_CTRL_LINE_INVERSION;
430 	ret = regmap_write(ili->regmap, ILI9322_IF_CTRL, reg);
431 	if (ret) {
432 		dev_err(ili->dev, "can't write IF CTRL register (%d)\n", ret);
433 		return ret;
434 	}
435 
436 	/* Set up the input mode */
437 	reg = (ili->input << 4);
438 	/* These are inverted, setting to 1 is the default, clearing flips */
439 	if (!ili->conf->flip_horizontal)
440 		reg |= ILI9322_ENTRY_HDIR;
441 	if (!ili->conf->flip_vertical)
442 		reg |= ILI9322_ENTRY_VDIR;
443 	reg |= ILI9322_ENTRY_AUTODETECT;
444 	ret = regmap_write(ili->regmap, ILI9322_ENTRY, reg);
445 	if (ret) {
446 		dev_err(ili->dev, "can't write ENTRY reg (%d)\n", ret);
447 		return ret;
448 	}
449 	dev_info(ili->dev, "display is in %s mode, syncmode %02x\n",
450 		 ili9322_inputs[ili->input],
451 		 ili->conf->syncmode);
452 
453 	dev_info(ili->dev, "initialized display\n");
454 
455 	return 0;
456 }
457 
458 /*
459  * This power-on sequence if from the datasheet, page 57.
460  */
461 static int ili9322_power_on(struct ili9322 *ili)
462 {
463 	int ret;
464 
465 	/* Assert RESET */
466 	gpiod_set_value(ili->reset_gpio, 1);
467 
468 	ret = regulator_bulk_enable(ARRAY_SIZE(ili->supplies), ili->supplies);
469 	if (ret < 0) {
470 		dev_err(ili->dev, "unable to enable regulators\n");
471 		return ret;
472 	}
473 	msleep(20);
474 
475 	/* De-assert RESET */
476 	gpiod_set_value(ili->reset_gpio, 0);
477 
478 	msleep(10);
479 
480 	return 0;
481 }
482 
483 static int ili9322_power_off(struct ili9322 *ili)
484 {
485 	return regulator_bulk_disable(ARRAY_SIZE(ili->supplies), ili->supplies);
486 }
487 
488 static int ili9322_disable(struct drm_panel *panel)
489 {
490 	struct ili9322 *ili = panel_to_ili9322(panel);
491 	int ret;
492 
493 	ret = regmap_write(ili->regmap, ILI9322_POW_CTRL,
494 			   ILI9322_POW_CTRL_STANDBY);
495 	if (ret) {
496 		dev_err(ili->dev, "unable to go to standby mode\n");
497 		return ret;
498 	}
499 
500 	return 0;
501 }
502 
503 static int ili9322_unprepare(struct drm_panel *panel)
504 {
505 	struct ili9322 *ili = panel_to_ili9322(panel);
506 
507 	return ili9322_power_off(ili);
508 }
509 
510 static int ili9322_prepare(struct drm_panel *panel)
511 {
512 	struct ili9322 *ili = panel_to_ili9322(panel);
513 	int ret;
514 
515 	ret = ili9322_power_on(ili);
516 	if (ret < 0)
517 		return ret;
518 
519 	ret = ili9322_init(panel, ili);
520 	if (ret < 0)
521 		ili9322_unprepare(panel);
522 
523 	return ret;
524 }
525 
526 static int ili9322_enable(struct drm_panel *panel)
527 {
528 	struct ili9322 *ili = panel_to_ili9322(panel);
529 	int ret;
530 
531 	ret = regmap_write(ili->regmap, ILI9322_POW_CTRL,
532 			   ILI9322_POW_CTRL_DEFAULT);
533 	if (ret) {
534 		dev_err(ili->dev, "unable to enable panel\n");
535 		return ret;
536 	}
537 
538 	return 0;
539 }
540 
541 /* Serial RGB modes */
542 static const struct drm_display_mode srgb_320x240_mode = {
543 	.clock = 24535,
544 	.hdisplay = 320,
545 	.hsync_start = 320 + 359,
546 	.hsync_end = 320 + 359 + 1,
547 	.htotal = 320 + 359 + 1 + 241,
548 	.vdisplay = 240,
549 	.vsync_start = 240 + 4,
550 	.vsync_end = 240 + 4 + 1,
551 	.vtotal = 262,
552 	.vrefresh = 60,
553 	.flags = 0,
554 };
555 
556 static const struct drm_display_mode srgb_360x240_mode = {
557 	.clock = 27000,
558 	.hdisplay = 360,
559 	.hsync_start = 360 + 35,
560 	.hsync_end = 360 + 35 + 1,
561 	.htotal = 360 + 35 + 1 + 241,
562 	.vdisplay = 240,
563 	.vsync_start = 240 + 21,
564 	.vsync_end = 240 + 21 + 1,
565 	.vtotal = 262,
566 	.vrefresh = 60,
567 	.flags = 0,
568 };
569 
570 /* This is the only mode listed for parallel RGB in the datasheet */
571 static const struct drm_display_mode prgb_320x240_mode = {
572 	.clock = 64000,
573 	.hdisplay = 320,
574 	.hsync_start = 320 + 38,
575 	.hsync_end = 320 + 38 + 1,
576 	.htotal = 320 + 38 + 1 + 50,
577 	.vdisplay = 240,
578 	.vsync_start = 240 + 4,
579 	.vsync_end = 240 + 4 + 1,
580 	.vtotal = 262,
581 	.vrefresh = 60,
582 	.flags = 0,
583 };
584 
585 /* YUV modes */
586 static const struct drm_display_mode yuv_640x320_mode = {
587 	.clock = 24540,
588 	.hdisplay = 640,
589 	.hsync_start = 640 + 252,
590 	.hsync_end = 640 + 252 + 1,
591 	.htotal = 640 + 252 + 1 + 28,
592 	.vdisplay = 320,
593 	.vsync_start = 320 + 4,
594 	.vsync_end = 320 + 4 + 1,
595 	.vtotal = 320 + 4 + 1 + 18,
596 	.vrefresh = 60,
597 	.flags = 0,
598 };
599 
600 static const struct drm_display_mode yuv_720x360_mode = {
601 	.clock = 27000,
602 	.hdisplay = 720,
603 	.hsync_start = 720 + 252,
604 	.hsync_end = 720 + 252 + 1,
605 	.htotal = 720 + 252 + 1 + 24,
606 	.vdisplay = 360,
607 	.vsync_start = 360 + 4,
608 	.vsync_end = 360 + 4 + 1,
609 	.vtotal = 360 + 4 + 1 + 18,
610 	.vrefresh = 60,
611 	.flags = 0,
612 };
613 
614 /* BT.656 VGA mode, 640x480 */
615 static const struct drm_display_mode itu_r_bt_656_640_mode = {
616 	.clock = 24540,
617 	.hdisplay = 640,
618 	.hsync_start = 640 + 3,
619 	.hsync_end = 640 + 3 + 1,
620 	.htotal = 640 + 3 + 1 + 272,
621 	.vdisplay = 480,
622 	.vsync_start = 480 + 4,
623 	.vsync_end = 480 + 4 + 1,
624 	.vtotal = 500,
625 	.vrefresh = 60,
626 	.flags = 0,
627 };
628 
629 /* BT.656 D1 mode 720x480 */
630 static const struct drm_display_mode itu_r_bt_656_720_mode = {
631 	.clock = 27000,
632 	.hdisplay = 720,
633 	.hsync_start = 720 + 3,
634 	.hsync_end = 720 + 3 + 1,
635 	.htotal = 720 + 3 + 1 + 272,
636 	.vdisplay = 480,
637 	.vsync_start = 480 + 4,
638 	.vsync_end = 480 + 4 + 1,
639 	.vtotal = 500,
640 	.vrefresh = 60,
641 	.flags = 0,
642 };
643 
644 static int ili9322_get_modes(struct drm_panel *panel,
645 			     struct drm_connector *connector)
646 {
647 	struct ili9322 *ili = panel_to_ili9322(panel);
648 	struct drm_device *drm = connector->dev;
649 	struct drm_display_mode *mode;
650 	struct drm_display_info *info;
651 
652 	info = &connector->display_info;
653 	info->width_mm = ili->conf->width_mm;
654 	info->height_mm = ili->conf->height_mm;
655 	if (ili->conf->dclk_active_high)
656 		info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
657 	else
658 		info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
659 
660 	if (ili->conf->de_active_high)
661 		info->bus_flags |= DRM_BUS_FLAG_DE_HIGH;
662 	else
663 		info->bus_flags |= DRM_BUS_FLAG_DE_LOW;
664 
665 	switch (ili->input) {
666 	case ILI9322_INPUT_SRGB_DUMMY_320X240:
667 		mode = drm_mode_duplicate(drm, &srgb_320x240_mode);
668 		break;
669 	case ILI9322_INPUT_SRGB_DUMMY_360X240:
670 		mode = drm_mode_duplicate(drm, &srgb_360x240_mode);
671 		break;
672 	case ILI9322_INPUT_PRGB_THROUGH:
673 	case ILI9322_INPUT_PRGB_ALIGNED:
674 		mode = drm_mode_duplicate(drm, &prgb_320x240_mode);
675 		break;
676 	case ILI9322_INPUT_YUV_640X320_YCBCR:
677 		mode = drm_mode_duplicate(drm, &yuv_640x320_mode);
678 		break;
679 	case ILI9322_INPUT_YUV_720X360_YCBCR:
680 		mode = drm_mode_duplicate(drm, &yuv_720x360_mode);
681 		break;
682 	case ILI9322_INPUT_ITU_R_BT656_720X360_YCBCR:
683 		mode = drm_mode_duplicate(drm, &itu_r_bt_656_720_mode);
684 		break;
685 	case ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR:
686 		mode = drm_mode_duplicate(drm, &itu_r_bt_656_640_mode);
687 		break;
688 	default:
689 		mode = NULL;
690 		break;
691 	}
692 	if (!mode) {
693 		DRM_ERROR("bad mode or failed to add mode\n");
694 		return -EINVAL;
695 	}
696 	drm_mode_set_name(mode);
697 	/*
698 	 * This is the preferred mode because most people are going
699 	 * to want to use the display with VGA type graphics.
700 	 */
701 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
702 
703 	/* Set up the polarity */
704 	if (ili->conf->hsync_active_high)
705 		mode->flags |= DRM_MODE_FLAG_PHSYNC;
706 	else
707 		mode->flags |= DRM_MODE_FLAG_NHSYNC;
708 	if (ili->conf->vsync_active_high)
709 		mode->flags |= DRM_MODE_FLAG_PVSYNC;
710 	else
711 		mode->flags |= DRM_MODE_FLAG_NVSYNC;
712 
713 	mode->width_mm = ili->conf->width_mm;
714 	mode->height_mm = ili->conf->height_mm;
715 	drm_mode_probed_add(connector, mode);
716 
717 	return 1; /* Number of modes */
718 }
719 
720 static const struct drm_panel_funcs ili9322_drm_funcs = {
721 	.disable = ili9322_disable,
722 	.unprepare = ili9322_unprepare,
723 	.prepare = ili9322_prepare,
724 	.enable = ili9322_enable,
725 	.get_modes = ili9322_get_modes,
726 };
727 
728 static int ili9322_probe(struct spi_device *spi)
729 {
730 	struct device *dev = &spi->dev;
731 	struct ili9322 *ili;
732 	const struct regmap_config *regmap_config;
733 	u8 gamma;
734 	u32 val;
735 	int ret;
736 	int i;
737 
738 	ili = devm_kzalloc(dev, sizeof(struct ili9322), GFP_KERNEL);
739 	if (!ili)
740 		return -ENOMEM;
741 
742 	spi_set_drvdata(spi, ili);
743 
744 	ili->dev = dev;
745 
746 	/*
747 	 * Every new incarnation of this display must have a unique
748 	 * data entry for the system in this driver.
749 	 */
750 	ili->conf = of_device_get_match_data(dev);
751 	if (!ili->conf) {
752 		dev_err(dev, "missing device configuration\n");
753 		return -ENODEV;
754 	}
755 
756 	val = ili->conf->vreg1out_mv;
757 	if (!val) {
758 		/* Default HW value, do not touch (should be 4.5V) */
759 		ili->vreg1out = U8_MAX;
760 	} else {
761 		if (val < 3600) {
762 			dev_err(dev, "too low VREG1OUT\n");
763 			return -EINVAL;
764 		}
765 		if (val > 6000) {
766 			dev_err(dev, "too high VREG1OUT\n");
767 			return -EINVAL;
768 		}
769 		if ((val % 100) != 0) {
770 			dev_err(dev, "VREG1OUT is no even 100 microvolt\n");
771 			return -EINVAL;
772 		}
773 		val -= 3600;
774 		val /= 100;
775 		dev_dbg(dev, "VREG1OUT = 0x%02x\n", val);
776 		ili->vreg1out = val;
777 	}
778 
779 	val = ili->conf->vcom_high_percent;
780 	if (!val) {
781 		/* Default HW value, do not touch (should be 91%) */
782 		ili->vcom_high = U8_MAX;
783 	} else {
784 		if (val < 37) {
785 			dev_err(dev, "too low VCOM high\n");
786 			return -EINVAL;
787 		}
788 		if (val > 100) {
789 			dev_err(dev, "too high VCOM high\n");
790 			return -EINVAL;
791 		}
792 		val -= 37;
793 		dev_dbg(dev, "VCOM high = 0x%02x\n", val);
794 		ili->vcom_high = val;
795 	}
796 
797 	val = ili->conf->vcom_amplitude_percent;
798 	if (!val) {
799 		/* Default HW value, do not touch (should be 114%) */
800 		ili->vcom_high = U8_MAX;
801 	} else {
802 		if (val < 70) {
803 			dev_err(dev, "too low VCOM amplitude\n");
804 			return -EINVAL;
805 		}
806 		if (val > 132) {
807 			dev_err(dev, "too high VCOM amplitude\n");
808 			return -EINVAL;
809 		}
810 		val -= 70;
811 		val >>= 1; /* Increments of 2% */
812 		dev_dbg(dev, "VCOM amplitude = 0x%02x\n", val);
813 		ili->vcom_amplitude = val;
814 	}
815 
816 	for (i = 0; i < ARRAY_SIZE(ili->gamma); i++) {
817 		val = ili->conf->gamma_corr_neg[i];
818 		if (val > 15) {
819 			dev_err(dev, "negative gamma %u > 15, capping\n", val);
820 			val = 15;
821 		}
822 		gamma = val << 4;
823 		val = ili->conf->gamma_corr_pos[i];
824 		if (val > 15) {
825 			dev_err(dev, "positive gamma %u > 15, capping\n", val);
826 			val = 15;
827 		}
828 		gamma |= val;
829 		ili->gamma[i] = gamma;
830 		dev_dbg(dev, "gamma V%d: 0x%02x\n", i + 1, gamma);
831 	}
832 
833 	ili->supplies[0].supply = "vcc"; /* 2.7-3.6 V */
834 	ili->supplies[1].supply = "iovcc"; /* 1.65-3.6V */
835 	ili->supplies[2].supply = "vci"; /* 2.7-3.6V */
836 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ili->supplies),
837 				      ili->supplies);
838 	if (ret < 0)
839 		return ret;
840 	ret = regulator_set_voltage(ili->supplies[0].consumer,
841 				    2700000, 3600000);
842 	if (ret)
843 		return ret;
844 	ret = regulator_set_voltage(ili->supplies[1].consumer,
845 				    1650000, 3600000);
846 	if (ret)
847 		return ret;
848 	ret = regulator_set_voltage(ili->supplies[2].consumer,
849 				    2700000, 3600000);
850 	if (ret)
851 		return ret;
852 
853 	ili->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
854 	if (IS_ERR(ili->reset_gpio)) {
855 		dev_err(dev, "failed to get RESET GPIO\n");
856 		return PTR_ERR(ili->reset_gpio);
857 	}
858 
859 	spi->bits_per_word = 8;
860 	ret = spi_setup(spi);
861 	if (ret < 0) {
862 		dev_err(dev, "spi setup failed.\n");
863 		return ret;
864 	}
865 	regmap_config = &ili9322_regmap_config;
866 	ili->regmap = devm_regmap_init(dev, &ili9322_regmap_bus, dev,
867 				       regmap_config);
868 	if (IS_ERR(ili->regmap)) {
869 		dev_err(dev, "failed to allocate register map\n");
870 		return PTR_ERR(ili->regmap);
871 	}
872 
873 	ret = regmap_read(ili->regmap, ILI9322_CHIP_ID, &val);
874 	if (ret) {
875 		dev_err(dev, "can't get chip ID (%d)\n", ret);
876 		return ret;
877 	}
878 	if (val != ILI9322_CHIP_ID_MAGIC) {
879 		dev_err(dev, "chip ID 0x%0x2, expected 0x%02x\n", val,
880 			ILI9322_CHIP_ID_MAGIC);
881 		return -ENODEV;
882 	}
883 
884 	/* Probe the system to find the display setting */
885 	if (ili->conf->input == ILI9322_INPUT_UNKNOWN) {
886 		ret = regmap_read(ili->regmap, ILI9322_ENTRY, &val);
887 		if (ret) {
888 			dev_err(dev, "can't get entry setting (%d)\n", ret);
889 			return ret;
890 		}
891 		/* Input enum corresponds to HW setting */
892 		ili->input = (val >> 4) & 0x0f;
893 		if (ili->input >= ILI9322_INPUT_UNKNOWN)
894 			ili->input = ILI9322_INPUT_UNKNOWN;
895 	} else {
896 		ili->input = ili->conf->input;
897 	}
898 
899 	drm_panel_init(&ili->panel, dev, &ili9322_drm_funcs,
900 		       DRM_MODE_CONNECTOR_DPI);
901 
902 	return drm_panel_add(&ili->panel);
903 }
904 
905 static int ili9322_remove(struct spi_device *spi)
906 {
907 	struct ili9322 *ili = spi_get_drvdata(spi);
908 
909 	ili9322_power_off(ili);
910 	drm_panel_remove(&ili->panel);
911 
912 	return 0;
913 }
914 
915 /*
916  * The D-Link DIR-685 panel is marked LM918A01-1A SY-B4-091116-E0199
917  */
918 static const struct ili9322_config ili9322_dir_685 = {
919 	.width_mm = 65,
920 	.height_mm = 50,
921 	.input = ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR,
922 	.vreg1out_mv = 4600,
923 	.vcom_high_percent = 91,
924 	.vcom_amplitude_percent = 114,
925 	.syncmode = ILI9322_IF_CTRL_SYNC_DISABLED,
926 	.dclk_active_high = true,
927 	.gamma_corr_neg = { 0xa, 0x5, 0x7, 0x7, 0x7, 0x5, 0x1, 0x6 },
928 	.gamma_corr_pos = { 0x7, 0x7, 0x3, 0x2, 0x3, 0x5, 0x7, 0x2 },
929 };
930 
931 static const struct of_device_id ili9322_of_match[] = {
932 	{
933 		.compatible = "dlink,dir-685-panel",
934 		.data = &ili9322_dir_685,
935 	},
936 	{
937 		.compatible = "ilitek,ili9322",
938 		.data = NULL,
939 	},
940 	{ }
941 };
942 MODULE_DEVICE_TABLE(of, ili9322_of_match);
943 
944 static struct spi_driver ili9322_driver = {
945 	.probe = ili9322_probe,
946 	.remove = ili9322_remove,
947 	.driver = {
948 		.name = "panel-ilitek-ili9322",
949 		.of_match_table = ili9322_of_match,
950 	},
951 };
952 module_spi_driver(ili9322_driver);
953 
954 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
955 MODULE_DESCRIPTION("ILI9322 LCD panel driver");
956 MODULE_LICENSE("GPL v2");
957