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