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