Merge tag 'arc-5.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
[linux-2.6-microblaze.git] / drivers / gpu / drm / panel / panel-ilitek-ili9322.c
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 <drm/drmP.h>
23 #include <drm/drm_panel.h>
24
25 #include <linux/of_device.h>
26 #include <linux/bitops.h>
27 #include <linux/gpio/consumer.h>
28 #include <linux/module.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 #define ILI9322_CHIP_ID                 0x00
38 #define ILI9322_CHIP_ID_MAGIC           0x96
39
40 /*
41  * Voltage on the communication interface, from 0.7 (0x00)
42  * to 1.32 (0x1f) times the VREG1OUT voltage in 2% increments.
43  * 1.00 (0x0f) is the default.
44  */
45 #define ILI9322_VCOM_AMP                0x01
46
47 /*
48  * High voltage on the communication signals, from 0.37 (0x00) to
49  * 1.0 (0x3f) times the VREGOUT1 voltage in 1% increments.
50  * 0.83 (0x2e) is the default.
51  */
52 #define ILI9322_VCOM_HIGH               0x02
53
54 /*
55  * VREG1 voltage regulator from 3.6V (0x00) to 6.0V (0x18) in 0.1V
56  * increments. 5.4V (0x12) is the default. This is the reference
57  * voltage for the VCOM levels and the greyscale level.
58  */
59 #define ILI9322_VREG1_VOLTAGE           0x03
60
61 /* Describes the incoming signal */
62 #define ILI9322_ENTRY                   0x06
63 /* 0 = right-to-left, 1 = left-to-right (default), horizontal flip */
64 #define ILI9322_ENTRY_HDIR              BIT(0)
65 /* 0 = down-to-up, 1 = up-to-down (default), vertical flip  */
66 #define ILI9322_ENTRY_VDIR              BIT(1)
67 /* NTSC, PAL or autodetect */
68 #define ILI9322_ENTRY_NTSC              (0 << 2)
69 #define ILI9322_ENTRY_PAL               (1 << 2)
70 #define ILI9322_ENTRY_AUTODETECT        (3 << 2)
71 /* Input format */
72 #define ILI9322_ENTRY_SERIAL_RGB_THROUGH (0 << 4)
73 #define ILI9322_ENTRY_SERIAL_RGB_ALIGNED (1 << 4)
74 #define ILI9322_ENTRY_SERIAL_RGB_DUMMY_320X240 (2 << 4)
75 #define ILI9322_ENTRY_SERIAL_RGB_DUMMY_360X240 (3 << 4)
76 #define ILI9322_ENTRY_DISABLE_1         (4 << 4)
77 #define ILI9322_ENTRY_PARALLEL_RGB_THROUGH (5 << 4)
78 #define ILI9322_ENTRY_PARALLEL_RGB_ALIGNED (6 << 4)
79 #define ILI9322_ENTRY_YUV_640Y_320CBCR_25_54_MHZ (7 << 4)
80 #define ILI9322_ENTRY_YUV_720Y_360CBCR_27_MHZ (8 << 4)
81 #define ILI9322_ENTRY_DISABLE_2         (9 << 4)
82 #define ILI9322_ENTRY_ITU_R_BT_656_720X360 (10 << 4)
83 #define ILI9322_ENTRY_ITU_R_BT_656_640X320 (11 << 4)
84
85 /* Power control */
86 #define ILI9322_POW_CTRL                0x07
87 #define ILI9322_POW_CTRL_STB            BIT(0) /* 0 = standby, 1 = normal */
88 #define ILI9322_POW_CTRL_VGL            BIT(1) /* 0 = off, 1 = on  */
89 #define ILI9322_POW_CTRL_VGH            BIT(2) /* 0 = off, 1 = on  */
90 #define ILI9322_POW_CTRL_DDVDH          BIT(3) /* 0 = off, 1 = on  */
91 #define ILI9322_POW_CTRL_VCOM           BIT(4) /* 0 = off, 1 = on  */
92 #define ILI9322_POW_CTRL_VCL            BIT(5) /* 0 = off, 1 = on  */
93 #define ILI9322_POW_CTRL_AUTO           BIT(6) /* 0 = interactive, 1 = auto */
94 #define ILI9322_POW_CTRL_STANDBY        (ILI9322_POW_CTRL_VGL | \
95                                          ILI9322_POW_CTRL_VGH | \
96                                          ILI9322_POW_CTRL_DDVDH | \
97                                          ILI9322_POW_CTRL_VCL | \
98                                          ILI9322_POW_CTRL_AUTO | \
99                                          BIT(7))
100 #define ILI9322_POW_CTRL_DEFAULT        (ILI9322_POW_CTRL_STANDBY | \
101                                          ILI9322_POW_CTRL_STB)
102
103 /* Vertical back porch bits 0..5 */
104 #define ILI9322_VBP                     0x08
105
106 /* Horizontal back porch, 8 bits */
107 #define ILI9322_HBP                     0x09
108
109 /*
110  * Polarity settings:
111  * 1 = positive polarity
112  * 0 = negative polarity
113  */
114 #define ILI9322_POL                     0x0a
115 #define ILI9322_POL_DCLK                BIT(0) /* 1 default */
116 #define ILI9322_POL_HSYNC               BIT(1) /* 0 default */
117 #define ILI9322_POL_VSYNC               BIT(2) /* 0 default */
118 #define ILI9322_POL_DE                  BIT(3) /* 1 default */
119 /*
120  * 0 means YCBCR are ordered Cb0,Y0,Cr0,Y1,Cb2,Y2,Cr2,Y3 (default)
121  *   in RGB mode this means RGB comes in RGBRGB
122  * 1 means YCBCR are ordered Cr0,Y0,Cb0,Y1,Cr2,Y2,Cb2,Y3
123  *   in RGB mode this means RGB comes in BGRBGR
124  */
125 #define ILI9322_POL_YCBCR_MODE          BIT(4)
126 /* Formula A for YCbCR->RGB = 0, Formula B = 1 */
127 #define ILI9322_POL_FORMULA             BIT(5)
128 /* Reverse polarity: 0 = 0..255, 1 = 255..0 */
129 #define ILI9322_POL_REV                 BIT(6)
130
131 #define ILI9322_IF_CTRL                 0x0b
132 #define ILI9322_IF_CTRL_HSYNC_VSYNC     0x00
133 #define ILI9322_IF_CTRL_HSYNC_VSYNC_DE  BIT(2)
134 #define ILI9322_IF_CTRL_DE_ONLY         BIT(3)
135 #define ILI9322_IF_CTRL_SYNC_DISABLED   (BIT(2) | BIT(3))
136 #define ILI9322_IF_CTRL_LINE_INVERSION  BIT(0) /* Not set means frame inv */
137
138 #define ILI9322_GLOBAL_RESET            0x04
139 #define ILI9322_GLOBAL_RESET_ASSERT     0x00 /* bit 0 = 0 -> reset */
140
141 /*
142  * 4+4 bits of negative and positive gamma correction
143  * Upper nybble, bits 4-7 are negative gamma
144  * Lower nybble, bits 0-3 are positive gamma
145  */
146 #define ILI9322_GAMMA_1                 0x10
147 #define ILI9322_GAMMA_2                 0x11
148 #define ILI9322_GAMMA_3                 0x12
149 #define ILI9322_GAMMA_4                 0x13
150 #define ILI9322_GAMMA_5                 0x14
151 #define ILI9322_GAMMA_6                 0x15
152 #define ILI9322_GAMMA_7                 0x16
153 #define ILI9322_GAMMA_8                 0x17
154
155 /**
156  * enum ili9322_input - the format of the incoming signal to the panel
157  *
158  * The panel can be connected to various input streams and four of them can
159  * be selected by electronic straps on the display. However it is possible
160  * to select another mode or override the electronic default with this
161  * setting.
162  */
163 enum ili9322_input {
164         ILI9322_INPUT_SRGB_THROUGH = 0x0,
165         ILI9322_INPUT_SRGB_ALIGNED = 0x1,
166         ILI9322_INPUT_SRGB_DUMMY_320X240 = 0x2,
167         ILI9322_INPUT_SRGB_DUMMY_360X240 = 0x3,
168         ILI9322_INPUT_DISABLED_1 = 0x4,
169         ILI9322_INPUT_PRGB_THROUGH = 0x5,
170         ILI9322_INPUT_PRGB_ALIGNED = 0x6,
171         ILI9322_INPUT_YUV_640X320_YCBCR = 0x7,
172         ILI9322_INPUT_YUV_720X360_YCBCR = 0x8,
173         ILI9322_INPUT_DISABLED_2 = 0x9,
174         ILI9322_INPUT_ITU_R_BT656_720X360_YCBCR = 0xa,
175         ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR = 0xb,
176         ILI9322_INPUT_UNKNOWN = 0xc,
177 };
178
179 static const char * const ili9322_inputs[] = {
180         "8 bit serial RGB through",
181         "8 bit serial RGB aligned",
182         "8 bit serial RGB dummy 320x240",
183         "8 bit serial RGB dummy 360x240",
184         "disabled 1",
185         "24 bit parallel RGB through",
186         "24 bit parallel RGB aligned",
187         "24 bit YUV 640Y 320CbCr",
188         "24 bit YUV 720Y 360CbCr",
189         "disabled 2",
190         "8 bit ITU-R BT.656 720Y 360CbCr",
191         "8 bit ITU-R BT.656 640Y 320CbCr",
192 };
193
194 /**
195  * struct ili9322_config - the system specific ILI9322 configuration
196  * @width_mm: physical panel width [mm]
197  * @height_mm: physical panel height [mm]
198  * @flip_horizontal: flip the image horizontally (right-to-left scan)
199  * (only in RGB and YUV modes)
200  * @flip_vertical: flip the image vertically (down-to-up scan)
201  * (only in RGB and YUV modes)
202  * @input: the input/entry type used in this system, if this is set to
203  * ILI9322_INPUT_UNKNOWN the driver will try to figure it out by probing
204  * the hardware
205  * @vreg1out_mv: the output in microvolts for the VREGOUT1 regulator used
206  * to drive the physical display. Valid ranges are 3600 thru 6000 in 100
207  * microvolt increments. If not specified, hardware defaults will be
208  * used (4.5V).
209  * @vcom_high_percent: the percentage of VREGOUT1 used for the peak
210  * voltage on the communications link. Valid ranges are 37 thru 100
211  * percent. If not specified, hardware defaults will be used (91%).
212  * @vcom_amplitude_percent: the percentage of VREGOUT1 used for the
213  * peak-to-peak amplitude of the communcation signals to the physical
214  * display. Valid ranges are 70 thru 132 percent in increments if two
215  * percent. Odd percentages will be truncated. If not specified, hardware
216  * defaults will be used (114%).
217  * @dclk_active_high: data/pixel clock active high, data will be clocked
218  * in on the rising edge of the DCLK (this is usually the case).
219  * @syncmode: The synchronization mode, what sync signals are emitted.
220  * See the enum for details.
221  * @de_active_high: DE (data entry) is active high
222  * @hsync_active_high: HSYNC is active high
223  * @vsync_active_high: VSYNC is active high
224  * @gamma_corr_pos: a set of 8 nybbles describing positive
225  * gamma correction for voltages V1 thru V8. Valid range 0..15
226  * @gamma_corr_neg: a set of 8 nybbles describing negative
227  * gamma correction for voltages V1 thru V8. Valid range 0..15
228  *
229  * These adjust what grayscale voltage will be output for input data V1 = 0,
230  * V2 = 16, V3 = 48, V4 = 96, V5 = 160, V6 = 208, V7 = 240 and V8 = 255.
231  * The curve is shaped like this:
232  *
233  *  ^
234  *  |                                                        V8
235  *  |                                                   V7
236  *  |                                          V6
237  *  |                               V5
238  *  |                    V4
239  *  |            V3
240  *  |     V2
241  *  | V1
242  *  +----------------------------------------------------------->
243  *    0   16     48      96         160        208      240  255
244  *
245  * The negative and postive gamma values adjust the V1 thru V8 up/down
246  * according to the datasheet specifications. This is a property of the
247  * physical display connected to the display controller and may vary.
248  * If defined, both arrays must be supplied in full. If the properties
249  * are not supplied, hardware defaults will be used.
250  */
251 struct ili9322_config {
252         u32 width_mm;
253         u32 height_mm;
254         bool flip_horizontal;
255         bool flip_vertical;
256         enum ili9322_input input;
257         u32 vreg1out_mv;
258         u32 vcom_high_percent;
259         u32 vcom_amplitude_percent;
260         bool dclk_active_high;
261         bool de_active_high;
262         bool hsync_active_high;
263         bool vsync_active_high;
264         u8 syncmode;
265         u8 gamma_corr_pos[8];
266         u8 gamma_corr_neg[8];
267 };
268
269 struct ili9322 {
270         struct device *dev;
271         const struct ili9322_config *conf;
272         struct drm_panel panel;
273         struct regmap *regmap;
274         struct regulator_bulk_data supplies[3];
275         struct gpio_desc *reset_gpio;
276         enum ili9322_input input;
277         struct videomode vm;
278         u8 gamma[8];
279         u8 vreg1out;
280         u8 vcom_high;
281         u8 vcom_amplitude;
282 };
283
284 static inline struct ili9322 *panel_to_ili9322(struct drm_panel *panel)
285 {
286         return container_of(panel, struct ili9322, panel);
287 }
288
289 static int ili9322_regmap_spi_write(void *context, const void *data,
290                                     size_t count)
291 {
292         struct device *dev = context;
293         struct spi_device *spi = to_spi_device(dev);
294         u8 buf[2];
295
296         /* Clear bit 7 to write */
297         memcpy(buf, data, 2);
298         buf[0] &= ~0x80;
299
300         dev_dbg(dev, "WRITE: %02x %02x\n", buf[0], buf[1]);
301         return spi_write_then_read(spi, buf, 2, NULL, 0);
302 }
303
304 static int ili9322_regmap_spi_read(void *context, const void *reg,
305                                    size_t reg_size, void *val, size_t val_size)
306 {
307         struct device *dev = context;
308         struct spi_device *spi = to_spi_device(dev);
309         u8 buf[1];
310
311         /* Set bit 7 to 1 to read */
312         memcpy(buf, reg, 1);
313         dev_dbg(dev, "READ: %02x reg size = %zu, val size = %zu\n",
314                 buf[0], reg_size, val_size);
315         buf[0] |= 0x80;
316
317         return spi_write_then_read(spi, buf, 1, val, 1);
318 }
319
320 static struct regmap_bus ili9322_regmap_bus = {
321         .write = ili9322_regmap_spi_write,
322         .read = ili9322_regmap_spi_read,
323         .reg_format_endian_default = REGMAP_ENDIAN_BIG,
324         .val_format_endian_default = REGMAP_ENDIAN_BIG,
325 };
326
327 static bool ili9322_volatile_reg(struct device *dev, unsigned int reg)
328 {
329         return false;
330 }
331
332 static bool ili9322_writeable_reg(struct device *dev, unsigned int reg)
333 {
334         /* Just register 0 is read-only */
335         if (reg == 0x00)
336                 return false;
337         return true;
338 }
339
340 static const struct regmap_config ili9322_regmap_config = {
341         .reg_bits = 8,
342         .val_bits = 8,
343         .max_register = 0x44,
344         .cache_type = REGCACHE_RBTREE,
345         .volatile_reg = ili9322_volatile_reg,
346         .writeable_reg = ili9322_writeable_reg,
347 };
348
349 static int ili9322_init(struct drm_panel *panel, struct ili9322 *ili)
350 {
351         struct drm_connector *connector = panel->connector;
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         if (ili->conf->dclk_active_high) {
410                 reg = ILI9322_POL_DCLK;
411                 connector->display_info.bus_flags |=
412                         DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
413         } else {
414                 reg = 0;
415                 connector->display_info.bus_flags |=
416                         DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
417         }
418         if (ili->conf->de_active_high) {
419                 reg |= ILI9322_POL_DE;
420                 connector->display_info.bus_flags |=
421                         DRM_BUS_FLAG_DE_HIGH;
422         } else {
423                 connector->display_info.bus_flags |=
424                         DRM_BUS_FLAG_DE_LOW;
425         }
426         if (ili->conf->hsync_active_high)
427                 reg |= ILI9322_POL_HSYNC;
428         if (ili->conf->vsync_active_high)
429                 reg |= ILI9322_POL_VSYNC;
430         ret = regmap_write(ili->regmap, ILI9322_POL, reg);
431         if (ret) {
432                 dev_err(ili->dev, "can't write POL register (%d)\n", ret);
433                 return ret;
434         }
435
436         /*
437          * Set up interface control.
438          * This is not used in the BT.656 mode (no H/Vsync or DE signals).
439          */
440         reg = ili->conf->syncmode;
441         reg |= ILI9322_IF_CTRL_LINE_INVERSION;
442         ret = regmap_write(ili->regmap, ILI9322_IF_CTRL, reg);
443         if (ret) {
444                 dev_err(ili->dev, "can't write IF CTRL register (%d)\n", ret);
445                 return ret;
446         }
447
448         /* Set up the input mode */
449         reg = (ili->input << 4);
450         /* These are inverted, setting to 1 is the default, clearing flips */
451         if (!ili->conf->flip_horizontal)
452                 reg |= ILI9322_ENTRY_HDIR;
453         if (!ili->conf->flip_vertical)
454                 reg |= ILI9322_ENTRY_VDIR;
455         reg |= ILI9322_ENTRY_AUTODETECT;
456         ret = regmap_write(ili->regmap, ILI9322_ENTRY, reg);
457         if (ret) {
458                 dev_err(ili->dev, "can't write ENTRY reg (%d)\n", ret);
459                 return ret;
460         }
461         dev_info(ili->dev, "display is in %s mode, syncmode %02x\n",
462                  ili9322_inputs[ili->input],
463                  ili->conf->syncmode);
464
465         dev_info(ili->dev, "initialized display\n");
466
467         return 0;
468 }
469
470 /*
471  * This power-on sequence if from the datasheet, page 57.
472  */
473 static int ili9322_power_on(struct ili9322 *ili)
474 {
475         int ret;
476
477         /* Assert RESET */
478         gpiod_set_value(ili->reset_gpio, 1);
479
480         ret = regulator_bulk_enable(ARRAY_SIZE(ili->supplies), ili->supplies);
481         if (ret < 0) {
482                 dev_err(ili->dev, "unable to enable regulators\n");
483                 return ret;
484         }
485         msleep(20);
486
487         /* De-assert RESET */
488         gpiod_set_value(ili->reset_gpio, 0);
489
490         msleep(10);
491
492         return 0;
493 }
494
495 static int ili9322_power_off(struct ili9322 *ili)
496 {
497         return regulator_bulk_disable(ARRAY_SIZE(ili->supplies), ili->supplies);
498 }
499
500 static int ili9322_disable(struct drm_panel *panel)
501 {
502         struct ili9322 *ili = panel_to_ili9322(panel);
503         int ret;
504
505         ret = regmap_write(ili->regmap, ILI9322_POW_CTRL,
506                            ILI9322_POW_CTRL_STANDBY);
507         if (ret) {
508                 dev_err(ili->dev, "unable to go to standby mode\n");
509                 return ret;
510         }
511
512         return 0;
513 }
514
515 static int ili9322_unprepare(struct drm_panel *panel)
516 {
517         struct ili9322 *ili = panel_to_ili9322(panel);
518
519         return ili9322_power_off(ili);
520 }
521
522 static int ili9322_prepare(struct drm_panel *panel)
523 {
524         struct ili9322 *ili = panel_to_ili9322(panel);
525         int ret;
526
527         ret = ili9322_power_on(ili);
528         if (ret < 0)
529                 return ret;
530
531         ret = ili9322_init(panel, ili);
532         if (ret < 0)
533                 ili9322_unprepare(panel);
534
535         return ret;
536 }
537
538 static int ili9322_enable(struct drm_panel *panel)
539 {
540         struct ili9322 *ili = panel_to_ili9322(panel);
541         int ret;
542
543         ret = regmap_write(ili->regmap, ILI9322_POW_CTRL,
544                            ILI9322_POW_CTRL_DEFAULT);
545         if (ret) {
546                 dev_err(ili->dev, "unable to enable panel\n");
547                 return ret;
548         }
549
550         return 0;
551 }
552
553 /* Serial RGB modes */
554 static const struct drm_display_mode srgb_320x240_mode = {
555         .clock = 2453500,
556         .hdisplay = 320,
557         .hsync_start = 320 + 359,
558         .hsync_end = 320 + 359 + 1,
559         .htotal = 320 + 359 + 1 + 241,
560         .vdisplay = 240,
561         .vsync_start = 240 + 4,
562         .vsync_end = 240 + 4 + 1,
563         .vtotal = 262,
564         .vrefresh = 60,
565         .flags = 0,
566 };
567
568 static const struct drm_display_mode srgb_360x240_mode = {
569         .clock = 2700000,
570         .hdisplay = 360,
571         .hsync_start = 360 + 35,
572         .hsync_end = 360 + 35 + 1,
573         .htotal = 360 + 35 + 1 + 241,
574         .vdisplay = 240,
575         .vsync_start = 240 + 21,
576         .vsync_end = 240 + 21 + 1,
577         .vtotal = 262,
578         .vrefresh = 60,
579         .flags = 0,
580 };
581
582 /* This is the only mode listed for parallel RGB in the datasheet */
583 static const struct drm_display_mode prgb_320x240_mode = {
584         .clock = 6400000,
585         .hdisplay = 320,
586         .hsync_start = 320 + 38,
587         .hsync_end = 320 + 38 + 1,
588         .htotal = 320 + 38 + 1 + 50,
589         .vdisplay = 240,
590         .vsync_start = 240 + 4,
591         .vsync_end = 240 + 4 + 1,
592         .vtotal = 262,
593         .vrefresh = 60,
594         .flags = 0,
595 };
596
597 /* YUV modes */
598 static const struct drm_display_mode yuv_640x320_mode = {
599         .clock = 2454000,
600         .hdisplay = 640,
601         .hsync_start = 640 + 252,
602         .hsync_end = 640 + 252 + 1,
603         .htotal = 640 + 252 + 1 + 28,
604         .vdisplay = 320,
605         .vsync_start = 320 + 4,
606         .vsync_end = 320 + 4 + 1,
607         .vtotal = 320 + 4 + 1 + 18,
608         .vrefresh = 60,
609         .flags = 0,
610 };
611
612 static const struct drm_display_mode yuv_720x360_mode = {
613         .clock = 2700000,
614         .hdisplay = 720,
615         .hsync_start = 720 + 252,
616         .hsync_end = 720 + 252 + 1,
617         .htotal = 720 + 252 + 1 + 24,
618         .vdisplay = 360,
619         .vsync_start = 360 + 4,
620         .vsync_end = 360 + 4 + 1,
621         .vtotal = 360 + 4 + 1 + 18,
622         .vrefresh = 60,
623         .flags = 0,
624 };
625
626 /* BT.656 VGA mode, 640x480 */
627 static const struct drm_display_mode itu_r_bt_656_640_mode = {
628         .clock = 2454000,
629         .hdisplay = 640,
630         .hsync_start = 640 + 3,
631         .hsync_end = 640 + 3 + 1,
632         .htotal = 640 + 3 + 1 + 272,
633         .vdisplay = 480,
634         .vsync_start = 480 + 4,
635         .vsync_end = 480 + 4 + 1,
636         .vtotal = 500,
637         .vrefresh = 60,
638         .flags = 0,
639 };
640
641 /* BT.656 D1 mode 720x480 */
642 static const struct drm_display_mode itu_r_bt_656_720_mode = {
643         .clock = 2700000,
644         .hdisplay = 720,
645         .hsync_start = 720 + 3,
646         .hsync_end = 720 + 3 + 1,
647         .htotal = 720 + 3 + 1 + 272,
648         .vdisplay = 480,
649         .vsync_start = 480 + 4,
650         .vsync_end = 480 + 4 + 1,
651         .vtotal = 500,
652         .vrefresh = 60,
653         .flags = 0,
654 };
655
656 static int ili9322_get_modes(struct drm_panel *panel)
657 {
658         struct drm_connector *connector = panel->connector;
659         struct ili9322 *ili = panel_to_ili9322(panel);
660         struct drm_display_mode *mode;
661
662         connector->display_info.width_mm = ili->conf->width_mm;
663         connector->display_info.height_mm = ili->conf->height_mm;
664
665         switch (ili->input) {
666         case ILI9322_INPUT_SRGB_DUMMY_320X240:
667                 mode = drm_mode_duplicate(panel->drm, &srgb_320x240_mode);
668                 break;
669         case ILI9322_INPUT_SRGB_DUMMY_360X240:
670                 mode = drm_mode_duplicate(panel->drm, &srgb_360x240_mode);
671                 break;
672         case ILI9322_INPUT_PRGB_THROUGH:
673         case ILI9322_INPUT_PRGB_ALIGNED:
674                 mode = drm_mode_duplicate(panel->drm, &prgb_320x240_mode);
675                 break;
676         case ILI9322_INPUT_YUV_640X320_YCBCR:
677                 mode = drm_mode_duplicate(panel->drm, &yuv_640x320_mode);
678                 break;
679         case ILI9322_INPUT_YUV_720X360_YCBCR:
680                 mode = drm_mode_duplicate(panel->drm, &yuv_720x360_mode);
681                 break;
682         case ILI9322_INPUT_ITU_R_BT656_720X360_YCBCR:
683                 mode = drm_mode_duplicate(panel->drm, &itu_r_bt_656_720_mode);
684                 break;
685         case ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR:
686                 mode = drm_mode_duplicate(panel->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);
900         ili->panel.dev = dev;
901         ili->panel.funcs = &ili9322_drm_funcs;
902
903         return drm_panel_add(&ili->panel);
904 }
905
906 static int ili9322_remove(struct spi_device *spi)
907 {
908         struct ili9322 *ili = spi_get_drvdata(spi);
909
910         ili9322_power_off(ili);
911         drm_panel_remove(&ili->panel);
912
913         return 0;
914 }
915
916 /*
917  * The D-Link DIR-685 panel is marked LM918A01-1A SY-B4-091116-E0199
918  */
919 static const struct ili9322_config ili9322_dir_685 = {
920         .width_mm = 65,
921         .height_mm = 50,
922         .input = ILI9322_INPUT_ITU_R_BT656_640X320_YCBCR,
923         .vreg1out_mv = 4600,
924         .vcom_high_percent = 91,
925         .vcom_amplitude_percent = 114,
926         .syncmode = ILI9322_IF_CTRL_SYNC_DISABLED,
927         .dclk_active_high = true,
928         .gamma_corr_neg = { 0xa, 0x5, 0x7, 0x7, 0x7, 0x5, 0x1, 0x6 },
929         .gamma_corr_pos = { 0x7, 0x7, 0x3, 0x2, 0x3, 0x5, 0x7, 0x2 },
930 };
931
932 static const struct of_device_id ili9322_of_match[] = {
933         {
934                 .compatible = "dlink,dir-685-panel",
935                 .data = &ili9322_dir_685,
936         },
937         {
938                 .compatible = "ilitek,ili9322",
939                 .data = NULL,
940         },
941         { }
942 };
943 MODULE_DEVICE_TABLE(of, ili9322_of_match);
944
945 static struct spi_driver ili9322_driver = {
946         .probe = ili9322_probe,
947         .remove = ili9322_remove,
948         .driver = {
949                 .name = "panel-ilitek-ili9322",
950                 .of_match_table = ili9322_of_match,
951         },
952 };
953 module_spi_driver(ili9322_driver);
954
955 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
956 MODULE_DESCRIPTION("ILI9322 LCD panel driver");
957 MODULE_LICENSE("GPL v2");