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