Merge remote-tracking branch 'staging/staging-next'
[deliverable/linux.git] / drivers / staging / fbtft / fbtft_device.c
CommitLineData
06d30f02
TP
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.
06d30f02
TP
14 */
15
805deadb 16#define pr_fmt(fmt) "fbtft_device: " fmt
06d30f02
TP
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>
598af18a 22#include <video/mipi_display.h>
06d30f02
TP
23
24#include "fbtft.h"
25
06d30f02
TP
26#define MAX_GPIOS 32
27
cc060ed0
FJ
28static struct spi_device *spi_device;
29static struct platform_device *p_device;
06d30f02
TP
30
31static char *name;
32module_param(name, charp, 0);
56cda8ac 33MODULE_PARM_DESC(name, "Devicename (required). name=list => list all supported devices.");
06d30f02 34
1c41494a 35static unsigned int rotate;
06d30f02
TP
36module_param(rotate, uint, 0);
37MODULE_PARM_DESC(rotate,
38"Angle to rotate display counter clockwise: 0, 90, 180, 270");
39
1c41494a 40static unsigned int busnum;
06d30f02
TP
41module_param(busnum, uint, 0);
42MODULE_PARM_DESC(busnum, "SPI bus number (default=0)");
43
1c41494a 44static unsigned int cs;
06d30f02
TP
45module_param(cs, uint, 0);
46MODULE_PARM_DESC(cs, "SPI chip select (default=0)");
47
1c41494a 48static unsigned int speed;
06d30f02
TP
49module_param(speed, uint, 0);
50MODULE_PARM_DESC(speed, "SPI speed (override device default)");
51
52static int mode = -1;
53module_param(mode, int, 0);
54MODULE_PARM_DESC(mode, "SPI mode (override device default)");
55
56static char *gpios;
57module_param(gpios, charp, 0);
58MODULE_PARM_DESC(gpios,
56cda8ac 59"List of gpios. Comma separated with the form: reset:23,dc:24 (when overriding the default, all gpios must be specified)");
06d30f02 60
1c41494a 61static unsigned int fps;
06d30f02
TP
62module_param(fps, uint, 0);
63MODULE_PARM_DESC(fps, "Frames per second (override driver default)");
64
65static char *gamma;
66module_param(gamma, charp, 0);
67MODULE_PARM_DESC(gamma,
68"String representation of Gamma Curve(s). Driver specific.");
69
70static int txbuflen;
71module_param(txbuflen, int, 0);
72MODULE_PARM_DESC(txbuflen, "txbuflen (override driver default)");
73
74static int bgr = -1;
75module_param(bgr, int, 0);
76MODULE_PARM_DESC(bgr,
77"BGR bit (supported by some drivers).");
78
1c41494a 79static unsigned int startbyte;
06d30f02
TP
80module_param(startbyte, uint, 0);
81MODULE_PARM_DESC(startbyte, "Sets the Start byte used by some SPI displays.");
82
83static bool custom;
84module_param(custom, bool, 0);
56cda8ac 85MODULE_PARM_DESC(custom, "Add a custom display device. Use speed= argument to make it a SPI device, else platform_device");
06d30f02 86
1c41494a 87static unsigned int width;
06d30f02
TP
88module_param(width, uint, 0);
89MODULE_PARM_DESC(width, "Display width, used with the custom argument");
90
1c41494a 91static unsigned int height;
06d30f02
TP
92module_param(height, uint, 0);
93MODULE_PARM_DESC(height, "Display height, used with the custom argument");
94
1c41494a 95static unsigned int buswidth = 8;
06d30f02
TP
96module_param(buswidth, uint, 0);
97MODULE_PARM_DESC(buswidth, "Display bus width, used with the custom argument");
98
99static int init[FBTFT_MAX_INIT_SEQUENCE];
100static int init_num;
101module_param_array(init, int, &init_num, 0);
102MODULE_PARM_DESC(init, "Init sequence, used with the custom argument");
103
104static unsigned long debug;
73762b9d 105module_param(debug, ulong, 0);
06d30f02
TP
106MODULE_PARM_DESC(debug,
107"level: 0-7 (the remaining 29 bits is for advanced usage)");
108
1c41494a 109static unsigned int verbose = 3;
06d30f02
TP
110module_param(verbose, uint, 0);
111MODULE_PARM_DESC(verbose,
112"0 silent, >0 show gpios, >1 show devices, >2 show devices before (default=3)");
113
06d30f02
TP
114struct fbtft_device_display {
115 char *name;
116 struct spi_board_info *spi;
117 struct platform_device *pdev;
118};
119
120static void fbtft_device_pdev_release(struct device *dev);
121
122static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len);
123static 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
e9f68065
DM
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
134static int cberry28_init_sequence[] = {
135 /* turn off sleep mode */
598af18a 136 -1, MIPI_DCS_EXIT_SLEEP_MODE,
e9f68065
DM
137 -2, 120,
138
139 /* set pixel format to RGB-565 */
598af18a 140 -1, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT,
e9f68065
DM
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
646287ba
DM
165 /* VCOM = 0.675V */
166 -1, 0xBB, 0x17,
e9f68065
DM
167
168 /* VCOM offset = 0V */
169 -1, 0xC5, 0x20,
170
171 /*
646287ba 172 * AVDD = 6.8V
e9f68065
DM
173 * AVCL = -4.8V
174 * VDS = 2.3V
175 */
646287ba 176 -1, 0xD0, 0xA4, 0xA1,
e9f68065 177
598af18a 178 -1, MIPI_DCS_SET_DISPLAY_ON,
e9f68065
DM
179
180 -3,
181};
182
06d30f02 183static int hy28b_init_sequence[] = {
73762b9d
AM
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 };
06d30f02
TP
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
214static int pitft_init_sequence[] = {
a79cb390
PL
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,
73762b9d
AM
220 -1, 0xED, 0x64, 0x03, 0x12, 0x81,
221 -1, 0xE8, 0x85, 0x00, 0x78,
222 -1, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
a79cb390
PL
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};
06d30f02
TP
244
245static int waveshare32b_init_sequence[] = {
73762b9d
AM
246 -1, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02,
247 -1, 0xCF, 0x00, 0xC1, 0x30,
a79cb390
PL
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,
73762b9d 262 -1, 0xE0, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E,
a79cb390 263 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
73762b9d 264 -1, 0xE1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31,
a79cb390
PL
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};
06d30f02
TP
272
273/* Supported displays in alphabetical order */
274static 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,
6c604d66 305 .fbtftops.set_addr_win =
06d30f02
TP
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 }
e9f68065
DM
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 }
06d30f02
TP
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 }
a1560f9b
HC
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 }
06d30f02
TP
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 },
153fe946 614 .startbyte = 0x70,
06d30f02
TP
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 },
153fe946 635 .startbyte = 0x70,
06d30f02 636 .bgr = true,
73762b9d 637 .fps = 50,
06d30f02
TP
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 },
8e56b955
AG
683 { "dc", 0 }, /* rev 2: 2 */
684 { "wr", 1 }, /* rev 2: 3 */
06d30f02
TP
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 },
153fe946 748 .startbyte = 0x70,
06d30f02
TP
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 }, {
3b143b55
KA
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
06d30f02
TP
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 },
6c604d66
AG
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 "
06d30f02
TP
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,
6c604d66 1021 .fbtftops.write =
06d30f02
TP
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,
3c588452
AG
1188 .init_sequence =
1189 waveshare32b_init_sequence,
06d30f02
TP
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.
fe9b610b
AJ
1218 * Used with the custom argument
1219 */
06d30f02
TP
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
1246static 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) {
8cd977c3 1258 data = *(u16 *)buf;
06d30f02
TP
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],
b30367c0 1271 data & 1);
06d30f02
TP
1272 data >>= 1;
1273 prev_data >>= 1;
1274 }
1275 }
1276#else
1277 for (i = 0; i < 16; i++) {
b30367c0 1278 gpio_set_value(par->gpio.db[i], data & 1);
06d30f02
TP
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
8cd977c3 1287 prev_data = *(u16 *)buf;
06d30f02
TP
1288#endif
1289 buf += 2;
1290 len -= 2;
1291 }
1292
1293 return 0;
1294}
1295
1296static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par,
1297 int xs, int ys, int xe, int ye)
1298{
06d30f02
TP
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 */
94c0a544 1305static struct fbtft_gpio fbtft_device_param_gpios[MAX_GPIOS + 1] = { };
06d30f02
TP
1306
1307static void fbtft_device_pdev_release(struct device *dev)
1308{
1309/* Needed to silence this message:
fe9b610b
AJ
1310 * Device 'xxx' does not have a release() function,
1311 * it is broken and must be fixed
1312 */
06d30f02
TP
1313}
1314
1315static int spi_device_found(struct device *dev, void *data)
1316{
5d5ccf21 1317 struct spi_device *spi = to_spi_device(dev);
06d30f02 1318
962539a0
SM
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);
06d30f02
TP
1322
1323 return 0;
1324}
1325
1326static void pr_spi_devices(void)
1327{
e714b7ea 1328 pr_debug("SPI devices registered:\n");
06d30f02
TP
1329 bus_for_each_dev(&spi_bus_type, NULL, NULL, spi_device_found);
1330}
1331
1332static int p_device_found(struct device *dev, void *data)
1333{
1334 struct platform_device
f6bfc25e 1335 *pdev = to_platform_device(dev);
06d30f02
TP
1336
1337 if (strstr(pdev->name, "fb"))
962539a0
SM
1338 dev_info(dev, "%s id=%d pdata? %s\n", pdev->name, pdev->id,
1339 pdev->dev.platform_data ? "yes" : "no");
06d30f02
TP
1340
1341 return 0;
1342}
1343
1344static void pr_p_devices(void)
1345{
e714b7ea 1346 pr_debug("'fb' Platform devices registered:\n");
06d30f02
TP
1347 bus_for_each_dev(&platform_bus_type, NULL, NULL, p_device_found);
1348}
1349
1350#ifdef MODULE
1c41494a 1351static void fbtft_device_spi_delete(struct spi_master *master, unsigned int cs)
06d30f02
TP
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)
962539a0 1361 dev_info(dev, "Deleting %s\n", str);
06d30f02
TP
1362 device_del(dev);
1363 }
1364}
1365
1366static 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) {
805deadb
SM
1372 pr_err("spi_busnum_to_master(%d) returned NULL\n",
1373 spi->bus_num);
06d30f02
TP
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) {
962539a0 1381 dev_err(&master->dev, "spi_new_device() returned NULL\n");
06d30f02
TP
1382 return -EPERM;
1383 }
1384 return 0;
1385}
1386#else
1387static int fbtft_device_spi_device_register(struct spi_board_info *spi)
1388{
1389 return spi_register_board_info(spi, 1);
1390}
1391#endif
1392
1393static 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
06d30f02
TP
1404 if (name == NULL) {
1405#ifdef MODULE
805deadb 1406 pr_err("missing module parameter: 'name'\n");
06d30f02
TP
1407 return -EINVAL;
1408#else
1409 return 0;
1410#endif
1411 }
1412
1413 if (init_num > FBTFT_MAX_INIT_SEQUENCE) {
805deadb
SM
1414 pr_err("init parameter: exceeded max array size: %d\n",
1415 FBTFT_MAX_INIT_SEQUENCE);
06d30f02
TP
1416 return -EINVAL;
1417 }
1418
1419 /* parse module parameter: gpios */
1420 while ((p_gpio = strsep(&gpios, ","))) {
1421 if (strchr(p_gpio, ':') == NULL) {
805deadb
SM
1422 pr_err("error: missing ':' in gpios parameter: %s\n",
1423 p_gpio);
06d30f02
TP
1424 return -EINVAL;
1425 }
1426 p_num = p_gpio;
1427 p_name = strsep(&p_num, ":");
1428 if (p_name == NULL || p_num == NULL) {
805deadb
SM
1429 pr_err("something bad happened parsing gpios parameter: %s\n",
1430 p_gpio);
06d30f02
TP
1431 return -EINVAL;
1432 }
1433 ret = kstrtol(p_num, 10, &val);
1434 if (ret) {
805deadb
SM
1435 pr_err("could not parse number in gpios parameter: %s:%s\n",
1436 p_name, p_num);
06d30f02
TP
1437 return -EINVAL;
1438 }
eb6a2dbf
SM
1439 strncpy(fbtft_device_param_gpios[i].name, p_name,
1440 FBTFT_GPIO_NAME_SIZE - 1);
8cd977c3 1441 fbtft_device_param_gpios[i++].gpio = (int)val;
06d30f02 1442 if (i == MAX_GPIOS) {
805deadb
SM
1443 pr_err("gpios parameter: exceeded max array size: %d\n",
1444 MAX_GPIOS);
06d30f02
TP
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
1454 if (verbose > 2)
1455 pr_p_devices(); /* print list of 'fb' platform devices */
1456
805deadb 1457 pr_debug("name='%s', busnum=%d, cs=%d\n", name, busnum, cs);
06d30f02
TP
1458
1459 if (rotate > 0 && rotate < 4) {
1460 rotate = (4 - rotate) * 90;
1461 pr_warn("argument 'rotate' should be an angle. Values 1-3 is deprecated. Setting it to %d.\n",
1462 rotate);
1463 }
1464 if (rotate != 0 && rotate != 90 && rotate != 180 && rotate != 270) {
1465 pr_warn("argument 'rotate' illegal value: %d. Setting it to 0.\n",
1466 rotate);
1467 rotate = 0;
1468 }
1469
1470 /* name=list lists all supported displays */
fb7014df 1471 if (strncmp(name, "list", FBTFT_GPIO_NAME_SIZE) == 0) {
805deadb 1472 pr_info("Supported displays:\n");
06d30f02
TP
1473
1474 for (i = 0; i < ARRAY_SIZE(displays); i++)
805deadb 1475 pr_info("%s\n", displays[i].name);
06d30f02
TP
1476 return -ECANCELED;
1477 }
1478
1479 if (custom) {
1480 i = ARRAY_SIZE(displays) - 1;
1481 displays[i].name = name;
1482 if (speed == 0) {
1483 displays[i].pdev->name = name;
1484 displays[i].spi = NULL;
1485 } else {
1486 strncpy(displays[i].spi->modalias, name, SPI_NAME_SIZE);
1487 displays[i].pdev = NULL;
1488 }
1489 }
1490
1491 for (i = 0; i < ARRAY_SIZE(displays); i++) {
1492 if (strncmp(name, displays[i].name, 32) == 0) {
1493 if (displays[i].spi) {
1494 spi = displays[i].spi;
1495 spi->chip_select = cs;
1496 spi->bus_num = busnum;
1497 if (speed)
1498 spi->max_speed_hz = speed;
1499 if (mode != -1)
1500 spi->mode = mode;
1501 pdata = (void *)spi->platform_data;
1502 } else if (displays[i].pdev) {
1503 p_device = displays[i].pdev;
1504 pdata = p_device->dev.platform_data;
1505 } else {
805deadb 1506 pr_err("broken displays array\n");
06d30f02
TP
1507 return -EINVAL;
1508 }
1509
1510 pdata->rotate = rotate;
1511 if (bgr == 0)
1512 pdata->bgr = false;
1513 else if (bgr == 1)
1514 pdata->bgr = true;
1515 if (startbyte)
1516 pdata->startbyte = startbyte;
1517 if (gamma)
1518 pdata->gamma = gamma;
1519 pdata->display.debug = debug;
1520 if (fps)
1521 pdata->fps = fps;
1522 if (txbuflen)
1523 pdata->txbuflen = txbuflen;
1524 if (init_num)
1525 pdata->display.init_sequence = init;
1526 if (gpio)
1527 pdata->gpios = gpio;
1528 if (custom) {
1529 pdata->display.width = width;
1530 pdata->display.height = height;
1531 pdata->display.buswidth = buswidth;
1532 pdata->display.backlight = 1;
1533 }
1534
1535 if (displays[i].spi) {
1536 ret = fbtft_device_spi_device_register(spi);
1537 if (ret) {
805deadb 1538 pr_err("failed to register SPI device\n");
06d30f02
TP
1539 return ret;
1540 }
06d30f02
TP
1541 } else {
1542 ret = platform_device_register(p_device);
1543 if (ret < 0) {
805deadb
SM
1544 pr_err("platform_device_register() returned %d\n",
1545 ret);
06d30f02
TP
1546 return ret;
1547 }
06d30f02 1548 }
bc573c51
AG
1549 found = true;
1550 break;
06d30f02
TP
1551 }
1552 }
1553
1554 if (!found) {
805deadb 1555 pr_err("display not supported: '%s'\n", name);
06d30f02
TP
1556 return -EINVAL;
1557 }
1558
1559 if (verbose && pdata && pdata->gpios) {
1560 gpio = pdata->gpios;
805deadb 1561 pr_info("GPIOS used by '%s':\n", name);
06d30f02
TP
1562 found = false;
1563 while (verbose && gpio->name[0]) {
805deadb 1564 pr_info("'%s' = GPIO%d\n", gpio->name, gpio->gpio);
06d30f02
TP
1565 gpio++;
1566 found = true;
1567 }
1568 if (!found)
805deadb 1569 pr_info("(none)\n");
06d30f02
TP
1570 }
1571
1572 if (spi_device && (verbose > 1))
1573 pr_spi_devices();
1574 if (p_device && (verbose > 1))
1575 pr_p_devices();
1576
1577 return 0;
1578}
1579
1580static void __exit fbtft_device_exit(void)
1581{
06d30f02
TP
1582 if (spi_device) {
1583 device_del(&spi_device->dev);
1584 kfree(spi_device);
1585 }
1586
1587 if (p_device)
1588 platform_device_unregister(p_device);
1589
1590}
1591
1592arch_initcall(fbtft_device_init);
1593module_exit(fbtft_device_exit);
1594
1595MODULE_DESCRIPTION("Add a FBTFT device.");
1596MODULE_AUTHOR("Noralf Tronnes");
1597MODULE_LICENSE("GPL");
This page took 0.308785 seconds and 5 git commands to generate.