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