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