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
write_gpio16_wr_slow(struct fbtft_par * par,void * buf,size_t len)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
adafruit18_green_tab_set_addr_win(struct fbtft_par * par,int xs,int ys,int xe,int ye)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
fbtft_device_pdev_release(struct device * dev)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
spi_device_found(struct device * dev,void * data)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
pr_spi_devices(void)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
p_device_found(struct device * dev,void * data)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
pr_p_devices(void)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
fbtft_device_spi_delete(struct spi_master * master,unsigned cs)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
fbtft_device_spi_device_register(struct spi_board_info * spi)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
fbtft_device_spi_device_register(struct spi_board_info * spi)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
fbtft_device_init(void)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
fbtft_device_exit(void)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");
1571