GNU Linux-libre 4.19.268-gnu1
[releases.git] / drivers / staging / fbtft / fbtft_device.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *
4  * Copyright (C) 2013, Noralf Tronnes
5  */
6
7 #define pr_fmt(fmt) "fbtft_device: " fmt
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <linux/gpio.h>
12 #include <linux/spi/spi.h>
13 #include <video/mipi_display.h>
14
15 #include "fbtft.h"
16
17 #define MAX_GPIOS 32
18
19 static struct spi_device *spi_device;
20 static struct platform_device *p_device;
21
22 static char *name;
23 module_param(name, charp, 0000);
24 MODULE_PARM_DESC(name,
25                  "Devicename (required). name=list => list all supported devices.");
26
27 static unsigned int rotate;
28 module_param(rotate, uint, 0000);
29 MODULE_PARM_DESC(rotate,
30                  "Angle to rotate display counter clockwise: 0, 90, 180, 270");
31
32 static unsigned int busnum;
33 module_param(busnum, uint, 0000);
34 MODULE_PARM_DESC(busnum, "SPI bus number (default=0)");
35
36 static unsigned int cs;
37 module_param(cs, uint, 0000);
38 MODULE_PARM_DESC(cs, "SPI chip select (default=0)");
39
40 static unsigned int speed;
41 module_param(speed, uint, 0000);
42 MODULE_PARM_DESC(speed, "SPI speed (override device default)");
43
44 static int mode = -1;
45 module_param(mode, int, 0000);
46 MODULE_PARM_DESC(mode, "SPI mode (override device default)");
47
48 static char *gpios;
49 module_param(gpios, charp, 0000);
50 MODULE_PARM_DESC(gpios,
51                  "List of gpios. Comma separated with the form: reset:23,dc:24 (when overriding the default, all gpios must be specified)");
52
53 static unsigned int fps;
54 module_param(fps, uint, 0000);
55 MODULE_PARM_DESC(fps, "Frames per second (override driver default)");
56
57 static char *gamma;
58 module_param(gamma, charp, 0000);
59 MODULE_PARM_DESC(gamma,
60                  "String representation of Gamma Curve(s). Driver specific.");
61
62 static int txbuflen;
63 module_param(txbuflen, int, 0000);
64 MODULE_PARM_DESC(txbuflen, "txbuflen (override driver default)");
65
66 static int bgr = -1;
67 module_param(bgr, int, 0000);
68 MODULE_PARM_DESC(bgr,
69                  "BGR bit (supported by some drivers).");
70
71 static unsigned int startbyte;
72 module_param(startbyte, uint, 0000);
73 MODULE_PARM_DESC(startbyte, "Sets the Start byte used by some SPI displays.");
74
75 static bool custom;
76 module_param(custom, bool, 0000);
77 MODULE_PARM_DESC(custom, "Add a custom display device. Use speed= argument to make it a SPI device, else platform_device");
78
79 static unsigned int width;
80 module_param(width, uint, 0000);
81 MODULE_PARM_DESC(width, "Display width, used with the custom argument");
82
83 static unsigned int height;
84 module_param(height, uint, 0000);
85 MODULE_PARM_DESC(height, "Display height, used with the custom argument");
86
87 static unsigned int buswidth = 8;
88 module_param(buswidth, uint, 0000);
89 MODULE_PARM_DESC(buswidth, "Display bus width, used with the custom argument");
90
91 static s16 init[FBTFT_MAX_INIT_SEQUENCE];
92 static int init_num;
93 module_param_array(init, short, &init_num, 0000);
94 MODULE_PARM_DESC(init, "Init sequence, used with the custom argument");
95
96 static unsigned long debug;
97 module_param(debug, ulong, 0000);
98 MODULE_PARM_DESC(debug,
99                  "level: 0-7 (the remaining 29 bits is for advanced usage)");
100
101 static unsigned int verbose = 3;
102 module_param(verbose, uint, 0000);
103 MODULE_PARM_DESC(verbose,
104                  "0 silent, >0 show gpios, >1 show devices, >2 show devices before (default=3)");
105
106 struct fbtft_device_display {
107         char *name;
108         struct spi_board_info *spi;
109         struct platform_device *pdev;
110 };
111
112 static void fbtft_device_pdev_release(struct device *dev);
113
114 static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len);
115 static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par,
116                                               int xs, int ys, int xe, int ye);
117
118 #define ADAFRUIT18_GAMMA \
119                 "02 1c 07 12 37 32 29 2d 29 25 2B 39 00 01 03 10\n" \
120                 "03 1d 07 06 2E 2C 29 2D 2E 2E 37 3F 00 00 02 10"
121
122 #define CBERRY28_GAMMA \
123                 "D0 00 14 15 13 2C 42 43 4E 09 16 14 18 21\n" \
124                 "D0 00 14 15 13 0B 43 55 53 0C 17 14 23 20"
125
126 static const s16 cberry28_init_sequence[] = {
127         /* turn off sleep mode */
128         -1, MIPI_DCS_EXIT_SLEEP_MODE,
129         -2, 120,
130
131         /* set pixel format to RGB-565 */
132         -1, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT,
133
134         -1, 0xB2, 0x0C, 0x0C, 0x00, 0x33, 0x33,
135
136         /*
137          * VGH = 13.26V
138          * VGL = -10.43V
139          */
140         -1, 0xB7, 0x35,
141
142         /*
143          * VDV and VRH register values come from command write
144          * (instead of NVM)
145          */
146         -1, 0xC2, 0x01, 0xFF,
147
148         /*
149          * VAP =  4.7V + (VCOM + VCOM offset + 0.5 * VDV)
150          * VAN = -4.7V + (VCOM + VCOM offset + 0.5 * VDV)
151          */
152         -1, 0xC3, 0x17,
153
154         /* VDV = 0V */
155         -1, 0xC4, 0x20,
156
157         /* VCOM = 0.675V */
158         -1, 0xBB, 0x17,
159
160         /* VCOM offset = 0V */
161         -1, 0xC5, 0x20,
162
163         /*
164          * AVDD = 6.8V
165          * AVCL = -4.8V
166          * VDS = 2.3V
167          */
168         -1, 0xD0, 0xA4, 0xA1,
169
170         -1, MIPI_DCS_SET_DISPLAY_ON,
171
172         -3,
173 };
174
175 static const s16 hy28b_init_sequence[] = {
176         -1, 0x00e7, 0x0010, -1, 0x0000, 0x0001,
177         -1, 0x0001, 0x0100, -1, 0x0002, 0x0700,
178         -1, 0x0003, 0x1030, -1, 0x0004, 0x0000,
179         -1, 0x0008, 0x0207, -1, 0x0009, 0x0000,
180         -1, 0x000a, 0x0000, -1, 0x000c, 0x0001,
181         -1, 0x000d, 0x0000, -1, 0x000f, 0x0000,
182         -1, 0x0010, 0x0000, -1, 0x0011, 0x0007,
183         -1, 0x0012, 0x0000, -1, 0x0013, 0x0000,
184         -2, 50, -1, 0x0010, 0x1590, -1, 0x0011,
185         0x0227, -2, 50, -1, 0x0012, 0x009c, -2, 50,
186         -1, 0x0013, 0x1900, -1, 0x0029, 0x0023,
187         -1, 0x002b, 0x000e, -2, 50,
188         -1, 0x0020, 0x0000, -1, 0x0021, 0x0000,
189         -2, 50, -1, 0x0050, 0x0000,
190         -1, 0x0051, 0x00ef, -1, 0x0052, 0x0000,
191         -1, 0x0053, 0x013f, -1, 0x0060, 0xa700,
192         -1, 0x0061, 0x0001, -1, 0x006a, 0x0000,
193         -1, 0x0080, 0x0000, -1, 0x0081, 0x0000,
194         -1, 0x0082, 0x0000, -1, 0x0083, 0x0000,
195         -1, 0x0084, 0x0000, -1, 0x0085, 0x0000,
196         -1, 0x0090, 0x0010, -1, 0x0092, 0x0000,
197         -1, 0x0093, 0x0003, -1, 0x0095, 0x0110,
198         -1, 0x0097, 0x0000, -1, 0x0098, 0x0000,
199         -1, 0x0007, 0x0133, -1, 0x0020, 0x0000,
200         -1, 0x0021, 0x0000, -2, 100, -3 };
201
202 #define HY28B_GAMMA \
203         "04 1F 4 7 7 0 7 7 6 0\n" \
204         "0F 00 1 7 4 0 0 0 6 7"
205
206 static const s16 pitft_init_sequence[] = {
207         -1, MIPI_DCS_SOFT_RESET,
208         -2, 5,
209         -1, MIPI_DCS_SET_DISPLAY_OFF,
210         -1, 0xEF, 0x03, 0x80, 0x02,
211         -1, 0xCF, 0x00, 0xC1, 0x30,
212         -1, 0xED, 0x64, 0x03, 0x12, 0x81,
213         -1, 0xE8, 0x85, 0x00, 0x78,
214         -1, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
215         -1, 0xF7, 0x20,
216         -1, 0xEA, 0x00, 0x00,
217         -1, 0xC0, 0x23,
218         -1, 0xC1, 0x10,
219         -1, 0xC5, 0x3E, 0x28,
220         -1, 0xC7, 0x86,
221         -1, MIPI_DCS_SET_PIXEL_FORMAT, 0x55,
222         -1, 0xB1, 0x00, 0x18,
223         -1, 0xB6, 0x08, 0x82, 0x27,
224         -1, 0xF2, 0x00,
225         -1, MIPI_DCS_SET_GAMMA_CURVE, 0x01,
226         -1, 0xE0, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E,
227                 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
228         -1, 0xE1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31,
229                 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
230         -1, MIPI_DCS_EXIT_SLEEP_MODE,
231         -2, 100,
232         -1, MIPI_DCS_SET_DISPLAY_ON,
233         -2, 20,
234         -3
235 };
236
237 static const s16 waveshare32b_init_sequence[] = {
238         -1, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
239         -1, 0xCF, 0x00, 0xC1, 0x30,
240         -1, 0xE8, 0x85, 0x00, 0x78,
241         -1, 0xEA, 0x00, 0x00,
242         -1, 0xED, 0x64, 0x03, 0x12, 0x81,
243         -1, 0xF7, 0x20,
244         -1, 0xC0, 0x23,
245         -1, 0xC1, 0x10,
246         -1, 0xC5, 0x3E, 0x28,
247         -1, 0xC7, 0x86,
248         -1, MIPI_DCS_SET_ADDRESS_MODE, 0x28,
249         -1, MIPI_DCS_SET_PIXEL_FORMAT, 0x55,
250         -1, 0xB1, 0x00, 0x18,
251         -1, 0xB6, 0x08, 0x82, 0x27,
252         -1, 0xF2, 0x00,
253         -1, MIPI_DCS_SET_GAMMA_CURVE, 0x01,
254         -1, 0xE0, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E,
255                 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
256         -1, 0xE1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31,
257                 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
258         -1, MIPI_DCS_EXIT_SLEEP_MODE,
259         -2, 120,
260         -1, MIPI_DCS_SET_DISPLAY_ON,
261         -1, MIPI_DCS_WRITE_MEMORY_START,
262         -3
263 };
264
265 #define PIOLED_GAMMA    "0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 " \
266                         "2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 " \
267                         "3 3 3 4 4 4 4 4 4 4 4 4 4 4 4"
268
269 /* Supported displays in alphabetical order */
270 static struct fbtft_device_display displays[] = {
271         {
272                 .name = "adafruit18",
273                 .spi = &(struct spi_board_info) {
274                         .modalias = "fb_st7735r",
275                         .max_speed_hz = 32000000,
276                         .mode = SPI_MODE_0,
277                         .platform_data = &(struct fbtft_platform_data) {
278                                 .display = {
279                                         .buswidth = 8,
280                                         .backlight = 1,
281                                 },
282                                 .gpios = (const struct fbtft_gpio []) {
283                                         { "reset", 25 },
284                                         { "dc", 24 },
285                                         { "led", 18 },
286                                         {},
287                                 },
288                                 .gamma = ADAFRUIT18_GAMMA,
289                         }
290                 }
291         }, {
292                 .name = "adafruit18_green",
293                 .spi = &(struct spi_board_info) {
294                         .modalias = "fb_st7735r",
295                         .max_speed_hz = 4000000,
296                         .mode = SPI_MODE_0,
297                         .platform_data = &(struct fbtft_platform_data) {
298                                 .display = {
299                                         .buswidth = 8,
300                                         .backlight = 1,
301                                         .fbtftops.set_addr_win =
302                                             adafruit18_green_tab_set_addr_win,
303                                 },
304                                 .bgr = true,
305                                 .gpios = (const struct fbtft_gpio []) {
306                                         { "reset", 25 },
307                                         { "dc", 24 },
308                                         { "led", 18 },
309                                         {},
310                                 },
311                                 .gamma = ADAFRUIT18_GAMMA,
312                         }
313                 }
314         }, {
315                 .name = "adafruit22",
316                 .spi = &(struct spi_board_info) {
317                         .modalias = "fb_hx8340bn",
318                         .max_speed_hz = 32000000,
319                         .mode = SPI_MODE_0,
320                         .platform_data = &(struct fbtft_platform_data) {
321                                 .display = {
322                                         .buswidth = 9,
323                                         .backlight = 1,
324                                 },
325                                 .bgr = true,
326                                 .gpios = (const struct fbtft_gpio []) {
327                                         { "reset", 25 },
328                                         { "led", 23 },
329                                         {},
330                                 },
331                         }
332                 }
333         }, {
334                 .name = "adafruit22a",
335                 .spi = &(struct spi_board_info) {
336                         .modalias = "fb_ili9340",
337                         .max_speed_hz = 32000000,
338                         .mode = SPI_MODE_0,
339                         .platform_data = &(struct fbtft_platform_data) {
340                                 .display = {
341                                         .buswidth = 8,
342                                         .backlight = 1,
343                                 },
344                                 .bgr = true,
345                                 .gpios = (const struct fbtft_gpio []) {
346                                         { "reset", 25 },
347                                         { "dc", 24 },
348                                         { "led", 18 },
349                                         {},
350                                 },
351                         }
352                 }
353         }, {
354                 .name = "adafruit28",
355                 .spi = &(struct spi_board_info) {
356                         .modalias = "fb_ili9341",
357                         .max_speed_hz = 32000000,
358                         .mode = SPI_MODE_0,
359                         .platform_data = &(struct fbtft_platform_data) {
360                                 .display = {
361                                         .buswidth = 8,
362                                         .backlight = 1,
363                                 },
364                                 .bgr = true,
365                                 .gpios = (const struct fbtft_gpio []) {
366                                         { "reset", 25 },
367                                         { "dc", 24 },
368                                         { "led", 18 },
369                                         {},
370                                 },
371                         }
372                 }
373         }, {
374                 .name = "adafruit13m",
375                 .spi = &(struct spi_board_info) {
376                         .modalias = "fb_ssd1306",
377                         .max_speed_hz = 16000000,
378                         .mode = SPI_MODE_0,
379                         .platform_data = &(struct fbtft_platform_data) {
380                                 .display = {
381                                         .buswidth = 8,
382                                 },
383                                 .gpios = (const struct fbtft_gpio []) {
384                                         { "reset", 25 },
385                                         { "dc", 24 },
386                                         {},
387                                 },
388                         }
389                 }
390         }, {
391                 .name = "admatec_c-berry28",
392                 .spi = &(struct spi_board_info) {
393                         .modalias = "fb_st7789v",
394                         .max_speed_hz = 48000000,
395                         .mode = SPI_MODE_0,
396                         .platform_data = &(struct fbtft_platform_data) {
397                                 .display = {
398                                         .buswidth = 8,
399                                         .backlight = 1,
400                                         .init_sequence = cberry28_init_sequence,
401                                 },
402                                 .gpios = (const struct fbtft_gpio []) {
403                                         { "reset", 25 },
404                                         { "dc", 22 },
405                                         { "led", 18 },
406                                         {},
407                                 },
408                                 .gamma = CBERRY28_GAMMA,
409                         }
410                 }
411         }, {
412                 .name = "agm1264k-fl",
413                 .pdev = &(struct platform_device) {
414                         .name = "fb_agm1264k-fl",
415                         .id = 0,
416                         .dev = {
417                         .release = fbtft_device_pdev_release,
418                         .platform_data = &(struct fbtft_platform_data) {
419                                 .display = {
420                                         .buswidth = 8,
421                                         .backlight = FBTFT_ONBOARD_BACKLIGHT,
422                                 },
423                                 .gpios = (const struct fbtft_gpio []) {
424                                         {},
425                                 },
426                         },
427                         }
428                 }
429         }, {
430                 .name = "dogs102",
431                 .spi = &(struct spi_board_info) {
432                         .modalias = "fb_uc1701",
433                         .max_speed_hz = 8000000,
434                         .mode = SPI_MODE_0,
435                         .platform_data = &(struct fbtft_platform_data) {
436                                 .display = {
437                                         .buswidth = 8,
438                                 },
439                                 .bgr = true,
440                                 .gpios = (const struct fbtft_gpio []) {
441                                         { "reset", 13 },
442                                         { "dc", 6 },
443                                         {},
444                                 },
445                         }
446                 }
447         }, {
448                 .name = "er_tftm050_2",
449                 .spi = &(struct spi_board_info) {
450                         .modalias = "fb_ra8875",
451                         .max_speed_hz = 5000000,
452                         .mode = SPI_MODE_3,
453                         .platform_data = &(struct fbtft_platform_data) {
454                                 .display = {
455                                         .buswidth = 8,
456                                         .backlight = 1,
457                                         .width = 480,
458                                         .height = 272,
459                                 },
460                                 .bgr = true,
461                                 .gpios = (const struct fbtft_gpio []) {
462                                         { "reset", 25 },
463                                         { "dc", 24 },
464                                         {},
465                                 },
466                         }
467                 }
468         }, {
469                 .name = "er_tftm070_5",
470                 .spi = &(struct spi_board_info) {
471                         .modalias = "fb_ra8875",
472                         .max_speed_hz = 5000000,
473                         .mode = SPI_MODE_3,
474                         .platform_data = &(struct fbtft_platform_data) {
475                                 .display = {
476                                         .buswidth = 8,
477                                         .backlight = 1,
478                                         .width = 800,
479                                         .height = 480,
480                                 },
481                                 .bgr = true,
482                                 .gpios = (const struct fbtft_gpio []) {
483                                         { "reset", 25 },
484                                         { "dc", 24 },
485                                         {},
486                                 },
487                         }
488                 }
489         }, {
490                 .name = "ew24ha0",
491                 .spi = &(struct spi_board_info) {
492                         .modalias = "fb_uc1611",
493                         .max_speed_hz = 32000000,
494                         .mode = SPI_MODE_3,
495                         .platform_data = &(struct fbtft_platform_data) {
496                                 .display = {
497                                         .buswidth = 8,
498                                 },
499                                 .gpios = (const struct fbtft_gpio []) {
500                                         { "dc", 24 },
501                                         {},
502                                 },
503                         }
504                 }
505         }, {
506                 .name = "ew24ha0_9bit",
507                 .spi = &(struct spi_board_info) {
508                         .modalias = "fb_uc1611",
509                         .max_speed_hz = 32000000,
510                         .mode = SPI_MODE_3,
511                         .platform_data = &(struct fbtft_platform_data) {
512                                 .display = {
513                                         .buswidth = 9,
514                                 },
515                                 .gpios = (const struct fbtft_gpio []) {
516                                         {},
517                                 },
518                         }
519                 }
520         }, {
521                 .name = "flexfb",
522                 .spi = &(struct spi_board_info) {
523                         .modalias = "flexfb",
524                         .max_speed_hz = 32000000,
525                         .mode = SPI_MODE_0,
526                         .platform_data = &(struct fbtft_platform_data) {
527                                 .gpios = (const struct fbtft_gpio []) {
528                                         { "reset", 25 },
529                                         { "dc", 24 },
530                                         {},
531                                 },
532                         }
533                 }
534         }, {
535                 .name = "flexpfb",
536                 .pdev = &(struct platform_device) {
537                         .name = "flexpfb",
538                         .id = 0,
539                         .dev = {
540                         .release = fbtft_device_pdev_release,
541                         .platform_data = &(struct fbtft_platform_data) {
542                                 .gpios = (const struct fbtft_gpio []) {
543                                         { "reset", 17 },
544                                         { "dc", 1 },
545                                         { "wr", 0 },
546                                         { "cs", 21 },
547                                         { "db00", 9 },
548                                         { "db01", 11 },
549                                         { "db02", 18 },
550                                         { "db03", 23 },
551                                         { "db04", 24 },
552                                         { "db05", 25 },
553                                         { "db06", 8 },
554                                         { "db07", 7 },
555                                         { "led", 4 },
556                                         {},
557                                 },
558                         },
559                         }
560                 }
561         }, {
562                 .name = "freetronicsoled128",
563                 .spi = &(struct spi_board_info) {
564                         .modalias = "fb_ssd1351",
565                         .max_speed_hz = 20000000,
566                         .mode = SPI_MODE_0,
567                         .platform_data = &(struct fbtft_platform_data) {
568                                 .display = {
569                                         .buswidth = 8,
570                                         .backlight = FBTFT_ONBOARD_BACKLIGHT,
571                                 },
572                                 .bgr = true,
573                                 .gpios = (const struct fbtft_gpio []) {
574                                         { "reset", 24 },
575                                         { "dc", 25 },
576                                         {},
577                                 },
578                         }
579                 }
580         }, {
581                 .name = "hx8353d",
582                 .spi = &(struct spi_board_info) {
583                         .modalias = "fb_hx8353d",
584                         .max_speed_hz = 16000000,
585                         .mode = SPI_MODE_0,
586                         .platform_data = &(struct fbtft_platform_data) {
587                                 .display = {
588                                         .buswidth = 8,
589                                         .backlight = 1,
590                                 },
591                                 .gpios = (const struct fbtft_gpio []) {
592                                         { "reset", 25 },
593                                         { "dc", 24 },
594                                         { "led", 23 },
595                                         {},
596                                 },
597                         }
598                 }
599         }, {
600                 .name = "hy28a",
601                 .spi = &(struct spi_board_info) {
602                         .modalias = "fb_ili9320",
603                         .max_speed_hz = 32000000,
604                         .mode = SPI_MODE_3,
605                         .platform_data = &(struct fbtft_platform_data) {
606                                 .display = {
607                                         .buswidth = 8,
608                                         .backlight = 1,
609                                 },
610                                 .startbyte = 0x70,
611                                 .bgr = true,
612                                 .gpios = (const struct fbtft_gpio []) {
613                                         { "reset", 25 },
614                                         { "led", 18 },
615                                         {},
616                                 },
617                         }
618                 }
619         }, {
620                 .name = "hy28b",
621                 .spi = &(struct spi_board_info) {
622                         .modalias = "fb_ili9325",
623                         .max_speed_hz = 48000000,
624                         .mode = SPI_MODE_3,
625                         .platform_data = &(struct fbtft_platform_data) {
626                                 .display = {
627                                         .buswidth = 8,
628                                         .backlight = 1,
629                                         .init_sequence = hy28b_init_sequence,
630                                 },
631                                 .startbyte = 0x70,
632                                 .bgr = true,
633                                 .fps = 50,
634                                 .gpios = (const struct fbtft_gpio []) {
635                                         { "reset", 25 },
636                                         { "led", 18 },
637                                         {},
638                                 },
639                                 .gamma = HY28B_GAMMA,
640                         }
641                 }
642         }, {
643                 .name = "ili9481",
644                 .spi = &(struct spi_board_info) {
645                         .modalias = "fb_ili9481",
646                         .max_speed_hz = 32000000,
647                         .mode = SPI_MODE_0,
648                         .platform_data = &(struct fbtft_platform_data) {
649                                 .display = {
650                                         .regwidth = 16,
651                                         .buswidth = 8,
652                                         .backlight = 1,
653                                 },
654                                 .bgr = true,
655                                 .gpios = (const struct fbtft_gpio []) {
656                                         { "reset", 25 },
657                                         { "dc", 24 },
658                                         { "led", 22 },
659                                         {},
660                                 },
661                         }
662                 }
663         }, {
664                 .name = "itdb24",
665                 .pdev = &(struct platform_device) {
666                         .name = "fb_s6d1121",
667                         .id = 0,
668                         .dev = {
669                         .release = fbtft_device_pdev_release,
670                         .platform_data = &(struct fbtft_platform_data) {
671                                 .display = {
672                                         .buswidth = 8,
673                                         .backlight = 1,
674                                 },
675                                 .bgr = false,
676                                 .gpios = (const struct fbtft_gpio []) {
677                                         /* Wiring for LCD adapter kit */
678                                         { "reset", 7 },
679                                         { "dc", 0 },    /* rev 2: 2 */
680                                         { "wr", 1 },    /* rev 2: 3 */
681                                         { "cs", 8 },
682                                         { "db00", 17 },
683                                         { "db01", 18 },
684                                         { "db02", 21 }, /* rev 2: 27 */
685                                         { "db03", 22 },
686                                         { "db04", 23 },
687                                         { "db05", 24 },
688                                         { "db06", 25 },
689                                         { "db07", 4 },
690                                         {}
691                                 },
692                         },
693                         }
694                 }
695         }, {
696                 .name = "itdb28",
697                 .pdev = &(struct platform_device) {
698                         .name = "fb_ili9325",
699                         .id = 0,
700                         .dev = {
701                         .release = fbtft_device_pdev_release,
702                         .platform_data = &(struct fbtft_platform_data) {
703                                 .display = {
704                                         .buswidth = 8,
705                                         .backlight = 1,
706                                 },
707                                 .bgr = true,
708                                 .gpios = (const struct fbtft_gpio []) {
709                                         {},
710                                 },
711                         },
712                         }
713                 }
714         }, {
715                 .name = "itdb28_spi",
716                 .spi = &(struct spi_board_info) {
717                         .modalias = "fb_ili9325",
718                         .max_speed_hz = 32000000,
719                         .mode = SPI_MODE_0,
720                         .platform_data = &(struct fbtft_platform_data) {
721                                 .display = {
722                                         .buswidth = 8,
723                                         .backlight = 1,
724                                 },
725                                 .bgr = true,
726                                 .gpios = (const struct fbtft_gpio []) {
727                                         { "reset", 25 },
728                                         { "dc", 24 },
729                                         {},
730                                 },
731                         }
732                 }
733         }, {
734                 .name = "mi0283qt-2",
735                 .spi = &(struct spi_board_info) {
736                         .modalias = "fb_hx8347d",
737                         .max_speed_hz = 32000000,
738                         .mode = SPI_MODE_0,
739                         .platform_data = &(struct fbtft_platform_data) {
740                                 .display = {
741                                         .buswidth = 8,
742                                         .backlight = 1,
743                                 },
744                                 .startbyte = 0x70,
745                                 .bgr = true,
746                                 .gpios = (const struct fbtft_gpio []) {
747                                         { "reset", 25 },
748                                         { "dc", 24 },
749                                         { "led", 18 },
750                                         {},
751                                 },
752                         }
753                 }
754         }, {
755                 .name = "mi0283qt-9a",
756                 .spi = &(struct spi_board_info) {
757                         .modalias = "fb_ili9341",
758                         .max_speed_hz = 32000000,
759                         .mode = SPI_MODE_0,
760                         .platform_data = &(struct fbtft_platform_data) {
761                                 .display = {
762                                         .buswidth = 9,
763                                         .backlight = 1,
764                                 },
765                                 .bgr = true,
766                                 .gpios = (const struct fbtft_gpio []) {
767                                         { "reset", 25 },
768                                         { "led", 18 },
769                                         {},
770                                 },
771                         }
772                 }
773         }, {
774                 .name = "mi0283qt-v2",
775                 .spi = &(struct spi_board_info) {
776                         .modalias = "fb_watterott",
777                         .max_speed_hz = 4000000,
778                         .mode = SPI_MODE_3,
779                         .platform_data = &(struct fbtft_platform_data) {
780                                 .gpios = (const struct fbtft_gpio []) {
781                                         { "reset", 25 },
782                                         {},
783                                 },
784                         }
785                 }
786         }, {
787                 .name = "nokia3310",
788                 .spi = &(struct spi_board_info) {
789                         .modalias = "fb_pcd8544",
790                         .max_speed_hz = 400000,
791                         .mode = SPI_MODE_0,
792                         .platform_data = &(struct fbtft_platform_data) {
793                                 .display = {
794                                         .buswidth = 8,
795                                 },
796                                 .gpios = (const struct fbtft_gpio []) {
797                                         { "reset", 25 },
798                                         { "dc", 24 },
799                                         { "led", 23 },
800                                         {},
801                                 },
802                         }
803                 }
804         }, {
805                 .name = "nokia3310a",
806                 .spi = &(struct spi_board_info) {
807                         .modalias = "fb_tls8204",
808                         .max_speed_hz = 1000000,
809                         .mode = SPI_MODE_0,
810                         .platform_data = &(struct fbtft_platform_data) {
811                                 .display = {
812                                         .buswidth = 8,
813                                 },
814                                 .gpios = (const struct fbtft_gpio []) {
815                                         { "reset", 25 },
816                                         { "dc", 24 },
817                                         { "led", 23 },
818                                         {},
819                                 },
820                         }
821                 }
822         }, {
823                 .name = "nokia5110",
824                 .spi = &(struct spi_board_info) {
825                         .modalias = "fb_ili9163",
826                         .max_speed_hz = 12000000,
827                         .mode = SPI_MODE_0,
828                         .platform_data = &(struct fbtft_platform_data) {
829                                 .display = {
830                                         .buswidth = 8,
831                                         .backlight = 1,
832                                 },
833                                 .bgr = true,
834                                 .gpios = (const struct fbtft_gpio []) {
835                                         {},
836                                 },
837                         }
838                 }
839         }, {
840                 .name = "piscreen",
841                 .spi = &(struct spi_board_info) {
842                         .modalias = "fb_ili9486",
843                         .max_speed_hz = 32000000,
844                         .mode = SPI_MODE_0,
845                         .platform_data = &(struct fbtft_platform_data) {
846                                 .display = {
847                                         .regwidth = 16,
848                                         .buswidth = 8,
849                                         .backlight = 1,
850                                 },
851                                 .bgr = true,
852                                 .gpios = (const struct fbtft_gpio []) {
853                                         { "reset", 25 },
854                                         { "dc", 24 },
855                                         { "led", 22 },
856                                         {},
857                                 },
858                         }
859                 }
860         }, {
861                 .name = "pitft",
862                 .spi = &(struct spi_board_info) {
863                         .modalias = "fb_ili9340",
864                         .max_speed_hz = 32000000,
865                         .mode = SPI_MODE_0,
866                         .chip_select = 0,
867                         .platform_data = &(struct fbtft_platform_data) {
868                                 .display = {
869                                         .buswidth = 8,
870                                         .backlight = 1,
871                                         .init_sequence = pitft_init_sequence,
872                                 },
873                                 .bgr = true,
874                                 .gpios = (const struct fbtft_gpio []) {
875                                         { "dc", 25 },
876                                         {},
877                                 },
878                         }
879                 }
880         }, {
881                 .name = "pioled",
882                 .spi = &(struct spi_board_info) {
883                         .modalias = "fb_ssd1351",
884                         .max_speed_hz = 20000000,
885                         .mode = SPI_MODE_0,
886                         .platform_data = &(struct fbtft_platform_data) {
887                                 .display = {
888                                         .buswidth = 8,
889                                 },
890                                 .bgr = true,
891                                 .gpios = (const struct fbtft_gpio []) {
892                                         { "reset", 24 },
893                                         { "dc", 25 },
894                                         {},
895                                 },
896                                 .gamma = PIOLED_GAMMA
897                         }
898                 }
899         }, {
900                 .name = "rpi-display",
901                 .spi = &(struct spi_board_info) {
902                         .modalias = "fb_ili9341",
903                         .max_speed_hz = 32000000,
904                         .mode = SPI_MODE_0,
905                         .platform_data = &(struct fbtft_platform_data) {
906                                 .display = {
907                                         .buswidth = 8,
908                                         .backlight = 1,
909                                 },
910                                 .bgr = true,
911                                 .gpios = (const struct fbtft_gpio []) {
912                                         { "reset", 23 },
913                                         { "dc", 24 },
914                                         { "led", 18 },
915                                         {},
916                                 },
917                         }
918                 }
919         }, {
920                 .name = "s6d02a1",
921                 .spi = &(struct spi_board_info) {
922                         .modalias = "fb_s6d02a1",
923                         .max_speed_hz = 32000000,
924                         .mode = SPI_MODE_0,
925                         .platform_data = &(struct fbtft_platform_data) {
926                                 .display = {
927                                         .buswidth = 8,
928                                         .backlight = 1,
929                                 },
930                                 .bgr = true,
931                                 .gpios = (const struct fbtft_gpio []) {
932                                         { "reset", 25 },
933                                         { "dc", 24 },
934                                         { "led", 23 },
935                                         {},
936                                 },
937                         }
938                 }
939         }, {
940                 .name = "sainsmart18",
941                 .spi = &(struct spi_board_info) {
942                         .modalias = "fb_st7735r",
943                         .max_speed_hz = 32000000,
944                         .mode = SPI_MODE_0,
945                         .platform_data = &(struct fbtft_platform_data) {
946                                 .display = {
947                                         .buswidth = 8,
948                                 },
949                                 .gpios = (const struct fbtft_gpio []) {
950                                         { "reset", 25 },
951                                         { "dc", 24 },
952                                         {},
953                                 },
954                         }
955                 }
956         }, {
957                 .name = "sainsmart32",
958                 .pdev = &(struct platform_device) {
959                         .name = "fb_ssd1289",
960                         .id = 0,
961                         .dev = {
962                         .release = fbtft_device_pdev_release,
963                         .platform_data = &(struct fbtft_platform_data) {
964                                 .display = {
965                                         .buswidth = 16,
966                                         .txbuflen = -2, /* disable buffer */
967                                         .backlight = 1,
968                                         .fbtftops.write = write_gpio16_wr_slow,
969                                 },
970                                 .bgr = true,
971                                 .gpios = (const struct fbtft_gpio []) {
972                                         {},
973                                 },
974                         },
975                 },
976                 }
977         }, {
978                 .name = "sainsmart32_fast",
979                 .pdev = &(struct platform_device) {
980                         .name = "fb_ssd1289",
981                         .id = 0,
982                         .dev = {
983                         .release = fbtft_device_pdev_release,
984                         .platform_data = &(struct fbtft_platform_data) {
985                                 .display = {
986                                         .buswidth = 16,
987                                         .txbuflen = -2, /* disable buffer */
988                                         .backlight = 1,
989                                 },
990                                 .bgr = true,
991                                 .gpios = (const struct fbtft_gpio []) {
992                                         {},
993                                 },
994                         },
995                 },
996                 }
997         }, {
998                 .name = "sainsmart32_latched",
999                 .pdev = &(struct platform_device) {
1000                         .name = "fb_ssd1289",
1001                         .id = 0,
1002                         .dev = {
1003                         .release = fbtft_device_pdev_release,
1004                         .platform_data = &(struct fbtft_platform_data) {
1005                                 .display = {
1006                                         .buswidth = 16,
1007                                         .txbuflen = -2, /* disable buffer */
1008                                         .backlight = 1,
1009                                         .fbtftops.write =
1010                                                 fbtft_write_gpio16_wr_latched,
1011                                 },
1012                                 .bgr = true,
1013                                 .gpios = (const struct fbtft_gpio []) {
1014                                         {},
1015                                 },
1016                         },
1017                 },
1018                 }
1019         }, {
1020                 .name = "sainsmart32_spi",
1021                 .spi = &(struct spi_board_info) {
1022                         .modalias = "fb_ssd1289",
1023                         .max_speed_hz = 16000000,
1024                         .mode = SPI_MODE_0,
1025                         .platform_data = &(struct fbtft_platform_data) {
1026                                 .display = {
1027                                         .buswidth = 8,
1028                                         .backlight = 1,
1029                                 },
1030                                 .bgr = true,
1031                                 .gpios = (const struct fbtft_gpio []) {
1032                                         { "reset", 25 },
1033                                         { "dc", 24 },
1034                                         {},
1035                                 },
1036                         }
1037                 }
1038         }, {
1039                 .name = "spidev",
1040                 .spi = &(struct spi_board_info) {
1041                         .modalias = "spidev",
1042                         .max_speed_hz = 500000,
1043                         .bus_num = 0,
1044                         .chip_select = 0,
1045                         .mode = SPI_MODE_0,
1046                         .platform_data = &(struct fbtft_platform_data) {
1047                                 .gpios = (const struct fbtft_gpio []) {
1048                                         {},
1049                                 },
1050                         }
1051                 }
1052         }, {
1053                 .name = "ssd1331",
1054                 .spi = &(struct spi_board_info) {
1055                         .modalias = "fb_ssd1331",
1056                         .max_speed_hz = 20000000,
1057                         .mode = SPI_MODE_3,
1058                         .platform_data = &(struct fbtft_platform_data) {
1059                                 .display = {
1060                                         .buswidth = 8,
1061                                 },
1062                                 .gpios = (const struct fbtft_gpio []) {
1063                                         { "reset", 24 },
1064                                         { "dc", 25 },
1065                                         {},
1066                                 },
1067                         }
1068                 }
1069         }, {
1070                 .name = "tinylcd35",
1071                 .spi = &(struct spi_board_info) {
1072                         .modalias = "fb_tinylcd",
1073                         .max_speed_hz = 32000000,
1074                         .mode = SPI_MODE_0,
1075                         .platform_data = &(struct fbtft_platform_data) {
1076                                 .display = {
1077                                         .buswidth = 8,
1078                                         .backlight = 1,
1079                                 },
1080                                 .bgr = true,
1081                                 .gpios = (const struct fbtft_gpio []) {
1082                                         { "reset", 25 },
1083                                         { "dc", 24 },
1084                                         { "led", 18 },
1085                                         {},
1086                                 },
1087                         }
1088                 }
1089         }, {
1090                 .name = "tm022hdh26",
1091                 .spi = &(struct spi_board_info) {
1092                         .modalias = "fb_ili9341",
1093                         .max_speed_hz = 32000000,
1094                         .mode = SPI_MODE_0,
1095                         .platform_data = &(struct fbtft_platform_data) {
1096                                 .display = {
1097                                         .buswidth = 8,
1098                                         .backlight = 1,
1099                                 },
1100                                 .bgr = true,
1101                                 .gpios = (const struct fbtft_gpio []) {
1102                                         { "reset", 25 },
1103                                         { "dc", 24 },
1104                                         { "led", 18 },
1105                                         {},
1106                                 },
1107                         }
1108                 }
1109         }, {
1110                 .name = "tontec35_9481", /* boards before 02 July 2014 */
1111                 .spi = &(struct spi_board_info) {
1112                         .modalias = "fb_ili9481",
1113                         .max_speed_hz = 128000000,
1114                         .mode = SPI_MODE_3,
1115                         .platform_data = &(struct fbtft_platform_data) {
1116                                 .display = {
1117                                         .buswidth = 8,
1118                                         .backlight = 1,
1119                                 },
1120                                 .bgr = true,
1121                                 .gpios = (const struct fbtft_gpio []) {
1122                                         { "reset", 15 },
1123                                         { "dc", 25 },
1124                                         { "led_", 18 },
1125                                         {},
1126                                 },
1127                         }
1128                 }
1129         }, {
1130                 .name = "tontec35_9486", /* boards after 02 July 2014 */
1131                 .spi = &(struct spi_board_info) {
1132                         .modalias = "fb_ili9486",
1133                         .max_speed_hz = 128000000,
1134                         .mode = SPI_MODE_3,
1135                         .platform_data = &(struct fbtft_platform_data) {
1136                                 .display = {
1137                                         .buswidth = 8,
1138                                         .backlight = 1,
1139                                 },
1140                                 .bgr = true,
1141                                 .gpios = (const struct fbtft_gpio []) {
1142                                         { "reset", 15 },
1143                                         { "dc", 25 },
1144                                         { "led_", 18 },
1145                                         {},
1146                                 },
1147                         }
1148                 }
1149         }, {
1150                 .name = "upd161704",
1151                 .spi = &(struct spi_board_info) {
1152                         .modalias = "fb_upd161704",
1153                         .max_speed_hz = 32000000,
1154                         .mode = SPI_MODE_0,
1155                         .platform_data = &(struct fbtft_platform_data) {
1156                                 .display = {
1157                                         .buswidth = 8,
1158                                 },
1159                                 .gpios = (const struct fbtft_gpio []) {
1160                                         { "reset", 24 },
1161                                         { "dc", 25 },
1162                                         {},
1163                                 },
1164                         }
1165                 }
1166         }, {
1167                 .name = "waveshare32b",
1168                 .spi = &(struct spi_board_info) {
1169                         .modalias = "fb_ili9340",
1170                         .max_speed_hz = 48000000,
1171                         .mode = SPI_MODE_0,
1172                         .platform_data = &(struct fbtft_platform_data) {
1173                                 .display = {
1174                                         .buswidth = 8,
1175                                         .backlight = 1,
1176                                         .init_sequence =
1177                                                 waveshare32b_init_sequence,
1178                                 },
1179                                 .bgr = true,
1180                                 .gpios = (const struct fbtft_gpio []) {
1181                                         { "reset", 27 },
1182                                         { "dc", 22 },
1183                                         {},
1184                                 },
1185                         }
1186                 }
1187         }, {
1188                 .name = "waveshare22",
1189                 .spi = &(struct spi_board_info) {
1190                         .modalias = "fb_bd663474",
1191                         .max_speed_hz = 32000000,
1192                         .mode = SPI_MODE_3,
1193                         .platform_data = &(struct fbtft_platform_data) {
1194                                 .display = {
1195                                         .buswidth = 8,
1196                                 },
1197                                 .gpios = (const struct fbtft_gpio []) {
1198                                         { "reset", 24 },
1199                                         { "dc", 25 },
1200                                         {},
1201                                 },
1202                         }
1203                 }
1204         }, {
1205                 /* This should be the last item.
1206                  * Used with the custom argument
1207                  */
1208                 .name = "",
1209                 .spi = &(struct spi_board_info) {
1210                         .modalias = "",
1211                         .max_speed_hz = 0,
1212                         .mode = SPI_MODE_0,
1213                         .platform_data = &(struct fbtft_platform_data) {
1214                                 .gpios = (const struct fbtft_gpio []) {
1215                                         {},
1216                                 },
1217                         }
1218                 },
1219                 .pdev = &(struct platform_device) {
1220                         .name = "",
1221                         .id = 0,
1222                         .dev = {
1223                                 .release = fbtft_device_pdev_release,
1224                                 .platform_data = &(struct fbtft_platform_data) {
1225                                         .gpios = (const struct fbtft_gpio []) {
1226                                                 {},
1227                                         },
1228                                 },
1229                         },
1230                 },
1231         }
1232 };
1233
1234 static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len)
1235 {
1236         u16 data;
1237         int i;
1238 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
1239         static u16 prev_data;
1240 #endif
1241
1242         fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
1243                           "%s(len=%d): ", __func__, len);
1244
1245         while (len) {
1246                 data = *(u16 *)buf;
1247
1248                 /* Start writing by pulling down /WR */
1249                 gpio_set_value(par->gpio.wr, 0);
1250
1251                 /* Set data */
1252 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
1253                 if (data == prev_data) {
1254                         gpio_set_value(par->gpio.wr, 0); /* used as delay */
1255                 } else {
1256                         for (i = 0; i < 16; i++) {
1257                                 if ((data & 1) != (prev_data & 1))
1258                                         gpio_set_value(par->gpio.db[i],
1259                                                        data & 1);
1260                                 data >>= 1;
1261                                 prev_data >>= 1;
1262                         }
1263                 }
1264 #else
1265                 for (i = 0; i < 16; i++) {
1266                         gpio_set_value(par->gpio.db[i], data & 1);
1267                         data >>= 1;
1268                 }
1269 #endif
1270
1271                 /* Pullup /WR */
1272                 gpio_set_value(par->gpio.wr, 1);
1273
1274 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
1275                 prev_data = *(u16 *)buf;
1276 #endif
1277                 buf += 2;
1278                 len -= 2;
1279         }
1280
1281         return 0;
1282 }
1283
1284 static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par,
1285                                               int xs, int ys, int xe, int ye)
1286 {
1287         write_reg(par, 0x2A, 0, xs + 2, 0, xe + 2);
1288         write_reg(par, 0x2B, 0, ys + 1, 0, ye + 1);
1289         write_reg(par, 0x2C);
1290 }
1291
1292 /* used if gpios parameter is present */
1293 static struct fbtft_gpio fbtft_device_param_gpios[MAX_GPIOS + 1] = { };
1294
1295 static void fbtft_device_pdev_release(struct device *dev)
1296 {
1297 /* Needed to silence this message:
1298  * Device 'xxx' does not have a release() function,
1299  * it is broken and must be fixed
1300  */
1301 }
1302
1303 static int spi_device_found(struct device *dev, void *data)
1304 {
1305         struct spi_device *spi = to_spi_device(dev);
1306
1307         dev_info(dev, "%s %s %dkHz %d bits mode=0x%02X\n", spi->modalias,
1308                  dev_name(dev), spi->max_speed_hz / 1000, spi->bits_per_word,
1309                  spi->mode);
1310
1311         return 0;
1312 }
1313
1314 static void pr_spi_devices(void)
1315 {
1316         pr_debug("SPI devices registered:\n");
1317         bus_for_each_dev(&spi_bus_type, NULL, NULL, spi_device_found);
1318 }
1319
1320 static int p_device_found(struct device *dev, void *data)
1321 {
1322         struct platform_device
1323         *pdev = to_platform_device(dev);
1324
1325         if (strstr(pdev->name, "fb"))
1326                 dev_info(dev, "%s id=%d pdata? %s\n", pdev->name, pdev->id,
1327                          pdev->dev.platform_data ? "yes" : "no");
1328
1329         return 0;
1330 }
1331
1332 static void pr_p_devices(void)
1333 {
1334         pr_debug("'fb' Platform devices registered:\n");
1335         bus_for_each_dev(&platform_bus_type, NULL, NULL, p_device_found);
1336 }
1337
1338 #ifdef MODULE
1339 static void fbtft_device_spi_delete(struct spi_master *master, unsigned int cs)
1340 {
1341         struct device *dev;
1342         char str[32];
1343
1344         snprintf(str, sizeof(str), "%s.%u", dev_name(&master->dev), cs);
1345
1346         dev = bus_find_device_by_name(&spi_bus_type, NULL, str);
1347         if (dev) {
1348                 if (verbose)
1349                         dev_info(dev, "Deleting %s\n", str);
1350                 device_del(dev);
1351         }
1352 }
1353
1354 static int fbtft_device_spi_device_register(struct spi_board_info *spi)
1355 {
1356         struct spi_master *master;
1357
1358         master = spi_busnum_to_master(spi->bus_num);
1359         if (!master) {
1360                 pr_err("spi_busnum_to_master(%d) returned NULL\n",
1361                        spi->bus_num);
1362                 return -EINVAL;
1363         }
1364         /* make sure it's available */
1365         fbtft_device_spi_delete(master, spi->chip_select);
1366         spi_device = spi_new_device(master, spi);
1367         put_device(&master->dev);
1368         if (!spi_device) {
1369                 dev_err(&master->dev, "spi_new_device() returned NULL\n");
1370                 return -EPERM;
1371         }
1372         return 0;
1373 }
1374 #else
1375 static int fbtft_device_spi_device_register(struct spi_board_info *spi)
1376 {
1377         return spi_register_board_info(spi, 1);
1378 }
1379 #endif
1380
1381 static int __init fbtft_device_init(void)
1382 {
1383         struct spi_board_info *spi = NULL;
1384         struct fbtft_platform_data *pdata;
1385         const struct fbtft_gpio *gpio = NULL;
1386         char *p_gpio, *p_name, *p_num;
1387         bool found = false;
1388         int i = 0;
1389         long val;
1390         int ret = 0;
1391
1392         if (!name) {
1393 #ifdef MODULE
1394                 pr_err("missing module parameter: 'name'\n");
1395                 return -EINVAL;
1396 #else
1397                 return 0;
1398 #endif
1399         }
1400
1401         if (init_num > FBTFT_MAX_INIT_SEQUENCE) {
1402                 pr_err("init parameter: exceeded max array size: %d\n",
1403                        FBTFT_MAX_INIT_SEQUENCE);
1404                 return -EINVAL;
1405         }
1406
1407         /* parse module parameter: gpios */
1408         while ((p_gpio = strsep(&gpios, ","))) {
1409                 if (!strchr(p_gpio, ':')) {
1410                         pr_err("error: missing ':' in gpios parameter: %s\n",
1411                                p_gpio);
1412                         return -EINVAL;
1413                 }
1414                 p_num = p_gpio;
1415                 p_name = strsep(&p_num, ":");
1416                 if (!p_name || !p_num) {
1417                         pr_err("something bad happened parsing gpios parameter: %s\n",
1418                                p_gpio);
1419                         return -EINVAL;
1420                 }
1421                 ret = kstrtol(p_num, 10, &val);
1422                 if (ret) {
1423                         pr_err("could not parse number in gpios parameter: %s:%s\n",
1424                                p_name, p_num);
1425                         return -EINVAL;
1426                 }
1427                 strncpy(fbtft_device_param_gpios[i].name, p_name,
1428                         FBTFT_GPIO_NAME_SIZE - 1);
1429                 fbtft_device_param_gpios[i++].gpio = (int)val;
1430                 if (i == MAX_GPIOS) {
1431                         pr_err("gpios parameter: exceeded max array size: %d\n",
1432                                MAX_GPIOS);
1433                         return -EINVAL;
1434                 }
1435         }
1436         if (fbtft_device_param_gpios[0].name[0])
1437                 gpio = fbtft_device_param_gpios;
1438
1439         if (verbose > 2) {
1440                 pr_spi_devices(); /* print list of registered SPI devices */
1441                 pr_p_devices(); /* print list of 'fb' platform devices */
1442         }
1443
1444         pr_debug("name='%s', busnum=%d, cs=%d\n", name, busnum, cs);
1445
1446         if (rotate > 0 && rotate < 4) {
1447                 rotate = (4 - rotate) * 90;
1448                 pr_warn("argument 'rotate' should be an angle. Values 1-3 is deprecated. Setting it to %d.\n",
1449                         rotate);
1450         }
1451         if (rotate != 0 && rotate != 90 && rotate != 180 && rotate != 270) {
1452                 pr_warn("argument 'rotate' illegal value: %d. Setting it to 0.\n",
1453                         rotate);
1454                 rotate = 0;
1455         }
1456
1457         /* name=list lists all supported displays */
1458         if (strncmp(name, "list", FBTFT_GPIO_NAME_SIZE) == 0) {
1459                 pr_info("Supported displays:\n");
1460
1461                 for (i = 0; i < ARRAY_SIZE(displays); i++)
1462                         pr_info("%s\n", displays[i].name);
1463                 return -ECANCELED;
1464         }
1465
1466         if (custom) {
1467                 i = ARRAY_SIZE(displays) - 1;
1468                 displays[i].name = name;
1469                 if (speed == 0) {
1470                         displays[i].pdev->name = name;
1471                         displays[i].spi = NULL;
1472                 } else {
1473                         size_t len;
1474
1475                         len = strlcpy(displays[i].spi->modalias, name,
1476                                       SPI_NAME_SIZE);
1477                         if (len >= SPI_NAME_SIZE)
1478                                 pr_warn("modalias (name) truncated to: %s\n",
1479                                         displays[i].spi->modalias);
1480                         displays[i].pdev = NULL;
1481                 }
1482         }
1483
1484         for (i = 0; i < ARRAY_SIZE(displays); i++) {
1485                 if (strncmp(name, displays[i].name, SPI_NAME_SIZE) == 0) {
1486                         if (displays[i].spi) {
1487                                 spi = displays[i].spi;
1488                                 spi->chip_select = cs;
1489                                 spi->bus_num = busnum;
1490                                 if (speed)
1491                                         spi->max_speed_hz = speed;
1492                                 if (mode != -1)
1493                                         spi->mode = mode;
1494                                 pdata = (void *)spi->platform_data;
1495                         } else if (displays[i].pdev) {
1496                                 p_device = displays[i].pdev;
1497                                 pdata = p_device->dev.platform_data;
1498                         } else {
1499                                 pr_err("broken displays array\n");
1500                                 return -EINVAL;
1501                         }
1502
1503                         pdata->rotate = rotate;
1504                         if (bgr == 0)
1505                                 pdata->bgr = false;
1506                         else if (bgr == 1)
1507                                 pdata->bgr = true;
1508                         if (startbyte)
1509                                 pdata->startbyte = startbyte;
1510                         if (gamma)
1511                                 pdata->gamma = gamma;
1512                         pdata->display.debug = debug;
1513                         if (fps)
1514                                 pdata->fps = fps;
1515                         if (txbuflen)
1516                                 pdata->txbuflen = txbuflen;
1517                         if (init_num)
1518                                 pdata->display.init_sequence = init;
1519                         if (gpio)
1520                                 pdata->gpios = gpio;
1521                         if (custom) {
1522                                 pdata->display.width = width;
1523                                 pdata->display.height = height;
1524                                 pdata->display.buswidth = buswidth;
1525                                 pdata->display.backlight = 1;
1526                         }
1527
1528                         if (displays[i].spi) {
1529                                 ret = fbtft_device_spi_device_register(spi);
1530                                 if (ret) {
1531                                         pr_err("failed to register SPI device\n");
1532                                         return ret;
1533                                 }
1534                         } else {
1535                                 ret = platform_device_register(p_device);
1536                                 if (ret < 0) {
1537                                         pr_err("platform_device_register() returned %d\n",
1538                                                ret);
1539                                         return ret;
1540                                 }
1541                         }
1542                         found = true;
1543                         break;
1544                 }
1545         }
1546
1547         if (!found) {
1548                 pr_err("display not supported: '%s'\n", name);
1549                 return -EINVAL;
1550         }
1551
1552         if (verbose && pdata && pdata->gpios) {
1553                 gpio = pdata->gpios;
1554                 pr_info("GPIOS used by '%s':\n", name);
1555                 found = false;
1556                 while (verbose && gpio->name[0]) {
1557                         pr_info("'%s' = GPIO%d\n", gpio->name, gpio->gpio);
1558                         gpio++;
1559                         found = true;
1560                 }
1561                 if (!found)
1562                         pr_info("(none)\n");
1563         }
1564
1565         if (spi_device && (verbose > 1))
1566                 pr_spi_devices();
1567         if (p_device && (verbose > 1))
1568                 pr_p_devices();
1569
1570         return 0;
1571 }
1572
1573 static void __exit fbtft_device_exit(void)
1574 {
1575         if (spi_device) {
1576                 device_del(&spi_device->dev);
1577                 kfree(spi_device);
1578         }
1579
1580         if (p_device)
1581                 platform_device_unregister(p_device);
1582 }
1583
1584 arch_initcall(fbtft_device_init);
1585 module_exit(fbtft_device_exit);
1586
1587 MODULE_DESCRIPTION("Add a FBTFT device.");
1588 MODULE_AUTHOR("Noralf Tronnes");
1589 MODULE_LICENSE("GPL");