]> Git Repo - linux.git/blob - drivers/gpu/drm/panel/panel-ilitek-ili9322.c
Revert "drm/amdgpu: add param to specify fw bo location for front-door loading"
[linux.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 <[email protected]>
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
285 static inline struct ili9322 *panel_to_ili9322(struct drm_panel *panel)
286 {
287         return container_of(panel, struct ili9322, panel);
288 }
289
290 static int ili9322_regmap_spi_write(void *context, const void *data,
291                                     size_t count)
292 {
293         struct device *dev = context;
294         struct spi_device *spi = to_spi_device(dev);
295         u8 buf[2];
296
297         /* Clear bit 7 to write */
298         memcpy(buf, data, 2);
299         buf[0] &= ~0x80;
300
301         dev_dbg(dev, "WRITE: %02x %02x\n", buf[0], buf[1]);
302         return spi_write_then_read(spi, buf, 2, NULL, 0);
303 }
304
305 static int ili9322_regmap_spi_read(void *context, const void *reg,
306                                    size_t reg_size, void *val, size_t val_size)
307 {
308         struct device *dev = context;
309         struct spi_device *spi = to_spi_device(dev);
310         u8 buf[1];
311
312         /* Set bit 7 to 1 to read */
313         memcpy(buf, reg, 1);
314         dev_dbg(dev, "READ: %02x reg size = %zu, val size = %zu\n",
315                 buf[0], reg_size, val_size);
316         buf[0] |= 0x80;
317
318         return spi_write_then_read(spi, buf, 1, val, 1);
319 }
320
321 static struct regmap_bus ili9322_regmap_bus = {
322         .write = ili9322_regmap_spi_write,
323         .read = ili9322_regmap_spi_read,
324         .reg_format_endian_default = REGMAP_ENDIAN_BIG,
325         .val_format_endian_default = REGMAP_ENDIAN_BIG,
326 };
327
328 static bool ili9322_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
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  */
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
477 static int ili9322_power_off(struct ili9322 *ili)
478 {
479         return regulator_bulk_disable(ARRAY_SIZE(ili->supplies), ili->supplies);
480 }
481
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
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
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
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
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
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
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 <[email protected]>");
942 MODULE_DESCRIPTION("ILI9322 LCD panel driver");
943 MODULE_LICENSE("GPL v2");
This page took 0.092328 seconds and 4 git commands to generate.