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