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 	struct drm_connector *connector = panel->connector;
353 	u8 reg;
354 	int ret;
355 	int i;
356 
357 	/* Reset display */
358 	ret = regmap_write(ili->regmap, ILI9322_GLOBAL_RESET,
359 			   ILI9322_GLOBAL_RESET_ASSERT);
360 	if (ret) {
361 		dev_err(ili->dev, "can't issue GRESET (%d)\n", ret);
362 		return ret;
363 	}
364 
365 	/* Set up the main voltage regulator */
366 	if (ili->vreg1out != U8_MAX) {
367 		ret = regmap_write(ili->regmap, ILI9322_VREG1_VOLTAGE,
368 				   ili->vreg1out);
369 		if (ret) {
370 			dev_err(ili->dev, "can't set up VREG1OUT (%d)\n", ret);
371 			return ret;
372 		}
373 	}
374 
375 	if (ili->vcom_amplitude != U8_MAX) {
376 		ret = regmap_write(ili->regmap, ILI9322_VCOM_AMP,
377 				   ili->vcom_amplitude);
378 		if (ret) {
379 			dev_err(ili->dev,
380 				"can't set up VCOM amplitude (%d)\n", ret);
381 			return ret;
382 		}
383 	};
384 
385 	if (ili->vcom_high != U8_MAX) {
386 		ret = regmap_write(ili->regmap, ILI9322_VCOM_HIGH,
387 				   ili->vcom_high);
388 		if (ret) {
389 			dev_err(ili->dev, "can't set up VCOM high (%d)\n", ret);
390 			return ret;
391 		}
392 	};
393 
394 	/* Set up gamma correction */
395 	for (i = 0; i < ARRAY_SIZE(ili->gamma); i++) {
396 		ret = regmap_write(ili->regmap, ILI9322_GAMMA_1 + i,
397 				   ili->gamma[i]);
398 		if (ret) {
399 			dev_err(ili->dev,
400 				"can't write gamma V%d to 0x%02x (%d)\n",
401 				i + 1, ILI9322_GAMMA_1 + i, ret);
402 			return ret;
403 		}
404 	}
405 
406 	/*
407 	 * Polarity and inverted color order for RGB input.
408 	 * None of this applies in the BT.656 mode.
409 	 */
410 	if (ili->conf->dclk_active_high) {
411 		reg = ILI9322_POL_DCLK;
412 		connector->display_info.bus_flags |=
413 			DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
414 	} else {
415 		reg = 0;
416 		connector->display_info.bus_flags |=
417 			DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
418 	}
419 	if (ili->conf->de_active_high) {
420 		reg |= ILI9322_POL_DE;
421 		connector->display_info.bus_flags |=
422 			DRM_BUS_FLAG_DE_HIGH;
423 	} else {
424 		connector->display_info.bus_flags |=
425 			DRM_BUS_FLAG_DE_LOW;
426 	}
427 	if (ili->conf->hsync_active_high)
428 		reg |= ILI9322_POL_HSYNC;
429 	if (ili->conf->vsync_active_high)
430 		reg |= ILI9322_POL_VSYNC;
431 	ret = regmap_write(ili->regmap, ILI9322_POL, reg);
432 	if (ret) {
433 		dev_err(ili->dev, "can't write POL register (%d)\n", ret);
434 		return ret;
435 	}
436 
437 	/*
438 	 * Set up interface control.
439 	 * This is not used in the BT.656 mode (no H/Vsync or DE signals).
440 	 */
441 	reg = ili->conf->syncmode;
442 	reg |= ILI9322_IF_CTRL_LINE_INVERSION;
443 	ret = regmap_write(ili->regmap, ILI9322_IF_CTRL, reg);
444 	if (ret) {
445 		dev_err(ili->dev, "can't write IF CTRL register (%d)\n", ret);
446 		return ret;
447 	}
448 
449 	/* Set up the input mode */
450 	reg = (ili->input << 4);
451 	/* These are inverted, setting to 1 is the default, clearing flips */
452 	if (!ili->conf->flip_horizontal)
453 		reg |= ILI9322_ENTRY_HDIR;
454 	if (!ili->conf->flip_vertical)
455 		reg |= ILI9322_ENTRY_VDIR;
456 	reg |= ILI9322_ENTRY_AUTODETECT;
457 	ret = regmap_write(ili->regmap, ILI9322_ENTRY, reg);
458 	if (ret) {
459 		dev_err(ili->dev, "can't write ENTRY reg (%d)\n", ret);
460 		return ret;
461 	}
462 	dev_info(ili->dev, "display is in %s mode, syncmode %02x\n",
463 		 ili9322_inputs[ili->input],
464 		 ili->conf->syncmode);
465 
466 	dev_info(ili->dev, "initialized display\n");
467 
468 	return 0;
469 }
470 
471 /*
472  * This power-on sequence if from the datasheet, page 57.
473  */
474 static int ili9322_power_on(struct ili9322 *ili)
475 {
476 	int ret;
477 
478 	/* Assert RESET */
479 	gpiod_set_value(ili->reset_gpio, 1);
480 
481 	ret = regulator_bulk_enable(ARRAY_SIZE(ili->supplies), ili->supplies);
482 	if (ret < 0) {
483 		dev_err(ili->dev, "unable to enable regulators\n");
484 		return ret;
485 	}
486 	msleep(20);
487 
488 	/* De-assert RESET */
489 	gpiod_set_value(ili->reset_gpio, 0);
490 
491 	msleep(10);
492 
493 	return 0;
494 }
495 
496 static int ili9322_power_off(struct ili9322 *ili)
497 {
498 	return regulator_bulk_disable(ARRAY_SIZE(ili->supplies), ili->supplies);
499 }
500 
501 static int ili9322_disable(struct drm_panel *panel)
502 {
503 	struct ili9322 *ili = panel_to_ili9322(panel);
504 	int ret;
505 
506 	ret = regmap_write(ili->regmap, ILI9322_POW_CTRL,
507 			   ILI9322_POW_CTRL_STANDBY);
508 	if (ret) {
509 		dev_err(ili->dev, "unable to go to standby mode\n");
510 		return ret;
511 	}
512 
513 	return 0;
514 }
515 
516 static int ili9322_unprepare(struct drm_panel *panel)
517 {
518 	struct ili9322 *ili = panel_to_ili9322(panel);
519 
520 	return ili9322_power_off(ili);
521 }
522 
523 static int ili9322_prepare(struct drm_panel *panel)
524 {
525 	struct ili9322 *ili = panel_to_ili9322(panel);
526 	int ret;
527 
528 	ret = ili9322_power_on(ili);
529 	if (ret < 0)
530 		return ret;
531 
532 	ret = ili9322_init(panel, ili);
533 	if (ret < 0)
534 		ili9322_unprepare(panel);
535 
536 	return ret;
537 }
538 
539 static int ili9322_enable(struct drm_panel *panel)
540 {
541 	struct ili9322 *ili = panel_to_ili9322(panel);
542 	int ret;
543 
544 	ret = regmap_write(ili->regmap, ILI9322_POW_CTRL,
545 			   ILI9322_POW_CTRL_DEFAULT);
546 	if (ret) {
547 		dev_err(ili->dev, "unable to enable panel\n");
548 		return ret;
549 	}
550 
551 	return 0;
552 }
553 
554 /* Serial RGB modes */
555 static const struct drm_display_mode srgb_320x240_mode = {
556 	.clock = 2453500,
557 	.hdisplay = 320,
558 	.hsync_start = 320 + 359,
559 	.hsync_end = 320 + 359 + 1,
560 	.htotal = 320 + 359 + 1 + 241,
561 	.vdisplay = 240,
562 	.vsync_start = 240 + 4,
563 	.vsync_end = 240 + 4 + 1,
564 	.vtotal = 262,
565 	.vrefresh = 60,
566 	.flags = 0,
567 };
568 
569 static const struct drm_display_mode srgb_360x240_mode = {
570 	.clock = 2700000,
571 	.hdisplay = 360,
572 	.hsync_start = 360 + 35,
573 	.hsync_end = 360 + 35 + 1,
574 	.htotal = 360 + 35 + 1 + 241,
575 	.vdisplay = 240,
576 	.vsync_start = 240 + 21,
577 	.vsync_end = 240 + 21 + 1,
578 	.vtotal = 262,
579 	.vrefresh = 60,
580 	.flags = 0,
581 };
582 
583 /* This is the only mode listed for parallel RGB in the datasheet */
584 static const struct drm_display_mode prgb_320x240_mode = {
585 	.clock = 6400000,
586 	.hdisplay = 320,
587 	.hsync_start = 320 + 38,
588 	.hsync_end = 320 + 38 + 1,
589 	.htotal = 320 + 38 + 1 + 50,
590 	.vdisplay = 240,
591 	.vsync_start = 240 + 4,
592 	.vsync_end = 240 + 4 + 1,
593 	.vtotal = 262,
594 	.vrefresh = 60,
595 	.flags = 0,
596 };
597 
598 /* YUV modes */
599 static const struct drm_display_mode yuv_640x320_mode = {
600 	.clock = 2454000,
601 	.hdisplay = 640,
602 	.hsync_start = 640 + 252,
603 	.hsync_end = 640 + 252 + 1,
604 	.htotal = 640 + 252 + 1 + 28,
605 	.vdisplay = 320,
606 	.vsync_start = 320 + 4,
607 	.vsync_end = 320 + 4 + 1,
608 	.vtotal = 320 + 4 + 1 + 18,
609 	.vrefresh = 60,
610 	.flags = 0,
611 };
612 
613 static const struct drm_display_mode yuv_720x360_mode = {
614 	.clock = 2700000,
615 	.hdisplay = 720,
616 	.hsync_start = 720 + 252,
617 	.hsync_end = 720 + 252 + 1,
618 	.htotal = 720 + 252 + 1 + 24,
619 	.vdisplay = 360,
620 	.vsync_start = 360 + 4,
621 	.vsync_end = 360 + 4 + 1,
622 	.vtotal = 360 + 4 + 1 + 18,
623 	.vrefresh = 60,
624 	.flags = 0,
625 };
626 
627 /* BT.656 VGA mode, 640x480 */
628 static const struct drm_display_mode itu_r_bt_656_640_mode = {
629 	.clock = 2454000,
630 	.hdisplay = 640,
631 	.hsync_start = 640 + 3,
632 	.hsync_end = 640 + 3 + 1,
633 	.htotal = 640 + 3 + 1 + 272,
634 	.vdisplay = 480,
635 	.vsync_start = 480 + 4,
636 	.vsync_end = 480 + 4 + 1,
637 	.vtotal = 500,
638 	.vrefresh = 60,
639 	.flags = 0,
640 };
641 
642 /* BT.656 D1 mode 720x480 */
643 static const struct drm_display_mode itu_r_bt_656_720_mode = {
644 	.clock = 2700000,
645 	.hdisplay = 720,
646 	.hsync_start = 720 + 3,
647 	.hsync_end = 720 + 3 + 1,
648 	.htotal = 720 + 3 + 1 + 272,
649 	.vdisplay = 480,
650 	.vsync_start = 480 + 4,
651 	.vsync_end = 480 + 4 + 1,
652 	.vtotal = 500,
653 	.vrefresh = 60,
654 	.flags = 0,
655 };
656 
657 static int ili9322_get_modes(struct drm_panel *panel)
658 {
659 	struct drm_connector *connector = panel->connector;
660 	struct ili9322 *ili = panel_to_ili9322(panel);
661 	struct drm_display_mode *mode;
662 
663 	connector->display_info.width_mm = ili->conf->width_mm;
664 	connector->display_info.height_mm = ili->conf->height_mm;
665 
666 	switch (ili->input) {
667 	case ILI9322_INPUT_SRGB_DUMMY_320X240:
668 		mode = drm_mode_duplicate(panel->drm, &srgb_320x240_mode);
669 		break;
670 	case ILI9322_INPUT_SRGB_DUMMY_360X240:
671 		mode = drm_mode_duplicate(panel->drm, &srgb_360x240_mode);
672 		break;
673 	case ILI9322_INPUT_PRGB_THROUGH:
674 	case ILI9322_INPUT_PRGB_ALIGNED:
675 		mode = drm_mode_duplicate(panel->drm, &prgb_320x240_mode);
676 		break;
677 	case ILI9322_INPUT_YUV_640X320_YCBCR:
678 		mode = drm_mode_duplicate(panel->drm, &yuv_640x320_mode);
679 		break;
680 	case ILI9322_INPUT_YUV_720X360_YCBCR:
681 		mode = drm_mode_duplicate(panel->drm, &yuv_720x360_mode);
682 		break;
683 	case ILI9322_INPUT_ITU_R_BT656_720X360_YCBCR:
684 		mode = drm_mode_duplicate(panel->drm, &itu_r_bt_656_720_mode);
685 		break;
686 	case ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR:
687 		mode = drm_mode_duplicate(panel->drm, &itu_r_bt_656_640_mode);
688 		break;
689 	default:
690 		mode = NULL;
691 		break;
692 	}
693 	if (!mode) {
694 		DRM_ERROR("bad mode or failed to add mode\n");
695 		return -EINVAL;
696 	}
697 	drm_mode_set_name(mode);
698 	/*
699 	 * This is the preferred mode because most people are going
700 	 * to want to use the display with VGA type graphics.
701 	 */
702 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
703 
704 	/* Set up the polarity */
705 	if (ili->conf->hsync_active_high)
706 		mode->flags |= DRM_MODE_FLAG_PHSYNC;
707 	else
708 		mode->flags |= DRM_MODE_FLAG_NHSYNC;
709 	if (ili->conf->vsync_active_high)
710 		mode->flags |= DRM_MODE_FLAG_PVSYNC;
711 	else
712 		mode->flags |= DRM_MODE_FLAG_NVSYNC;
713 
714 	mode->width_mm = ili->conf->width_mm;
715 	mode->height_mm = ili->conf->height_mm;
716 	drm_mode_probed_add(connector, mode);
717 
718 	return 1; /* Number of modes */
719 }
720 
721 static const struct drm_panel_funcs ili9322_drm_funcs = {
722 	.disable = ili9322_disable,
723 	.unprepare = ili9322_unprepare,
724 	.prepare = ili9322_prepare,
725 	.enable = ili9322_enable,
726 	.get_modes = ili9322_get_modes,
727 };
728 
729 static int ili9322_probe(struct spi_device *spi)
730 {
731 	struct device *dev = &spi->dev;
732 	struct ili9322 *ili;
733 	const struct regmap_config *regmap_config;
734 	u8 gamma;
735 	u32 val;
736 	int ret;
737 	int i;
738 
739 	ili = devm_kzalloc(dev, sizeof(struct ili9322), GFP_KERNEL);
740 	if (!ili)
741 		return -ENOMEM;
742 
743 	spi_set_drvdata(spi, ili);
744 
745 	ili->dev = dev;
746 
747 	/*
748 	 * Every new incarnation of this display must have a unique
749 	 * data entry for the system in this driver.
750 	 */
751 	ili->conf = of_device_get_match_data(dev);
752 	if (!ili->conf) {
753 		dev_err(dev, "missing device configuration\n");
754 		return -ENODEV;
755 	}
756 
757 	val = ili->conf->vreg1out_mv;
758 	if (!val) {
759 		/* Default HW value, do not touch (should be 4.5V) */
760 		ili->vreg1out = U8_MAX;
761 	} else {
762 		if (val < 3600) {
763 			dev_err(dev, "too low VREG1OUT\n");
764 			return -EINVAL;
765 		}
766 		if (val > 6000) {
767 			dev_err(dev, "too high VREG1OUT\n");
768 			return -EINVAL;
769 		}
770 		if ((val % 100) != 0) {
771 			dev_err(dev, "VREG1OUT is no even 100 microvolt\n");
772 			return -EINVAL;
773 		}
774 		val -= 3600;
775 		val /= 100;
776 		dev_dbg(dev, "VREG1OUT = 0x%02x\n", val);
777 		ili->vreg1out = val;
778 	}
779 
780 	val = ili->conf->vcom_high_percent;
781 	if (!val) {
782 		/* Default HW value, do not touch (should be 91%) */
783 		ili->vcom_high = U8_MAX;
784 	} else {
785 		if (val < 37) {
786 			dev_err(dev, "too low VCOM high\n");
787 			return -EINVAL;
788 		}
789 		if (val > 100) {
790 			dev_err(dev, "too high VCOM high\n");
791 			return -EINVAL;
792 		}
793 		val -= 37;
794 		dev_dbg(dev, "VCOM high = 0x%02x\n", val);
795 		ili->vcom_high = val;
796 	}
797 
798 	val = ili->conf->vcom_amplitude_percent;
799 	if (!val) {
800 		/* Default HW value, do not touch (should be 114%) */
801 		ili->vcom_high = U8_MAX;
802 	} else {
803 		if (val < 70) {
804 			dev_err(dev, "too low VCOM amplitude\n");
805 			return -EINVAL;
806 		}
807 		if (val > 132) {
808 			dev_err(dev, "too high VCOM amplitude\n");
809 			return -EINVAL;
810 		}
811 		val -= 70;
812 		val >>= 1; /* Increments of 2% */
813 		dev_dbg(dev, "VCOM amplitude = 0x%02x\n", val);
814 		ili->vcom_amplitude = val;
815 	}
816 
817 	for (i = 0; i < ARRAY_SIZE(ili->gamma); i++) {
818 		val = ili->conf->gamma_corr_neg[i];
819 		if (val > 15) {
820 			dev_err(dev, "negative gamma %u > 15, capping\n", val);
821 			val = 15;
822 		}
823 		gamma = val << 4;
824 		val = ili->conf->gamma_corr_pos[i];
825 		if (val > 15) {
826 			dev_err(dev, "positive gamma %u > 15, capping\n", val);
827 			val = 15;
828 		}
829 		gamma |= val;
830 		ili->gamma[i] = gamma;
831 		dev_dbg(dev, "gamma V%d: 0x%02x\n", i + 1, gamma);
832 	}
833 
834 	ili->supplies[0].supply = "vcc"; /* 2.7-3.6 V */
835 	ili->supplies[1].supply = "iovcc"; /* 1.65-3.6V */
836 	ili->supplies[2].supply = "vci"; /* 2.7-3.6V */
837 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ili->supplies),
838 				      ili->supplies);
839 	if (ret < 0)
840 		return ret;
841 	ret = regulator_set_voltage(ili->supplies[0].consumer,
842 				    2700000, 3600000);
843 	if (ret)
844 		return ret;
845 	ret = regulator_set_voltage(ili->supplies[1].consumer,
846 				    1650000, 3600000);
847 	if (ret)
848 		return ret;
849 	ret = regulator_set_voltage(ili->supplies[2].consumer,
850 				    2700000, 3600000);
851 	if (ret)
852 		return ret;
853 
854 	ili->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
855 	if (IS_ERR(ili->reset_gpio)) {
856 		dev_err(dev, "failed to get RESET GPIO\n");
857 		return PTR_ERR(ili->reset_gpio);
858 	}
859 
860 	spi->bits_per_word = 8;
861 	ret = spi_setup(spi);
862 	if (ret < 0) {
863 		dev_err(dev, "spi setup failed.\n");
864 		return ret;
865 	}
866 	regmap_config = &ili9322_regmap_config;
867 	ili->regmap = devm_regmap_init(dev, &ili9322_regmap_bus, dev,
868 				       regmap_config);
869 	if (IS_ERR(ili->regmap)) {
870 		dev_err(dev, "failed to allocate register map\n");
871 		return PTR_ERR(ili->regmap);
872 	}
873 
874 	ret = regmap_read(ili->regmap, ILI9322_CHIP_ID, &val);
875 	if (ret) {
876 		dev_err(dev, "can't get chip ID (%d)\n", ret);
877 		return ret;
878 	}
879 	if (val != ILI9322_CHIP_ID_MAGIC) {
880 		dev_err(dev, "chip ID 0x%0x2, expected 0x%02x\n", val,
881 			ILI9322_CHIP_ID_MAGIC);
882 		return -ENODEV;
883 	}
884 
885 	/* Probe the system to find the display setting */
886 	if (ili->conf->input == ILI9322_INPUT_UNKNOWN) {
887 		ret = regmap_read(ili->regmap, ILI9322_ENTRY, &val);
888 		if (ret) {
889 			dev_err(dev, "can't get entry setting (%d)\n", ret);
890 			return ret;
891 		}
892 		/* Input enum corresponds to HW setting */
893 		ili->input = (val >> 4) & 0x0f;
894 		if (ili->input >= ILI9322_INPUT_UNKNOWN)
895 			ili->input = ILI9322_INPUT_UNKNOWN;
896 	} else {
897 		ili->input = ili->conf->input;
898 	}
899 
900 	drm_panel_init(&ili->panel);
901 	ili->panel.dev = dev;
902 	ili->panel.funcs = &ili9322_drm_funcs;
903 
904 	return drm_panel_add(&ili->panel);
905 }
906 
907 static int ili9322_remove(struct spi_device *spi)
908 {
909 	struct ili9322 *ili = spi_get_drvdata(spi);
910 
911 	ili9322_power_off(ili);
912 	drm_panel_remove(&ili->panel);
913 
914 	return 0;
915 }
916 
917 /*
918  * The D-Link DIR-685 panel is marked LM918A01-1A SY-B4-091116-E0199
919  */
920 static const struct ili9322_config ili9322_dir_685 = {
921 	.width_mm = 65,
922 	.height_mm = 50,
923 	.input = ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR,
924 	.vreg1out_mv = 4600,
925 	.vcom_high_percent = 91,
926 	.vcom_amplitude_percent = 114,
927 	.syncmode = ILI9322_IF_CTRL_SYNC_DISABLED,
928 	.dclk_active_high = true,
929 	.gamma_corr_neg = { 0xa, 0x5, 0x7, 0x7, 0x7, 0x5, 0x1, 0x6 },
930 	.gamma_corr_pos = { 0x7, 0x7, 0x3, 0x2, 0x3, 0x5, 0x7, 0x2 },
931 };
932 
933 static const struct of_device_id ili9322_of_match[] = {
934 	{
935 		.compatible = "dlink,dir-685-panel",
936 		.data = &ili9322_dir_685,
937 	},
938 	{
939 		.compatible = "ilitek,ili9322",
940 		.data = NULL,
941 	},
942 	{ }
943 };
944 MODULE_DEVICE_TABLE(of, ili9322_of_match);
945 
946 static struct spi_driver ili9322_driver = {
947 	.probe = ili9322_probe,
948 	.remove = ili9322_remove,
949 	.driver = {
950 		.name = "panel-ilitek-ili9322",
951 		.of_match_table = ili9322_of_match,
952 	},
953 };
954 module_spi_driver(ili9322_driver);
955 
956 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
957 MODULE_DESCRIPTION("ILI9322 LCD panel driver");
958 MODULE_LICENSE("GPL v2");
959