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