2 * Copyright (C) 2013 Noralf Tronnes
4 * This driver is inspired by:
5 * st7735fb.c, Copyright (C) 2011, Matt Porter
6 * broadsheetfb.c, Copyright (C) 2008, Jaya Kumar
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/string.h>
24 #include <linux/vmalloc.h>
25 #include <linux/slab.h>
26 #include <linux/init.h>
28 #include <linux/gpio.h>
29 #include <linux/spi/spi.h>
30 #include <linux/delay.h>
31 #include <linux/uaccess.h>
32 #include <linux/backlight.h>
33 #include <linux/platform_device.h>
34 #include <linux/spinlock.h>
35 #include <linux/dma-mapping.h>
37 #include <linux/of_gpio.h>
42 static unsigned long debug
;
43 module_param(debug
, ulong
, 0);
44 MODULE_PARM_DESC(debug
, "override device debug level");
47 static bool dma
= true;
48 module_param(dma
, bool, 0);
49 MODULE_PARM_DESC(dma
, "Use DMA buffer");
52 void fbtft_dbg_hex(const struct device
*dev
, int groupsize
,
53 void *buf
, size_t len
, const char *fmt
, ...)
56 static char textbuf
[512];
61 text_len
= vscnprintf(text
, sizeof(textbuf
), fmt
, args
);
64 hex_dump_to_buffer(buf
, len
, 32, groupsize
, text
+ text_len
,
65 512 - text_len
, false);
68 dev_info(dev
, "%s ...\n", text
);
70 dev_info(dev
, "%s\n", text
);
72 EXPORT_SYMBOL(fbtft_dbg_hex
);
74 static unsigned long fbtft_request_gpios_match(struct fbtft_par
*par
,
75 const struct fbtft_gpio
*gpio
)
80 fbtft_par_dbg(DEBUG_REQUEST_GPIOS_MATCH
, par
, "%s('%s')\n",
81 __func__
, gpio
->name
);
83 if (strcasecmp(gpio
->name
, "reset") == 0) {
84 par
->gpio
.reset
= gpio
->gpio
;
85 return GPIOF_OUT_INIT_HIGH
;
86 } else if (strcasecmp(gpio
->name
, "dc") == 0) {
87 par
->gpio
.dc
= gpio
->gpio
;
88 return GPIOF_OUT_INIT_LOW
;
89 } else if (strcasecmp(gpio
->name
, "cs") == 0) {
90 par
->gpio
.cs
= gpio
->gpio
;
91 return GPIOF_OUT_INIT_HIGH
;
92 } else if (strcasecmp(gpio
->name
, "wr") == 0) {
93 par
->gpio
.wr
= gpio
->gpio
;
94 return GPIOF_OUT_INIT_HIGH
;
95 } else if (strcasecmp(gpio
->name
, "rd") == 0) {
96 par
->gpio
.rd
= gpio
->gpio
;
97 return GPIOF_OUT_INIT_HIGH
;
98 } else if (strcasecmp(gpio
->name
, "latch") == 0) {
99 par
->gpio
.latch
= gpio
->gpio
;
100 return GPIOF_OUT_INIT_LOW
;
101 } else if (gpio
->name
[0] == 'd' && gpio
->name
[1] == 'b') {
102 ret
= kstrtol(&gpio
->name
[2], 10, &val
);
103 if (ret
== 0 && val
< 16) {
104 par
->gpio
.db
[val
] = gpio
->gpio
;
105 return GPIOF_OUT_INIT_LOW
;
107 } else if (strcasecmp(gpio
->name
, "led") == 0) {
108 par
->gpio
.led
[0] = gpio
->gpio
;
109 return GPIOF_OUT_INIT_LOW
;
110 } else if (strcasecmp(gpio
->name
, "led_") == 0) {
111 par
->gpio
.led
[0] = gpio
->gpio
;
112 return GPIOF_OUT_INIT_HIGH
;
115 return FBTFT_GPIO_NO_MATCH
;
118 static int fbtft_request_gpios(struct fbtft_par
*par
)
120 struct fbtft_platform_data
*pdata
= par
->pdata
;
121 const struct fbtft_gpio
*gpio
;
125 if (!(pdata
&& pdata
->gpios
))
129 while (gpio
->name
[0]) {
130 flags
= FBTFT_GPIO_NO_MATCH
;
131 /* if driver provides match function, try it first,
132 if no match use our own */
133 if (par
->fbtftops
.request_gpios_match
)
134 flags
= par
->fbtftops
.request_gpios_match(par
, gpio
);
135 if (flags
== FBTFT_GPIO_NO_MATCH
)
136 flags
= fbtft_request_gpios_match(par
, gpio
);
137 if (flags
!= FBTFT_GPIO_NO_MATCH
) {
138 ret
= devm_gpio_request_one(par
->info
->device
,
140 par
->info
->device
->driver
->name
);
142 dev_err(par
->info
->device
,
143 "%s: gpio_request_one('%s'=%d) failed with %d\n",
144 __func__
, gpio
->name
,
148 fbtft_par_dbg(DEBUG_REQUEST_GPIOS
, par
,
149 "%s: '%s' = GPIO%d\n",
150 __func__
, gpio
->name
, gpio
->gpio
);
159 static int fbtft_request_one_gpio(struct fbtft_par
*par
,
160 const char *name
, int index
, int *gpiop
)
162 struct device
*dev
= par
->info
->device
;
163 struct device_node
*node
= dev
->of_node
;
164 int gpio
, flags
, ret
= 0;
165 enum of_gpio_flags of_flags
;
167 if (of_find_property(node
, name
, NULL
)) {
168 gpio
= of_get_named_gpio_flags(node
, name
, index
, &of_flags
);
171 if (gpio
== -EPROBE_DEFER
)
175 "failed to get '%s' from DT\n", name
);
179 /* active low translates to initially low */
180 flags
= (of_flags
& OF_GPIO_ACTIVE_LOW
) ? GPIOF_OUT_INIT_LOW
:
182 ret
= devm_gpio_request_one(dev
, gpio
, flags
,
186 "gpio_request_one('%s'=%d) failed with %d\n",
192 fbtft_par_dbg(DEBUG_REQUEST_GPIOS
, par
, "%s: '%s' = GPIO%d\n",
193 __func__
, name
, gpio
);
199 static int fbtft_request_gpios_dt(struct fbtft_par
*par
)
204 if (!par
->info
->device
->of_node
)
207 ret
= fbtft_request_one_gpio(par
, "reset-gpios", 0, &par
->gpio
.reset
);
210 ret
= fbtft_request_one_gpio(par
, "dc-gpios", 0, &par
->gpio
.dc
);
213 ret
= fbtft_request_one_gpio(par
, "rd-gpios", 0, &par
->gpio
.rd
);
216 ret
= fbtft_request_one_gpio(par
, "wr-gpios", 0, &par
->gpio
.wr
);
219 ret
= fbtft_request_one_gpio(par
, "cs-gpios", 0, &par
->gpio
.cs
);
222 ret
= fbtft_request_one_gpio(par
, "latch-gpios", 0, &par
->gpio
.latch
);
225 for (i
= 0; i
< 16; i
++) {
226 ret
= fbtft_request_one_gpio(par
, "db-gpios", i
,
230 ret
= fbtft_request_one_gpio(par
, "led-gpios", i
,
234 ret
= fbtft_request_one_gpio(par
, "aux-gpios", i
,
244 #ifdef CONFIG_FB_BACKLIGHT
245 static int fbtft_backlight_update_status(struct backlight_device
*bd
)
247 struct fbtft_par
*par
= bl_get_data(bd
);
248 bool polarity
= !!(bd
->props
.state
& BL_CORE_DRIVER1
);
250 fbtft_par_dbg(DEBUG_BACKLIGHT
, par
,
251 "%s: polarity=%d, power=%d, fb_blank=%d\n",
252 __func__
, polarity
, bd
->props
.power
, bd
->props
.fb_blank
);
254 if ((bd
->props
.power
== FB_BLANK_UNBLANK
) && (bd
->props
.fb_blank
== FB_BLANK_UNBLANK
))
255 gpio_set_value(par
->gpio
.led
[0], polarity
);
257 gpio_set_value(par
->gpio
.led
[0], !polarity
);
262 static int fbtft_backlight_get_brightness(struct backlight_device
*bd
)
264 return bd
->props
.brightness
;
267 void fbtft_unregister_backlight(struct fbtft_par
*par
)
269 fbtft_par_dbg(DEBUG_BACKLIGHT
, par
, "%s()\n", __func__
);
271 if (par
->info
->bl_dev
) {
272 par
->info
->bl_dev
->props
.power
= FB_BLANK_POWERDOWN
;
273 backlight_update_status(par
->info
->bl_dev
);
274 backlight_device_unregister(par
->info
->bl_dev
);
275 par
->info
->bl_dev
= NULL
;
279 static const struct backlight_ops fbtft_bl_ops
= {
280 .get_brightness
= fbtft_backlight_get_brightness
,
281 .update_status
= fbtft_backlight_update_status
,
284 void fbtft_register_backlight(struct fbtft_par
*par
)
286 struct backlight_device
*bd
;
287 struct backlight_properties bl_props
= { 0, };
289 fbtft_par_dbg(DEBUG_BACKLIGHT
, par
, "%s()\n", __func__
);
291 if (par
->gpio
.led
[0] == -1) {
292 fbtft_par_dbg(DEBUG_BACKLIGHT
, par
,
293 "%s(): led pin not set, exiting.\n", __func__
);
297 bl_props
.type
= BACKLIGHT_RAW
;
298 /* Assume backlight is off, get polarity from current state of pin */
299 bl_props
.power
= FB_BLANK_POWERDOWN
;
300 if (!gpio_get_value(par
->gpio
.led
[0]))
301 bl_props
.state
|= BL_CORE_DRIVER1
;
303 bd
= backlight_device_register(dev_driver_string(par
->info
->device
),
304 par
->info
->device
, par
, &fbtft_bl_ops
, &bl_props
);
306 dev_err(par
->info
->device
,
307 "cannot register backlight device (%ld)\n",
311 par
->info
->bl_dev
= bd
;
313 if (!par
->fbtftops
.unregister_backlight
)
314 par
->fbtftops
.unregister_backlight
= fbtft_unregister_backlight
;
317 void fbtft_register_backlight(struct fbtft_par
*par
) { };
318 void fbtft_unregister_backlight(struct fbtft_par
*par
) { };
320 EXPORT_SYMBOL(fbtft_register_backlight
);
321 EXPORT_SYMBOL(fbtft_unregister_backlight
);
323 static void fbtft_set_addr_win(struct fbtft_par
*par
, int xs
, int ys
, int xe
,
326 /* Column address set */
328 (xs
>> 8) & 0xFF, xs
& 0xFF, (xe
>> 8) & 0xFF, xe
& 0xFF);
330 /* Row address set */
332 (ys
>> 8) & 0xFF, ys
& 0xFF, (ye
>> 8) & 0xFF, ye
& 0xFF);
335 write_reg(par
, 0x2C);
338 static void fbtft_reset(struct fbtft_par
*par
)
340 if (par
->gpio
.reset
== -1)
342 fbtft_par_dbg(DEBUG_RESET
, par
, "%s()\n", __func__
);
343 gpio_set_value(par
->gpio
.reset
, 0);
345 gpio_set_value(par
->gpio
.reset
, 1);
349 static void fbtft_update_display(struct fbtft_par
*par
, unsigned start_line
,
353 struct timespec ts_start
, ts_end
, ts_fps
, ts_duration
;
354 long fps_ms
, fps_us
, duration_ms
, duration_us
;
355 long fps
, throughput
;
359 if (unlikely(par
->debug
& (DEBUG_TIME_FIRST_UPDATE
| DEBUG_TIME_EACH_UPDATE
))) {
360 if ((par
->debug
& DEBUG_TIME_EACH_UPDATE
) ||
361 ((par
->debug
& DEBUG_TIME_FIRST_UPDATE
) && !par
->first_update_done
)) {
362 getnstimeofday(&ts_start
);
368 if (start_line
> end_line
) {
369 dev_warn(par
->info
->device
,
370 "%s: start_line=%u is larger than end_line=%u. Shouldn't happen, will do full display update\n",
371 __func__
, start_line
, end_line
);
373 end_line
= par
->info
->var
.yres
- 1;
375 if (start_line
> par
->info
->var
.yres
- 1 || end_line
> par
->info
->var
.yres
- 1) {
376 dev_warn(par
->info
->device
,
377 "%s: start_line=%u or end_line=%u is larger than max=%d. Shouldn't happen, will do full display update\n",
378 __func__
, start_line
, end_line
, par
->info
->var
.yres
- 1);
380 end_line
= par
->info
->var
.yres
- 1;
383 fbtft_par_dbg(DEBUG_UPDATE_DISPLAY
, par
, "%s(start_line=%u, end_line=%u)\n",
384 __func__
, start_line
, end_line
);
386 if (par
->fbtftops
.set_addr_win
)
387 par
->fbtftops
.set_addr_win(par
, 0, start_line
,
388 par
->info
->var
.xres
- 1, end_line
);
390 offset
= start_line
* par
->info
->fix
.line_length
;
391 len
= (end_line
- start_line
+ 1) * par
->info
->fix
.line_length
;
392 ret
= par
->fbtftops
.write_vmem(par
, offset
, len
);
394 dev_err(par
->info
->device
,
395 "%s: write_vmem failed to update display buffer\n",
398 if (unlikely(timeit
)) {
399 getnstimeofday(&ts_end
);
400 if (par
->update_time
.tv_nsec
== 0 && par
->update_time
.tv_sec
== 0) {
401 par
->update_time
.tv_sec
= ts_start
.tv_sec
;
402 par
->update_time
.tv_nsec
= ts_start
.tv_nsec
;
404 ts_fps
= timespec_sub(ts_start
, par
->update_time
);
405 par
->update_time
.tv_sec
= ts_start
.tv_sec
;
406 par
->update_time
.tv_nsec
= ts_start
.tv_nsec
;
407 fps_ms
= (ts_fps
.tv_sec
* 1000) + ((ts_fps
.tv_nsec
/ 1000000) % 1000);
408 fps_us
= (ts_fps
.tv_nsec
/ 1000) % 1000;
409 fps
= fps_ms
* 1000 + fps_us
;
410 fps
= fps
? 1000000 / fps
: 0;
412 ts_duration
= timespec_sub(ts_end
, ts_start
);
413 duration_ms
= (ts_duration
.tv_sec
* 1000) + ((ts_duration
.tv_nsec
/ 1000000) % 1000);
414 duration_us
= (ts_duration
.tv_nsec
/ 1000) % 1000;
415 throughput
= duration_ms
* 1000 + duration_us
;
416 throughput
= throughput
? (len
* 1000) / throughput
: 0;
417 throughput
= throughput
* 1000 / 1024;
419 dev_info(par
->info
->device
,
420 "Display update: %ld kB/s (%ld.%.3ld ms), fps=%ld (%ld.%.3ld ms)\n",
421 throughput
, duration_ms
, duration_us
,
422 fps
, fps_ms
, fps_us
);
423 par
->first_update_done
= true;
427 static void fbtft_mkdirty(struct fb_info
*info
, int y
, int height
)
429 struct fbtft_par
*par
= info
->par
;
430 struct fb_deferred_io
*fbdefio
= info
->fbdefio
;
432 /* special case, needed ? */
435 height
= info
->var
.yres
- 1;
438 /* Mark display lines/area as dirty */
439 spin_lock(&par
->dirty_lock
);
440 if (y
< par
->dirty_lines_start
)
441 par
->dirty_lines_start
= y
;
442 if (y
+ height
- 1 > par
->dirty_lines_end
)
443 par
->dirty_lines_end
= y
+ height
- 1;
444 spin_unlock(&par
->dirty_lock
);
446 /* Schedule deferred_io to update display (no-op if already on queue)*/
447 schedule_delayed_work(&info
->deferred_work
, fbdefio
->delay
);
450 static void fbtft_deferred_io(struct fb_info
*info
, struct list_head
*pagelist
)
452 struct fbtft_par
*par
= info
->par
;
453 unsigned dirty_lines_start
, dirty_lines_end
;
456 unsigned y_low
= 0, y_high
= 0;
459 spin_lock(&par
->dirty_lock
);
460 dirty_lines_start
= par
->dirty_lines_start
;
461 dirty_lines_end
= par
->dirty_lines_end
;
462 /* set display line markers as clean */
463 par
->dirty_lines_start
= par
->info
->var
.yres
- 1;
464 par
->dirty_lines_end
= 0;
465 spin_unlock(&par
->dirty_lock
);
467 /* Mark display lines as dirty */
468 list_for_each_entry(page
, pagelist
, lru
) {
470 index
= page
->index
<< PAGE_SHIFT
;
471 y_low
= index
/ info
->fix
.line_length
;
472 y_high
= (index
+ PAGE_SIZE
- 1) / info
->fix
.line_length
;
473 dev_dbg(info
->device
,
474 "page->index=%lu y_low=%d y_high=%d\n",
475 page
->index
, y_low
, y_high
);
476 if (y_high
> info
->var
.yres
- 1)
477 y_high
= info
->var
.yres
- 1;
478 if (y_low
< dirty_lines_start
)
479 dirty_lines_start
= y_low
;
480 if (y_high
> dirty_lines_end
)
481 dirty_lines_end
= y_high
;
484 par
->fbtftops
.update_display(info
->par
,
485 dirty_lines_start
, dirty_lines_end
);
488 static void fbtft_fb_fillrect(struct fb_info
*info
,
489 const struct fb_fillrect
*rect
)
491 struct fbtft_par
*par
= info
->par
;
494 "%s: dx=%d, dy=%d, width=%d, height=%d\n",
495 __func__
, rect
->dx
, rect
->dy
, rect
->width
, rect
->height
);
496 sys_fillrect(info
, rect
);
498 par
->fbtftops
.mkdirty(info
, rect
->dy
, rect
->height
);
501 static void fbtft_fb_copyarea(struct fb_info
*info
,
502 const struct fb_copyarea
*area
)
504 struct fbtft_par
*par
= info
->par
;
507 "%s: dx=%d, dy=%d, width=%d, height=%d\n",
508 __func__
, area
->dx
, area
->dy
, area
->width
, area
->height
);
509 sys_copyarea(info
, area
);
511 par
->fbtftops
.mkdirty(info
, area
->dy
, area
->height
);
514 static void fbtft_fb_imageblit(struct fb_info
*info
,
515 const struct fb_image
*image
)
517 struct fbtft_par
*par
= info
->par
;
520 "%s: dx=%d, dy=%d, width=%d, height=%d\n",
521 __func__
, image
->dx
, image
->dy
, image
->width
, image
->height
);
522 sys_imageblit(info
, image
);
524 par
->fbtftops
.mkdirty(info
, image
->dy
, image
->height
);
527 static ssize_t
fbtft_fb_write(struct fb_info
*info
, const char __user
*buf
,
528 size_t count
, loff_t
*ppos
)
530 struct fbtft_par
*par
= info
->par
;
534 "%s: count=%zd, ppos=%llu\n", __func__
, count
, *ppos
);
535 res
= fb_sys_write(info
, buf
, count
, ppos
);
537 /* TODO: only mark changed area
538 update all for now */
539 par
->fbtftops
.mkdirty(info
, -1, 0);
545 static unsigned int chan_to_field(unsigned chan
, struct fb_bitfield
*bf
)
548 chan
>>= 16 - bf
->length
;
549 return chan
<< bf
->offset
;
552 static int fbtft_fb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
553 unsigned blue
, unsigned transp
,
554 struct fb_info
*info
)
560 "%s(regno=%u, red=0x%X, green=0x%X, blue=0x%X, trans=0x%X)\n",
561 __func__
, regno
, red
, green
, blue
, transp
);
563 switch (info
->fix
.visual
) {
564 case FB_VISUAL_TRUECOLOR
:
566 u32
*pal
= info
->pseudo_palette
;
568 val
= chan_to_field(red
, &info
->var
.red
);
569 val
|= chan_to_field(green
, &info
->var
.green
);
570 val
|= chan_to_field(blue
, &info
->var
.blue
);
581 static int fbtft_fb_blank(int blank
, struct fb_info
*info
)
583 struct fbtft_par
*par
= info
->par
;
586 dev_dbg(info
->dev
, "%s(blank=%d)\n",
589 if (!par
->fbtftops
.blank
)
593 case FB_BLANK_POWERDOWN
:
594 case FB_BLANK_VSYNC_SUSPEND
:
595 case FB_BLANK_HSYNC_SUSPEND
:
596 case FB_BLANK_NORMAL
:
597 ret
= par
->fbtftops
.blank(par
, true);
599 case FB_BLANK_UNBLANK
:
600 ret
= par
->fbtftops
.blank(par
, false);
606 static void fbtft_merge_fbtftops(struct fbtft_ops
*dst
, struct fbtft_ops
*src
)
609 dst
->write
= src
->write
;
611 dst
->read
= src
->read
;
613 dst
->write_vmem
= src
->write_vmem
;
614 if (src
->write_register
)
615 dst
->write_register
= src
->write_register
;
616 if (src
->set_addr_win
)
617 dst
->set_addr_win
= src
->set_addr_win
;
619 dst
->reset
= src
->reset
;
621 dst
->mkdirty
= src
->mkdirty
;
622 if (src
->update_display
)
623 dst
->update_display
= src
->update_display
;
624 if (src
->init_display
)
625 dst
->init_display
= src
->init_display
;
627 dst
->blank
= src
->blank
;
628 if (src
->request_gpios_match
)
629 dst
->request_gpios_match
= src
->request_gpios_match
;
630 if (src
->request_gpios
)
631 dst
->request_gpios
= src
->request_gpios
;
632 if (src
->verify_gpios
)
633 dst
->verify_gpios
= src
->verify_gpios
;
634 if (src
->register_backlight
)
635 dst
->register_backlight
= src
->register_backlight
;
636 if (src
->unregister_backlight
)
637 dst
->unregister_backlight
= src
->unregister_backlight
;
639 dst
->set_var
= src
->set_var
;
641 dst
->set_gamma
= src
->set_gamma
;
645 * fbtft_framebuffer_alloc - creates a new frame buffer info structure
647 * @display: pointer to structure describing the display
648 * @dev: pointer to the device for this fb, this can be NULL
650 * Creates a new frame buffer info structure.
652 * Also creates and populates the following structures:
655 * info->pseudo_palette
659 * Returns the new structure, or NULL if an error occurred.
662 struct fb_info
*fbtft_framebuffer_alloc(struct fbtft_display
*display
,
664 struct fbtft_platform_data
*pdata
)
666 struct fb_info
*info
;
667 struct fbtft_par
*par
;
668 struct fb_ops
*fbops
= NULL
;
669 struct fb_deferred_io
*fbdefio
= NULL
;
675 int txbuflen
= display
->txbuflen
;
676 unsigned bpp
= display
->bpp
;
677 unsigned fps
= display
->fps
;
679 int *init_sequence
= display
->init_sequence
;
680 char *gamma
= display
->gamma
;
681 unsigned long *gamma_curves
= NULL
;
684 if (display
->gamma_num
* display
->gamma_len
> FBTFT_GAMMA_MAX_VALUES_TOTAL
) {
685 dev_err(dev
, "FBTFT_GAMMA_MAX_VALUES_TOTAL=%d is exceeded\n",
686 FBTFT_GAMMA_MAX_VALUES_TOTAL
);
697 dev_err(dev
, "platform data is missing\n");
701 /* override driver values? */
705 txbuflen
= pdata
->txbuflen
;
706 if (pdata
->display
.init_sequence
)
707 init_sequence
= pdata
->display
.init_sequence
;
709 gamma
= pdata
->gamma
;
710 if (pdata
->display
.debug
)
711 display
->debug
= pdata
->display
.debug
;
712 if (pdata
->display
.backlight
)
713 display
->backlight
= pdata
->display
.backlight
;
714 if (pdata
->display
.width
)
715 display
->width
= pdata
->display
.width
;
716 if (pdata
->display
.height
)
717 display
->height
= pdata
->display
.height
;
718 if (pdata
->display
.buswidth
)
719 display
->buswidth
= pdata
->display
.buswidth
;
720 if (pdata
->display
.regwidth
)
721 display
->regwidth
= pdata
->display
.regwidth
;
723 display
->debug
|= debug
;
724 fbtft_expand_debug_value(&display
->debug
);
726 switch (pdata
->rotate
) {
729 width
= display
->height
;
730 height
= display
->width
;
733 width
= display
->width
;
734 height
= display
->height
;
737 vmem_size
= display
->width
* display
->height
* bpp
/ 8;
738 vmem
= vzalloc(vmem_size
);
742 fbops
= devm_kzalloc(dev
, sizeof(struct fb_ops
), GFP_KERNEL
);
746 fbdefio
= devm_kzalloc(dev
, sizeof(struct fb_deferred_io
), GFP_KERNEL
);
750 buf
= devm_kzalloc(dev
, 128, GFP_KERNEL
);
754 if (display
->gamma_num
&& display
->gamma_len
) {
755 gamma_curves
= devm_kzalloc(dev
, display
->gamma_num
* display
->gamma_len
* sizeof(gamma_curves
[0]),
761 info
= framebuffer_alloc(sizeof(struct fbtft_par
), dev
);
765 info
->screen_base
= (u8 __force __iomem
*)vmem
;
767 info
->fbdefio
= fbdefio
;
769 fbops
->owner
= dev
->driver
->owner
;
770 fbops
->fb_read
= fb_sys_read
;
771 fbops
->fb_write
= fbtft_fb_write
;
772 fbops
->fb_fillrect
= fbtft_fb_fillrect
;
773 fbops
->fb_copyarea
= fbtft_fb_copyarea
;
774 fbops
->fb_imageblit
= fbtft_fb_imageblit
;
775 fbops
->fb_setcolreg
= fbtft_fb_setcolreg
;
776 fbops
->fb_blank
= fbtft_fb_blank
;
778 fbdefio
->delay
= HZ
/fps
;
779 fbdefio
->deferred_io
= fbtft_deferred_io
;
780 fb_deferred_io_init(info
);
782 strncpy(info
->fix
.id
, dev
->driver
->name
, 16);
783 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
784 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
785 info
->fix
.xpanstep
= 0;
786 info
->fix
.ypanstep
= 0;
787 info
->fix
.ywrapstep
= 0;
788 info
->fix
.line_length
= width
* bpp
/ 8;
789 info
->fix
.accel
= FB_ACCEL_NONE
;
790 info
->fix
.smem_len
= vmem_size
;
792 info
->var
.rotate
= pdata
->rotate
;
793 info
->var
.xres
= width
;
794 info
->var
.yres
= height
;
795 info
->var
.xres_virtual
= info
->var
.xres
;
796 info
->var
.yres_virtual
= info
->var
.yres
;
797 info
->var
.bits_per_pixel
= bpp
;
798 info
->var
.nonstd
= 1;
801 info
->var
.red
.offset
= 11;
802 info
->var
.red
.length
= 5;
803 info
->var
.green
.offset
= 5;
804 info
->var
.green
.length
= 6;
805 info
->var
.blue
.offset
= 0;
806 info
->var
.blue
.length
= 5;
807 info
->var
.transp
.offset
= 0;
808 info
->var
.transp
.length
= 0;
810 info
->flags
= FBINFO_FLAG_DEFAULT
| FBINFO_VIRTFB
;
815 par
->debug
= display
->debug
;
817 spin_lock_init(&par
->dirty_lock
);
818 par
->bgr
= pdata
->bgr
;
819 par
->startbyte
= pdata
->startbyte
;
820 par
->init_sequence
= init_sequence
;
821 par
->gamma
.curves
= gamma_curves
;
822 par
->gamma
.num_curves
= display
->gamma_num
;
823 par
->gamma
.num_values
= display
->gamma_len
;
824 mutex_init(&par
->gamma
.lock
);
825 info
->pseudo_palette
= par
->pseudo_palette
;
827 if (par
->gamma
.curves
&& gamma
) {
828 if (fbtft_gamma_parse_str(par
,
829 par
->gamma
.curves
, gamma
, strlen(gamma
)))
833 /* Transmit buffer */
835 txbuflen
= vmem_size
+ 2; /* add in case startbyte is used */
837 #ifdef __LITTLE_ENDIAN
838 if ((!txbuflen
) && (bpp
> 8))
839 txbuflen
= PAGE_SIZE
; /* need buffer for byteswapping */
843 #ifdef CONFIG_HAS_DMA
845 dev
->coherent_dma_mask
= ~0;
846 txbuf
= dmam_alloc_coherent(dev
, txbuflen
, &par
->txbuf
.dma
, GFP_DMA
);
850 txbuf
= devm_kzalloc(par
->info
->device
, txbuflen
, GFP_KERNEL
);
854 par
->txbuf
.buf
= txbuf
;
855 par
->txbuf
.len
= txbuflen
;
858 /* Initialize gpios to disabled */
859 par
->gpio
.reset
= -1;
864 par
->gpio
.latch
= -1;
865 for (i
= 0; i
< 16; i
++) {
866 par
->gpio
.db
[i
] = -1;
867 par
->gpio
.led
[i
] = -1;
868 par
->gpio
.aux
[i
] = -1;
871 /* default fbtft operations */
872 par
->fbtftops
.write
= fbtft_write_spi
;
873 par
->fbtftops
.read
= fbtft_read_spi
;
874 par
->fbtftops
.write_vmem
= fbtft_write_vmem16_bus8
;
875 par
->fbtftops
.write_register
= fbtft_write_reg8_bus8
;
876 par
->fbtftops
.set_addr_win
= fbtft_set_addr_win
;
877 par
->fbtftops
.reset
= fbtft_reset
;
878 par
->fbtftops
.mkdirty
= fbtft_mkdirty
;
879 par
->fbtftops
.update_display
= fbtft_update_display
;
880 par
->fbtftops
.request_gpios
= fbtft_request_gpios
;
881 if (display
->backlight
)
882 par
->fbtftops
.register_backlight
= fbtft_register_backlight
;
884 /* use driver provided functions */
885 fbtft_merge_fbtftops(&par
->fbtftops
, &display
->fbtftops
);
894 EXPORT_SYMBOL(fbtft_framebuffer_alloc
);
897 * fbtft_framebuffer_release - frees up all memory used by the framebuffer
899 * @info: frame buffer info structure
902 void fbtft_framebuffer_release(struct fb_info
*info
)
904 fb_deferred_io_cleanup(info
);
905 vfree(info
->screen_base
);
906 framebuffer_release(info
);
908 EXPORT_SYMBOL(fbtft_framebuffer_release
);
911 * fbtft_register_framebuffer - registers a tft frame buffer device
912 * @fb_info: frame buffer info structure
914 * Sets SPI driverdata if needed
915 * Requests needed gpios.
916 * Initializes display
918 * Registers a frame buffer device @fb_info.
920 * Returns negative errno on error, or zero for success.
923 int fbtft_register_framebuffer(struct fb_info
*fb_info
)
928 struct fbtft_par
*par
= fb_info
->par
;
929 struct spi_device
*spi
= par
->spi
;
932 if (!par
->fbtftops
.init_display
) {
933 dev_err(fb_info
->device
, "missing fbtftops.init_display()\n");
938 spi_set_drvdata(spi
, fb_info
);
940 platform_set_drvdata(par
->pdev
, fb_info
);
942 ret
= par
->fbtftops
.request_gpios(par
);
946 if (par
->fbtftops
.verify_gpios
) {
947 ret
= par
->fbtftops
.verify_gpios(par
);
952 ret
= par
->fbtftops
.init_display(par
);
955 if (par
->fbtftops
.set_var
) {
956 ret
= par
->fbtftops
.set_var(par
);
961 /* update the entire display */
962 par
->fbtftops
.update_display(par
, 0, par
->info
->var
.yres
- 1);
964 if (par
->fbtftops
.set_gamma
&& par
->gamma
.curves
) {
965 ret
= par
->fbtftops
.set_gamma(par
, par
->gamma
.curves
);
970 if (par
->fbtftops
.register_backlight
)
971 par
->fbtftops
.register_backlight(par
);
973 ret
= register_framebuffer(fb_info
);
977 fbtft_sysfs_init(par
);
980 sprintf(text1
, ", %zu KiB %sbuffer memory",
981 par
->txbuf
.len
>> 10, par
->txbuf
.dma
? "DMA " : "");
983 sprintf(text2
, ", spi%d.%d at %d MHz", spi
->master
->bus_num
,
984 spi
->chip_select
, spi
->max_speed_hz
/ 1000000);
985 dev_info(fb_info
->dev
,
986 "%s frame buffer, %dx%d, %d KiB video memory%s, fps=%lu%s\n",
987 fb_info
->fix
.id
, fb_info
->var
.xres
, fb_info
->var
.yres
,
988 fb_info
->fix
.smem_len
>> 10, text1
,
989 HZ
/ fb_info
->fbdefio
->delay
, text2
);
991 #ifdef CONFIG_FB_BACKLIGHT
992 /* Turn on backlight if available */
993 if (fb_info
->bl_dev
) {
994 fb_info
->bl_dev
->props
.power
= FB_BLANK_UNBLANK
;
995 fb_info
->bl_dev
->ops
->update_status(fb_info
->bl_dev
);
1002 if (par
->fbtftops
.unregister_backlight
)
1003 par
->fbtftops
.unregister_backlight(par
);
1005 spi_set_drvdata(spi
, NULL
);
1007 platform_set_drvdata(par
->pdev
, NULL
);
1011 EXPORT_SYMBOL(fbtft_register_framebuffer
);
1014 * fbtft_unregister_framebuffer - releases a tft frame buffer device
1015 * @fb_info: frame buffer info structure
1017 * Frees SPI driverdata if needed
1019 * Unregisters frame buffer device.
1022 int fbtft_unregister_framebuffer(struct fb_info
*fb_info
)
1024 struct fbtft_par
*par
= fb_info
->par
;
1025 struct spi_device
*spi
= par
->spi
;
1028 spi_set_drvdata(spi
, NULL
);
1030 platform_set_drvdata(par
->pdev
, NULL
);
1031 if (par
->fbtftops
.unregister_backlight
)
1032 par
->fbtftops
.unregister_backlight(par
);
1033 fbtft_sysfs_exit(par
);
1034 return unregister_framebuffer(fb_info
);
1036 EXPORT_SYMBOL(fbtft_unregister_framebuffer
);
1040 * fbtft_init_display_dt() - Device Tree init_display() function
1043 * Return: 0 if successful, negative if error
1045 static int fbtft_init_display_dt(struct fbtft_par
*par
)
1047 struct device_node
*node
= par
->info
->device
->of_node
;
1048 struct property
*prop
;
1056 prop
= of_find_property(node
, "init", NULL
);
1057 p
= of_prop_next_u32(prop
, NULL
, &val
);
1061 par
->fbtftops
.reset(par
);
1062 if (par
->gpio
.cs
!= -1)
1063 gpio_set_value(par
->gpio
.cs
, 0); /* Activate chip */
1066 if (val
& FBTFT_OF_INIT_CMD
) {
1069 while (p
&& !(val
& 0xFFFF0000)) {
1071 dev_err(par
->info
->device
,
1072 "%s: Maximum register values exceeded\n",
1077 p
= of_prop_next_u32(prop
, p
, &val
);
1079 /* make debug message */
1080 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
,
1081 "init: write_register:\n");
1082 for (j
= 0; j
< i
; j
++)
1083 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
,
1084 "buf[%d] = %02X\n", j
, buf
[j
]);
1086 par
->fbtftops
.write_register(par
, i
,
1087 buf
[0], buf
[1], buf
[2], buf
[3],
1088 buf
[4], buf
[5], buf
[6], buf
[7],
1089 buf
[8], buf
[9], buf
[10], buf
[11],
1090 buf
[12], buf
[13], buf
[14], buf
[15],
1091 buf
[16], buf
[17], buf
[18], buf
[19],
1092 buf
[20], buf
[21], buf
[22], buf
[23],
1093 buf
[24], buf
[25], buf
[26], buf
[27],
1094 buf
[28], buf
[29], buf
[30], buf
[31],
1095 buf
[32], buf
[33], buf
[34], buf
[35],
1096 buf
[36], buf
[37], buf
[38], buf
[39],
1097 buf
[40], buf
[41], buf
[42], buf
[43],
1098 buf
[44], buf
[45], buf
[46], buf
[47],
1099 buf
[48], buf
[49], buf
[50], buf
[51],
1100 buf
[52], buf
[53], buf
[54], buf
[55],
1101 buf
[56], buf
[57], buf
[58], buf
[59],
1102 buf
[60], buf
[61], buf
[62], buf
[63]);
1103 } else if (val
& FBTFT_OF_INIT_DELAY
) {
1104 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
,
1105 "init: msleep(%u)\n", val
& 0xFFFF);
1106 msleep(val
& 0xFFFF);
1107 p
= of_prop_next_u32(prop
, p
, &val
);
1109 dev_err(par
->info
->device
, "illegal init value 0x%X\n",
1120 * fbtft_init_display() - Generic init_display() function
1123 * Uses par->init_sequence to do the initialization
1125 * Return: 0 if successful, negative if error
1127 int fbtft_init_display(struct fbtft_par
*par
)
1136 if (!par
->init_sequence
) {
1137 dev_err(par
->info
->device
,
1138 "error: init_sequence is not set\n");
1142 /* make sure stop marker exists */
1143 for (i
= 0; i
< FBTFT_MAX_INIT_SEQUENCE
; i
++)
1144 if (par
->init_sequence
[i
] == -3)
1146 if (i
== FBTFT_MAX_INIT_SEQUENCE
) {
1147 dev_err(par
->info
->device
,
1148 "missing stop marker at end of init sequence\n");
1152 par
->fbtftops
.reset(par
);
1153 if (par
->gpio
.cs
!= -1)
1154 gpio_set_value(par
->gpio
.cs
, 0); /* Activate chip */
1157 while (i
< FBTFT_MAX_INIT_SEQUENCE
) {
1158 if (par
->init_sequence
[i
] == -3) {
1162 if (par
->init_sequence
[i
] >= 0) {
1163 dev_err(par
->info
->device
,
1164 "missing delimiter at position %d\n", i
);
1167 if (par
->init_sequence
[i
+ 1] < 0) {
1168 dev_err(par
->info
->device
,
1169 "missing value after delimiter %d at position %d\n",
1170 par
->init_sequence
[i
], i
);
1173 switch (par
->init_sequence
[i
]) {
1176 /* make debug message */
1179 while (par
->init_sequence
[j
] >= 0) {
1180 sprintf(str
, "0x%02X ", par
->init_sequence
[j
]);
1184 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
,
1185 "init: write(0x%02X) %s\n",
1186 par
->init_sequence
[i
], msg
);
1190 while (par
->init_sequence
[i
] >= 0) {
1192 dev_err(par
->info
->device
,
1193 "%s: Maximum register values exceeded\n",
1197 buf
[j
++] = par
->init_sequence
[i
++];
1199 par
->fbtftops
.write_register(par
, j
,
1200 buf
[0], buf
[1], buf
[2], buf
[3],
1201 buf
[4], buf
[5], buf
[6], buf
[7],
1202 buf
[8], buf
[9], buf
[10], buf
[11],
1203 buf
[12], buf
[13], buf
[14], buf
[15],
1204 buf
[16], buf
[17], buf
[18], buf
[19],
1205 buf
[20], buf
[21], buf
[22], buf
[23],
1206 buf
[24], buf
[25], buf
[26], buf
[27],
1207 buf
[28], buf
[29], buf
[30], buf
[31],
1208 buf
[32], buf
[33], buf
[34], buf
[35],
1209 buf
[36], buf
[37], buf
[38], buf
[39],
1210 buf
[40], buf
[41], buf
[42], buf
[43],
1211 buf
[44], buf
[45], buf
[46], buf
[47],
1212 buf
[48], buf
[49], buf
[50], buf
[51],
1213 buf
[52], buf
[53], buf
[54], buf
[55],
1214 buf
[56], buf
[57], buf
[58], buf
[59],
1215 buf
[60], buf
[61], buf
[62], buf
[63]);
1219 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
,
1220 "init: mdelay(%d)\n", par
->init_sequence
[i
]);
1221 mdelay(par
->init_sequence
[i
++]);
1224 dev_err(par
->info
->device
,
1225 "unknown delimiter %d at position %d\n",
1226 par
->init_sequence
[i
], i
);
1231 dev_err(par
->info
->device
,
1232 "%s: something is wrong. Shouldn't get here.\n", __func__
);
1235 EXPORT_SYMBOL(fbtft_init_display
);
1238 * fbtft_verify_gpios() - Generic verify_gpios() function
1241 * Uses @spi, @pdev and @buswidth to determine which GPIOs is needed
1243 * Return: 0 if successful, negative if error
1245 static int fbtft_verify_gpios(struct fbtft_par
*par
)
1247 struct fbtft_platform_data
*pdata
= par
->pdata
;
1250 fbtft_par_dbg(DEBUG_VERIFY_GPIOS
, par
, "%s()\n", __func__
);
1252 if (pdata
->display
.buswidth
!= 9 && par
->startbyte
== 0 &&
1254 dev_err(par
->info
->device
,
1255 "Missing info about 'dc' gpio. Aborting.\n");
1262 if (par
->gpio
.wr
< 0) {
1263 dev_err(par
->info
->device
, "Missing 'wr' gpio. Aborting.\n");
1266 for (i
= 0; i
< pdata
->display
.buswidth
; i
++) {
1267 if (par
->gpio
.db
[i
] < 0) {
1268 dev_err(par
->info
->device
,
1269 "Missing 'db%02d' gpio. Aborting.\n", i
);
1278 /* returns 0 if the property is not present */
1279 static u32
fbtft_of_value(struct device_node
*node
, const char *propname
)
1284 ret
= of_property_read_u32(node
, propname
, &val
);
1286 pr_info("%s: %s = %u\n", __func__
, propname
, val
);
1291 static struct fbtft_platform_data
*fbtft_probe_dt(struct device
*dev
)
1293 struct device_node
*node
= dev
->of_node
;
1294 struct fbtft_platform_data
*pdata
;
1297 dev_err(dev
, "Missing platform data or DT\n");
1298 return ERR_PTR(-EINVAL
);
1301 pdata
= devm_kzalloc(dev
, sizeof(*pdata
), GFP_KERNEL
);
1303 return ERR_PTR(-ENOMEM
);
1305 pdata
->display
.width
= fbtft_of_value(node
, "width");
1306 pdata
->display
.height
= fbtft_of_value(node
, "height");
1307 pdata
->display
.regwidth
= fbtft_of_value(node
, "regwidth");
1308 pdata
->display
.buswidth
= fbtft_of_value(node
, "buswidth");
1309 pdata
->display
.backlight
= fbtft_of_value(node
, "backlight");
1310 pdata
->display
.bpp
= fbtft_of_value(node
, "bpp");
1311 pdata
->display
.debug
= fbtft_of_value(node
, "debug");
1312 pdata
->rotate
= fbtft_of_value(node
, "rotate");
1313 pdata
->bgr
= of_property_read_bool(node
, "bgr");
1314 pdata
->fps
= fbtft_of_value(node
, "fps");
1315 pdata
->txbuflen
= fbtft_of_value(node
, "txbuflen");
1316 pdata
->startbyte
= fbtft_of_value(node
, "startbyte");
1317 of_property_read_string(node
, "gamma", (const char **)&pdata
->gamma
);
1319 if (of_find_property(node
, "led-gpios", NULL
))
1320 pdata
->display
.backlight
= 1;
1321 if (of_find_property(node
, "init", NULL
))
1322 pdata
->display
.fbtftops
.init_display
= fbtft_init_display_dt
;
1323 pdata
->display
.fbtftops
.request_gpios
= fbtft_request_gpios_dt
;
1328 static struct fbtft_platform_data
*fbtft_probe_dt(struct device
*dev
)
1330 dev_err(dev
, "Missing platform data\n");
1331 return ERR_PTR(-EINVAL
);
1336 * fbtft_probe_common() - Generic device probe() helper function
1337 * @display: Display properties
1339 * @pdev: Platform device
1341 * Allocates, initializes and registers a framebuffer
1343 * Either @sdev or @pdev should be NULL
1345 * Return: 0 if successful, negative if error
1347 int fbtft_probe_common(struct fbtft_display
*display
,
1348 struct spi_device
*sdev
, struct platform_device
*pdev
)
1351 struct fb_info
*info
;
1352 struct fbtft_par
*par
;
1353 struct fbtft_platform_data
*pdata
;
1361 if (unlikely(display
->debug
& DEBUG_DRIVER_INIT_FUNCTIONS
))
1362 dev_info(dev
, "%s()\n", __func__
);
1364 pdata
= dev
->platform_data
;
1366 pdata
= fbtft_probe_dt(dev
);
1368 return PTR_ERR(pdata
);
1371 info
= fbtft_framebuffer_alloc(display
, dev
, pdata
);
1379 if (display
->buswidth
== 0) {
1380 dev_err(dev
, "buswidth is not set\n");
1384 /* write register functions */
1385 if (display
->regwidth
== 8 && display
->buswidth
== 8) {
1386 par
->fbtftops
.write_register
= fbtft_write_reg8_bus8
;
1388 if (display
->regwidth
== 8 && display
->buswidth
== 9 && par
->spi
) {
1389 par
->fbtftops
.write_register
= fbtft_write_reg8_bus9
;
1390 } else if (display
->regwidth
== 16 && display
->buswidth
== 8) {
1391 par
->fbtftops
.write_register
= fbtft_write_reg16_bus8
;
1392 } else if (display
->regwidth
== 16 && display
->buswidth
== 16) {
1393 par
->fbtftops
.write_register
= fbtft_write_reg16_bus16
;
1396 "no default functions for regwidth=%d and buswidth=%d\n",
1397 display
->regwidth
, display
->buswidth
);
1400 /* write_vmem() functions */
1401 if (display
->buswidth
== 8)
1402 par
->fbtftops
.write_vmem
= fbtft_write_vmem16_bus8
;
1403 else if (display
->buswidth
== 9)
1404 par
->fbtftops
.write_vmem
= fbtft_write_vmem16_bus9
;
1405 else if (display
->buswidth
== 16)
1406 par
->fbtftops
.write_vmem
= fbtft_write_vmem16_bus16
;
1408 /* GPIO write() functions */
1410 if (display
->buswidth
== 8)
1411 par
->fbtftops
.write
= fbtft_write_gpio8_wr
;
1412 else if (display
->buswidth
== 16)
1413 par
->fbtftops
.write
= fbtft_write_gpio16_wr
;
1416 /* 9-bit SPI setup */
1417 if (par
->spi
&& display
->buswidth
== 9) {
1418 if (par
->spi
->master
->bits_per_word_mask
& SPI_BPW_MASK(9)) {
1419 par
->spi
->bits_per_word
= 9;
1421 dev_warn(&par
->spi
->dev
,
1422 "9-bit SPI not available, emulating using 8-bit.\n");
1423 /* allocate buffer with room for dc bits */
1424 par
->extra
= devm_kzalloc(par
->info
->device
,
1425 par
->txbuf
.len
+ (par
->txbuf
.len
/ 8) + 8,
1431 par
->fbtftops
.write
= fbtft_write_spi_emulate_9
;
1435 if (!par
->fbtftops
.verify_gpios
)
1436 par
->fbtftops
.verify_gpios
= fbtft_verify_gpios
;
1438 /* make sure we still use the driver provided functions */
1439 fbtft_merge_fbtftops(&par
->fbtftops
, &display
->fbtftops
);
1441 /* use init_sequence if provided */
1442 if (par
->init_sequence
)
1443 par
->fbtftops
.init_display
= fbtft_init_display
;
1445 /* use platform_data provided functions above all */
1446 fbtft_merge_fbtftops(&par
->fbtftops
, &pdata
->display
.fbtftops
);
1448 ret
= fbtft_register_framebuffer(info
);
1455 fbtft_framebuffer_release(info
);
1459 EXPORT_SYMBOL(fbtft_probe_common
);
1462 * fbtft_remove_common() - Generic device remove() helper function
1464 * @info: Framebuffer
1466 * Unregisters and releases the framebuffer
1468 * Return: 0 if successful, negative if error
1470 int fbtft_remove_common(struct device
*dev
, struct fb_info
*info
)
1472 struct fbtft_par
*par
;
1478 fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS
, par
,
1479 "%s()\n", __func__
);
1480 fbtft_unregister_framebuffer(info
);
1481 fbtft_framebuffer_release(info
);
1485 EXPORT_SYMBOL(fbtft_remove_common
);
1487 MODULE_LICENSE("GPL");