3 * Copyright (C) 2013, Noralf Tronnes
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.
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.
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/gpio.h>
20 #include <linux/spi/spi.h>
24 #define DRVNAME "fbtft_device"
28 static struct spi_device *spi_device;
29 static struct platform_device *p_device;
32 module_param(name, charp, 0);
33 MODULE_PARM_DESC(name, "Devicename (required). name=list => list all supported devices.");
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");
40 static unsigned busnum;
41 module_param(busnum, uint, 0);
42 MODULE_PARM_DESC(busnum, "SPI bus number (default=0)");
45 module_param(cs, uint, 0);
46 MODULE_PARM_DESC(cs, "SPI chip select (default=0)");
48 static unsigned speed;
49 module_param(speed, uint, 0);
50 MODULE_PARM_DESC(speed, "SPI speed (override device default)");
53 module_param(mode, int, 0);
54 MODULE_PARM_DESC(mode, "SPI mode (override device default)");
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)");
62 module_param(fps, uint, 0);
63 MODULE_PARM_DESC(fps, "Frames per second (override driver default)");
66 module_param(gamma, charp, 0);
67 MODULE_PARM_DESC(gamma,
68 "String representation of Gamma Curve(s). Driver specific.");
71 module_param(txbuflen, int, 0);
72 MODULE_PARM_DESC(txbuflen, "txbuflen (override driver default)");
75 module_param(bgr, int, 0);
77 "BGR bit (supported by some drivers).");
79 static unsigned startbyte;
80 module_param(startbyte, uint, 0);
81 MODULE_PARM_DESC(startbyte, "Sets the Start byte used by some SPI displays.");
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");
87 static unsigned width;
88 module_param(width, uint, 0);
89 MODULE_PARM_DESC(width, "Display width, used with the custom argument");
91 static unsigned height;
92 module_param(height, uint, 0);
93 MODULE_PARM_DESC(height, "Display height, used with the custom argument");
95 static unsigned buswidth = 8;
96 module_param(buswidth, uint, 0);
97 MODULE_PARM_DESC(buswidth, "Display bus width, used with the custom argument");
99 static int init[FBTFT_MAX_INIT_SEQUENCE];
101 module_param_array(init, int, &init_num, 0);
102 MODULE_PARM_DESC(init, "Init sequence, used with the custom argument");
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)");
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)");
114 struct fbtft_device_display {
116 struct spi_board_info *spi;
117 struct platform_device *pdev;
120 static void fbtft_device_pdev_release(struct device *dev);
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);
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"
130 static int hy28b_init_sequence[] = {
131 -1, 0x00e7, 0x0010, -1, 0x0000, 0x0001,
132 -1, 0x0001, 0x0100, -1, 0x0002, 0x0700,
133 -1, 0x0003, 0x1030, -1, 0x0004, 0x0000,
134 -1, 0x0008, 0x0207, -1, 0x0009, 0x0000,
135 -1, 0x000a, 0x0000, -1, 0x000c, 0x0001,
136 -1, 0x000d, 0x0000, -1, 0x000f, 0x0000,
137 -1, 0x0010, 0x0000, -1, 0x0011, 0x0007,
138 -1, 0x0012, 0x0000, -1, 0x0013, 0x0000,
139 -2, 50, -1, 0x0010, 0x1590, -1, 0x0011,
140 0x0227, -2, 50, -1, 0x0012, 0x009c, -2, 50,
141 -1, 0x0013, 0x1900, -1, 0x0029, 0x0023,
142 -1, 0x002b, 0x000e, -2, 50,
143 -1, 0x0020, 0x0000, -1, 0x0021, 0x0000,
144 -2, 50, -1, 0x0050, 0x0000,
145 -1, 0x0051, 0x00ef, -1, 0x0052, 0x0000,
146 -1, 0x0053, 0x013f, -1, 0x0060, 0xa700,
147 -1, 0x0061, 0x0001, -1, 0x006a, 0x0000,
148 -1, 0x0080, 0x0000, -1, 0x0081, 0x0000,
149 -1, 0x0082, 0x0000, -1, 0x0083, 0x0000,
150 -1, 0x0084, 0x0000, -1, 0x0085, 0x0000,
151 -1, 0x0090, 0x0010, -1, 0x0092, 0x0000,
152 -1, 0x0093, 0x0003, -1, 0x0095, 0x0110,
153 -1, 0x0097, 0x0000, -1, 0x0098, 0x0000,
154 -1, 0x0007, 0x0133, -1, 0x0020, 0x0000,
155 -1, 0x0021, 0x0000, -2, 100, -3 };
157 #define HY28B_GAMMA \
158 "04 1F 4 7 7 0 7 7 6 0\n" \
159 "0F 00 1 7 4 0 0 0 6 7"
161 static int pitft_init_sequence[] = {
162 -1, 0x01, -2, 5, -1, 0x28, -1, 0xEF,
163 0x03, 0x80, 0x02, -1, 0xCF, 0x00, 0xC1, 0x30,
164 -1, 0xED, 0x64, 0x03, 0x12, 0x81,
165 -1, 0xE8, 0x85, 0x00, 0x78,
166 -1, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
167 -1, 0xF7, 0x20, -1, 0xEA, 0x00, 0x00,
168 -1, 0xC0, 0x23, -1, 0xC1, 0x10, -1, 0xC5,
169 0x3e, 0x28, -1, 0xC7, 0x86, -1, 0x3A, 0x55,
170 -1, 0xB1, 0x00, 0x18, -1, 0xB6, 0x08, 0x82,
171 0x27, -1, 0xF2, 0x00, -1, 0x26, 0x01,
172 -1, 0xE0, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08,
173 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03,
174 0x0E, 0x09, 0x00, -1, 0xE1, 0x00, 0x0E, 0x14,
175 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48,
176 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, -1,
177 0x11, -2, 100, -1, 0x29, -2, 20, -3 };
179 static int waveshare32b_init_sequence[] = {
180 -1, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
181 -1, 0xCF, 0x00, 0xC1, 0x30,
182 -1, 0xE8, 0x85, 0x00, 0x78, -1, 0xEA, 0x00,
183 0x00, -1, 0xED, 0x64, 0x03, 0x12, 0x81,
184 -1, 0xF7, 0x20, -1, 0xC0, 0x23, -1, 0xC1,
185 0x10, -1, 0xC5, 0x3e, 0x28, -1, 0xC7, 0x86,
186 -1, 0x36, 0x28, -1, 0x3A, 0x55, -1, 0xB1, 0x00,
187 0x18, -1, 0xB6, 0x08, 0x82, 0x27,
188 -1, 0xF2, 0x00, -1, 0x26, 0x01,
189 -1, 0xE0, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E,
190 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
191 -1, 0xE1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31,
192 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
193 -1, 0x11, -2, 120, -1, 0x29, -1, 0x2c, -3 };
195 /* Supported displays in alphabetical order */
196 static struct fbtft_device_display displays[] = {
198 .name = "adafruit18",
199 .spi = &(struct spi_board_info) {
200 .modalias = "fb_st7735r",
201 .max_speed_hz = 32000000,
203 .platform_data = &(struct fbtft_platform_data) {
208 .gpios = (const struct fbtft_gpio []) {
214 .gamma = ADAFRUIT18_GAMMA,
218 .name = "adafruit18_green",
219 .spi = &(struct spi_board_info) {
220 .modalias = "fb_st7735r",
221 .max_speed_hz = 4000000,
223 .platform_data = &(struct fbtft_platform_data) {
227 .fbtftops.set_addr_win =
228 adafruit18_green_tab_set_addr_win,
231 .gpios = (const struct fbtft_gpio []) {
237 .gamma = ADAFRUIT18_GAMMA,
241 .name = "adafruit22",
242 .spi = &(struct spi_board_info) {
243 .modalias = "fb_hx8340bn",
244 .max_speed_hz = 32000000,
246 .platform_data = &(struct fbtft_platform_data) {
252 .gpios = (const struct fbtft_gpio []) {
260 .name = "adafruit22a",
261 .spi = &(struct spi_board_info) {
262 .modalias = "fb_ili9340",
263 .max_speed_hz = 32000000,
265 .platform_data = &(struct fbtft_platform_data) {
271 .gpios = (const struct fbtft_gpio []) {
280 .name = "adafruit28",
281 .spi = &(struct spi_board_info) {
282 .modalias = "fb_ili9341",
283 .max_speed_hz = 32000000,
285 .platform_data = &(struct fbtft_platform_data) {
291 .gpios = (const struct fbtft_gpio []) {
300 .name = "adafruit13m",
301 .spi = &(struct spi_board_info) {
302 .modalias = "fb_ssd1306",
303 .max_speed_hz = 16000000,
305 .platform_data = &(struct fbtft_platform_data) {
309 .gpios = (const struct fbtft_gpio []) {
317 .name = "agm1264k-fl",
318 .pdev = &(struct platform_device) {
319 .name = "fb_agm1264k-fl",
322 .release = fbtft_device_pdev_release,
323 .platform_data = &(struct fbtft_platform_data) {
326 .backlight = FBTFT_ONBOARD_BACKLIGHT,
328 .gpios = (const struct fbtft_gpio []) {
336 .spi = &(struct spi_board_info) {
337 .modalias = "fb_uc1701",
338 .max_speed_hz = 8000000,
340 .platform_data = &(struct fbtft_platform_data) {
345 .gpios = (const struct fbtft_gpio []) {
353 .name = "er_tftm050_2",
354 .spi = &(struct spi_board_info) {
355 .modalias = "fb_ra8875",
356 .max_speed_hz = 5000000,
358 .platform_data = &(struct fbtft_platform_data) {
366 .gpios = (const struct fbtft_gpio []) {
374 .name = "er_tftm070_5",
375 .spi = &(struct spi_board_info) {
376 .modalias = "fb_ra8875",
377 .max_speed_hz = 5000000,
379 .platform_data = &(struct fbtft_platform_data) {
387 .gpios = (const struct fbtft_gpio []) {
396 .spi = &(struct spi_board_info) {
397 .modalias = "fb_uc1611",
398 .max_speed_hz = 32000000,
400 .platform_data = &(struct fbtft_platform_data) {
404 .gpios = (const struct fbtft_gpio []) {
411 .name = "ew24ha0_9bit",
412 .spi = &(struct spi_board_info) {
413 .modalias = "fb_uc1611",
414 .max_speed_hz = 32000000,
416 .platform_data = &(struct fbtft_platform_data) {
420 .gpios = (const struct fbtft_gpio []) {
427 .spi = &(struct spi_board_info) {
428 .modalias = "flexfb",
429 .max_speed_hz = 32000000,
431 .platform_data = &(struct fbtft_platform_data) {
432 .gpios = (const struct fbtft_gpio []) {
441 .pdev = &(struct platform_device) {
445 .release = fbtft_device_pdev_release,
446 .platform_data = &(struct fbtft_platform_data) {
447 .gpios = (const struct fbtft_gpio []) {
467 .name = "freetronicsoled128",
468 .spi = &(struct spi_board_info) {
469 .modalias = "fb_ssd1351",
470 .max_speed_hz = 20000000,
472 .platform_data = &(struct fbtft_platform_data) {
475 .backlight = FBTFT_ONBOARD_BACKLIGHT,
478 .gpios = (const struct fbtft_gpio []) {
487 .spi = &(struct spi_board_info) {
488 .modalias = "fb_hx8353d",
489 .max_speed_hz = 16000000,
491 .platform_data = &(struct fbtft_platform_data) {
496 .gpios = (const struct fbtft_gpio []) {
506 .spi = &(struct spi_board_info) {
507 .modalias = "fb_ili9320",
508 .max_speed_hz = 32000000,
510 .platform_data = &(struct fbtft_platform_data) {
517 .gpios = (const struct fbtft_gpio []) {
526 .spi = &(struct spi_board_info) {
527 .modalias = "fb_ili9325",
528 .max_speed_hz = 48000000,
530 .platform_data = &(struct fbtft_platform_data) {
534 .init_sequence = hy28b_init_sequence,
539 .gpios = (const struct fbtft_gpio []) {
544 .gamma = HY28B_GAMMA,
549 .spi = &(struct spi_board_info) {
550 .modalias = "fb_ili9481",
551 .max_speed_hz = 32000000,
553 .platform_data = &(struct fbtft_platform_data) {
560 .gpios = (const struct fbtft_gpio []) {
570 .pdev = &(struct platform_device) {
571 .name = "fb_s6d1121",
574 .release = fbtft_device_pdev_release,
575 .platform_data = &(struct fbtft_platform_data) {
581 .gpios = (const struct fbtft_gpio []) {
582 /* Wiring for LCD adapter kit */
584 { "dc", 0 }, /* rev 2: 2 */
585 { "wr", 1 }, /* rev 2: 3 */
589 { "db02", 21 }, /* rev 2: 27 */
602 .pdev = &(struct platform_device) {
603 .name = "fb_ili9325",
606 .release = fbtft_device_pdev_release,
607 .platform_data = &(struct fbtft_platform_data) {
613 .gpios = (const struct fbtft_gpio []) {
620 .name = "itdb28_spi",
621 .spi = &(struct spi_board_info) {
622 .modalias = "fb_ili9325",
623 .max_speed_hz = 32000000,
625 .platform_data = &(struct fbtft_platform_data) {
631 .gpios = (const struct fbtft_gpio []) {
639 .name = "mi0283qt-2",
640 .spi = &(struct spi_board_info) {
641 .modalias = "fb_hx8347d",
642 .max_speed_hz = 32000000,
644 .platform_data = &(struct fbtft_platform_data) {
651 .gpios = (const struct fbtft_gpio []) {
660 .name = "mi0283qt-9a",
661 .spi = &(struct spi_board_info) {
662 .modalias = "fb_ili9341",
663 .max_speed_hz = 32000000,
665 .platform_data = &(struct fbtft_platform_data) {
671 .gpios = (const struct fbtft_gpio []) {
679 .name = "mi0283qt-v2",
680 .spi = &(struct spi_board_info) {
681 .modalias = "fb_watterott",
682 .max_speed_hz = 4000000,
684 .platform_data = &(struct fbtft_platform_data) {
685 .gpios = (const struct fbtft_gpio []) {
693 .spi = &(struct spi_board_info) {
694 .modalias = "fb_pcd8544",
695 .max_speed_hz = 400000,
697 .platform_data = &(struct fbtft_platform_data) {
701 .gpios = (const struct fbtft_gpio []) {
710 .name = "nokia3310a",
711 .spi = &(struct spi_board_info) {
712 .modalias = "fb_tls8204",
713 .max_speed_hz = 1000000,
715 .platform_data = &(struct fbtft_platform_data) {
719 .gpios = (const struct fbtft_gpio []) {
729 .spi = &(struct spi_board_info) {
730 .modalias = "fb_ili9163",
731 .max_speed_hz = 12000000,
733 .platform_data = &(struct fbtft_platform_data) {
739 .gpios = (const struct fbtft_gpio []) {
747 .spi = &(struct spi_board_info) {
748 .modalias = "fb_ili9486",
749 .max_speed_hz = 32000000,
751 .platform_data = &(struct fbtft_platform_data) {
758 .gpios = (const struct fbtft_gpio []) {
768 .spi = &(struct spi_board_info) {
769 .modalias = "fb_ili9340",
770 .max_speed_hz = 32000000,
773 .platform_data = &(struct fbtft_platform_data) {
777 .init_sequence = pitft_init_sequence,
780 .gpios = (const struct fbtft_gpio []) {
788 .spi = &(struct spi_board_info) {
789 .modalias = "fb_ssd1351",
790 .max_speed_hz = 20000000,
792 .platform_data = &(struct fbtft_platform_data) {
797 .gpios = (const struct fbtft_gpio []) {
802 .gamma = "0 2 2 2 2 2 2 2 "
813 .name = "rpi-display",
814 .spi = &(struct spi_board_info) {
815 .modalias = "fb_ili9341",
816 .max_speed_hz = 32000000,
818 .platform_data = &(struct fbtft_platform_data) {
824 .gpios = (const struct fbtft_gpio []) {
834 .spi = &(struct spi_board_info) {
835 .modalias = "fb_s6d02a1",
836 .max_speed_hz = 32000000,
838 .platform_data = &(struct fbtft_platform_data) {
844 .gpios = (const struct fbtft_gpio []) {
853 .name = "sainsmart18",
854 .spi = &(struct spi_board_info) {
855 .modalias = "fb_st7735r",
856 .max_speed_hz = 32000000,
858 .platform_data = &(struct fbtft_platform_data) {
862 .gpios = (const struct fbtft_gpio []) {
870 .name = "sainsmart32",
871 .pdev = &(struct platform_device) {
872 .name = "fb_ssd1289",
875 .release = fbtft_device_pdev_release,
876 .platform_data = &(struct fbtft_platform_data) {
879 .txbuflen = -2, /* disable buffer */
881 .fbtftops.write = write_gpio16_wr_slow,
884 .gpios = (const struct fbtft_gpio []) {
891 .name = "sainsmart32_fast",
892 .pdev = &(struct platform_device) {
893 .name = "fb_ssd1289",
896 .release = fbtft_device_pdev_release,
897 .platform_data = &(struct fbtft_platform_data) {
900 .txbuflen = -2, /* disable buffer */
904 .gpios = (const struct fbtft_gpio []) {
911 .name = "sainsmart32_latched",
912 .pdev = &(struct platform_device) {
913 .name = "fb_ssd1289",
916 .release = fbtft_device_pdev_release,
917 .platform_data = &(struct fbtft_platform_data) {
920 .txbuflen = -2, /* disable buffer */
923 fbtft_write_gpio16_wr_latched,
926 .gpios = (const struct fbtft_gpio []) {
933 .name = "sainsmart32_spi",
934 .spi = &(struct spi_board_info) {
935 .modalias = "fb_ssd1289",
936 .max_speed_hz = 16000000,
938 .platform_data = &(struct fbtft_platform_data) {
944 .gpios = (const struct fbtft_gpio []) {
953 .spi = &(struct spi_board_info) {
954 .modalias = "spidev",
955 .max_speed_hz = 500000,
959 .platform_data = &(struct fbtft_platform_data) {
960 .gpios = (const struct fbtft_gpio []) {
967 .spi = &(struct spi_board_info) {
968 .modalias = "fb_ssd1331",
969 .max_speed_hz = 20000000,
971 .platform_data = &(struct fbtft_platform_data) {
975 .gpios = (const struct fbtft_gpio []) {
984 .spi = &(struct spi_board_info) {
985 .modalias = "fb_tinylcd",
986 .max_speed_hz = 32000000,
988 .platform_data = &(struct fbtft_platform_data) {
994 .gpios = (const struct fbtft_gpio []) {
1003 .name = "tm022hdh26",
1004 .spi = &(struct spi_board_info) {
1005 .modalias = "fb_ili9341",
1006 .max_speed_hz = 32000000,
1008 .platform_data = &(struct fbtft_platform_data) {
1014 .gpios = (const struct fbtft_gpio []) {
1023 .name = "tontec35_9481", /* boards before 02 July 2014 */
1024 .spi = &(struct spi_board_info) {
1025 .modalias = "fb_ili9481",
1026 .max_speed_hz = 128000000,
1028 .platform_data = &(struct fbtft_platform_data) {
1034 .gpios = (const struct fbtft_gpio []) {
1043 .name = "tontec35_9486", /* boards after 02 July 2014 */
1044 .spi = &(struct spi_board_info) {
1045 .modalias = "fb_ili9486",
1046 .max_speed_hz = 128000000,
1048 .platform_data = &(struct fbtft_platform_data) {
1054 .gpios = (const struct fbtft_gpio []) {
1063 .name = "upd161704",
1064 .spi = &(struct spi_board_info) {
1065 .modalias = "fb_upd161704",
1066 .max_speed_hz = 32000000,
1068 .platform_data = &(struct fbtft_platform_data) {
1072 .gpios = (const struct fbtft_gpio []) {
1080 .name = "waveshare32b",
1081 .spi = &(struct spi_board_info) {
1082 .modalias = "fb_ili9340",
1083 .max_speed_hz = 48000000,
1085 .platform_data = &(struct fbtft_platform_data) {
1090 waveshare32b_init_sequence,
1093 .gpios = (const struct fbtft_gpio []) {
1101 .name = "waveshare22",
1102 .spi = &(struct spi_board_info) {
1103 .modalias = "fb_bd663474",
1104 .max_speed_hz = 32000000,
1106 .platform_data = &(struct fbtft_platform_data) {
1110 .gpios = (const struct fbtft_gpio []) {
1118 /* This should be the last item.
1119 Used with the custom argument */
1121 .spi = &(struct spi_board_info) {
1125 .platform_data = &(struct fbtft_platform_data) {
1126 .gpios = (const struct fbtft_gpio []) {
1131 .pdev = &(struct platform_device) {
1135 .release = fbtft_device_pdev_release,
1136 .platform_data = &(struct fbtft_platform_data) {
1137 .gpios = (const struct fbtft_gpio []) {
1146 static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len)
1150 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
1151 static u16 prev_data;
1154 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
1155 "%s(len=%d): ", __func__, len);
1158 data = *(u16 *) buf;
1160 /* Start writing by pulling down /WR */
1161 gpio_set_value(par->gpio.wr, 0);
1164 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
1165 if (data == prev_data) {
1166 gpio_set_value(par->gpio.wr, 0); /* used as delay */
1168 for (i = 0; i < 16; i++) {
1169 if ((data & 1) != (prev_data & 1))
1170 gpio_set_value(par->gpio.db[i],
1177 for (i = 0; i < 16; i++) {
1178 gpio_set_value(par->gpio.db[i], data & 1);
1184 gpio_set_value(par->gpio.wr, 1);
1186 #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
1187 prev_data = *(u16 *) buf;
1196 static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par,
1197 int xs, int ys, int xe, int ye)
1199 write_reg(par, 0x2A, 0, xs + 2, 0, xe + 2);
1200 write_reg(par, 0x2B, 0, ys + 1, 0, ye + 1);
1201 write_reg(par, 0x2C);
1204 /* used if gpios parameter is present */
1205 static struct fbtft_gpio fbtft_device_param_gpios[MAX_GPIOS + 1] = { };
1207 static void fbtft_device_pdev_release(struct device *dev)
1209 /* Needed to silence this message:
1210 Device 'xxx' does not have a release() function, it is broken and must be fixed
1214 static int spi_device_found(struct device *dev, void *data)
1216 struct spi_device *spi = container_of(dev, struct spi_device, dev);
1218 dev_info(dev, "%s %s %dkHz %d bits mode=0x%02X\n", spi->modalias,
1219 dev_name(dev), spi->max_speed_hz / 1000, spi->bits_per_word,
1225 static void pr_spi_devices(void)
1227 pr_info(DRVNAME": SPI devices registered:\n");
1228 bus_for_each_dev(&spi_bus_type, NULL, NULL, spi_device_found);
1231 static int p_device_found(struct device *dev, void *data)
1233 struct platform_device
1234 *pdev = container_of(dev, struct platform_device, dev);
1236 if (strstr(pdev->name, "fb"))
1237 dev_info(dev, "%s id=%d pdata? %s\n", pdev->name, pdev->id,
1238 pdev->dev.platform_data ? "yes" : "no");
1243 static void pr_p_devices(void)
1245 pr_info(DRVNAME": 'fb' Platform devices registered:\n");
1246 bus_for_each_dev(&platform_bus_type, NULL, NULL, p_device_found);
1250 static void fbtft_device_spi_delete(struct spi_master *master, unsigned cs)
1255 snprintf(str, sizeof(str), "%s.%u", dev_name(&master->dev), cs);
1257 dev = bus_find_device_by_name(&spi_bus_type, NULL, str);
1260 dev_info(dev, "Deleting %s\n", str);
1265 static int fbtft_device_spi_device_register(struct spi_board_info *spi)
1267 struct spi_master *master;
1269 master = spi_busnum_to_master(spi->bus_num);
1271 pr_err(DRVNAME ": spi_busnum_to_master(%d) returned NULL\n",
1275 /* make sure it's available */
1276 fbtft_device_spi_delete(master, spi->chip_select);
1277 spi_device = spi_new_device(master, spi);
1278 put_device(&master->dev);
1280 dev_err(&master->dev, "spi_new_device() returned NULL\n");
1286 static int fbtft_device_spi_device_register(struct spi_board_info *spi)
1288 return spi_register_board_info(spi, 1);
1292 static int __init fbtft_device_init(void)
1294 struct spi_board_info *spi = NULL;
1295 struct fbtft_platform_data *pdata;
1296 const struct fbtft_gpio *gpio = NULL;
1297 char *p_gpio, *p_name, *p_num;
1303 pr_debug("\n\n"DRVNAME": init\n");
1307 pr_err(DRVNAME": missing module parameter: 'name'\n");
1314 if (init_num > FBTFT_MAX_INIT_SEQUENCE) {
1316 ": init parameter: exceeded max array size: %d\n",
1317 FBTFT_MAX_INIT_SEQUENCE);
1321 /* parse module parameter: gpios */
1322 while ((p_gpio = strsep(&gpios, ","))) {
1323 if (strchr(p_gpio, ':') == NULL) {
1325 ": error: missing ':' in gpios parameter: %s\n",
1330 p_name = strsep(&p_num, ":");
1331 if (p_name == NULL || p_num == NULL) {
1333 ": something bad happened parsing gpios parameter: %s\n",
1337 ret = kstrtol(p_num, 10, &val);
1340 ": could not parse number in gpios parameter: %s:%s\n",
1344 strncpy(fbtft_device_param_gpios[i].name, p_name,
1345 FBTFT_GPIO_NAME_SIZE - 1);
1346 fbtft_device_param_gpios[i++].gpio = (int) val;
1347 if (i == MAX_GPIOS) {
1349 ": gpios parameter: exceeded max array size: %d\n",
1354 if (fbtft_device_param_gpios[0].name[0])
1355 gpio = fbtft_device_param_gpios;
1358 pr_spi_devices(); /* print list of registered SPI devices */
1361 pr_p_devices(); /* print list of 'fb' platform devices */
1363 pr_debug(DRVNAME": name='%s', busnum=%d, cs=%d\n", name, busnum, cs);
1365 if (rotate > 0 && rotate < 4) {
1366 rotate = (4 - rotate) * 90;
1367 pr_warn("argument 'rotate' should be an angle. Values 1-3 is deprecated. Setting it to %d.\n",
1370 if (rotate != 0 && rotate != 90 && rotate != 180 && rotate != 270) {
1371 pr_warn("argument 'rotate' illegal value: %d. Setting it to 0.\n",
1376 /* name=list lists all supported displays */
1377 if (strncmp(name, "list", FBTFT_GPIO_NAME_SIZE) == 0) {
1378 pr_info(DRVNAME": Supported displays:\n");
1380 for (i = 0; i < ARRAY_SIZE(displays); i++)
1381 pr_info(DRVNAME": %s\n", displays[i].name);
1386 i = ARRAY_SIZE(displays) - 1;
1387 displays[i].name = name;
1389 displays[i].pdev->name = name;
1390 displays[i].spi = NULL;
1392 strncpy(displays[i].spi->modalias, name, SPI_NAME_SIZE);
1393 displays[i].pdev = NULL;
1397 for (i = 0; i < ARRAY_SIZE(displays); i++) {
1398 if (strncmp(name, displays[i].name, 32) == 0) {
1399 if (displays[i].spi) {
1400 spi = displays[i].spi;
1401 spi->chip_select = cs;
1402 spi->bus_num = busnum;
1404 spi->max_speed_hz = speed;
1407 pdata = (void *)spi->platform_data;
1408 } else if (displays[i].pdev) {
1409 p_device = displays[i].pdev;
1410 pdata = p_device->dev.platform_data;
1412 pr_err(DRVNAME": broken displays array\n");
1416 pdata->rotate = rotate;
1422 pdata->startbyte = startbyte;
1424 pdata->gamma = gamma;
1425 pdata->display.debug = debug;
1429 pdata->txbuflen = txbuflen;
1431 pdata->display.init_sequence = init;
1433 pdata->gpios = gpio;
1435 pdata->display.width = width;
1436 pdata->display.height = height;
1437 pdata->display.buswidth = buswidth;
1438 pdata->display.backlight = 1;
1441 if (displays[i].spi) {
1442 ret = fbtft_device_spi_device_register(spi);
1445 ": failed to register SPI device\n");
1449 ret = platform_device_register(p_device);
1452 ": platform_device_register() returned %d\n",
1463 pr_err(DRVNAME": display not supported: '%s'\n", name);
1467 if (verbose && pdata && pdata->gpios) {
1468 gpio = pdata->gpios;
1469 pr_info(DRVNAME": GPIOS used by '%s':\n", name);
1471 while (verbose && gpio->name[0]) {
1472 pr_info(DRVNAME": '%s' = GPIO%d\n",
1473 gpio->name, gpio->gpio);
1478 pr_info(DRVNAME": (none)\n");
1481 if (spi_device && (verbose > 1))
1483 if (p_device && (verbose > 1))
1489 static void __exit fbtft_device_exit(void)
1491 pr_debug(DRVNAME" - exit\n");
1494 device_del(&spi_device->dev);
1499 platform_device_unregister(p_device);
1503 arch_initcall(fbtft_device_init);
1504 module_exit(fbtft_device_exit);
1506 MODULE_DESCRIPTION("Add a FBTFT device.");
1507 MODULE_AUTHOR("Noralf Tronnes");
1508 MODULE_LICENSE("GPL");