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.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/string.h>
28 #include <linux/vmalloc.h>
29 #include <linux/slab.h>
30 #include <linux/init.h>
32 #include <linux/gpio.h>
33 #include <linux/spi/spi.h>
34 #include <linux/delay.h>
35 #include <linux/uaccess.h>
36 #include <linux/backlight.h>
37 #include <linux/platform_device.h>
38 #include <linux/spinlock.h>
39 #include <linux/dma-mapping.h>
41 #include <linux/of_gpio.h>
46 static unsigned long debug
;
47 module_param(debug
, ulong
, 0);
48 MODULE_PARM_DESC(debug
, "override device debug level");
51 static bool dma
= true;
52 module_param(dma
, bool, 0);
53 MODULE_PARM_DESC(dma
, "Use DMA buffer");
57 void fbtft_dbg_hex(const struct device
*dev
, int groupsize
,
58 void *buf
, size_t len
, const char *fmt
, ...)
61 static char textbuf
[512];
66 text_len
= vscnprintf(text
, sizeof(textbuf
), fmt
, args
);
69 hex_dump_to_buffer(buf
, len
, 32, groupsize
, text
+ text_len
,
70 512 - text_len
, false);
73 dev_info(dev
, "%s ...\n", text
);
75 dev_info(dev
, "%s\n", text
);
77 EXPORT_SYMBOL(fbtft_dbg_hex
);
79 static unsigned long fbtft_request_gpios_match(struct fbtft_par
*par
,
80 const struct fbtft_gpio
*gpio
)
85 fbtft_par_dbg(DEBUG_REQUEST_GPIOS_MATCH
, par
, "%s('%s')\n",
86 __func__
, gpio
->name
);
88 if (strcasecmp(gpio
->name
, "reset") == 0) {
89 par
->gpio
.reset
= gpio
->gpio
;
90 return GPIOF_OUT_INIT_HIGH
;
91 } else if (strcasecmp(gpio
->name
, "dc") == 0) {
92 par
->gpio
.dc
= gpio
->gpio
;
93 return GPIOF_OUT_INIT_LOW
;
94 } else if (strcasecmp(gpio
->name
, "cs") == 0) {
95 par
->gpio
.cs
= gpio
->gpio
;
96 return GPIOF_OUT_INIT_HIGH
;
97 } else if (strcasecmp(gpio
->name
, "wr") == 0) {
98 par
->gpio
.wr
= gpio
->gpio
;
99 return GPIOF_OUT_INIT_HIGH
;
100 } else if (strcasecmp(gpio
->name
, "rd") == 0) {
101 par
->gpio
.rd
= gpio
->gpio
;
102 return GPIOF_OUT_INIT_HIGH
;
103 } else if (strcasecmp(gpio
->name
, "latch") == 0) {
104 par
->gpio
.latch
= gpio
->gpio
;
105 return GPIOF_OUT_INIT_LOW
;
106 } else if (gpio
->name
[0] == 'd' && gpio
->name
[1] == 'b') {
107 ret
= kstrtol(&gpio
->name
[2], 10, &val
);
108 if (ret
== 0 && val
< 16) {
109 par
->gpio
.db
[val
] = gpio
->gpio
;
110 return GPIOF_OUT_INIT_LOW
;
112 } else if (strcasecmp(gpio
->name
, "led") == 0) {
113 par
->gpio
.led
[0] = gpio
->gpio
;
114 return GPIOF_OUT_INIT_LOW
;
115 } else if (strcasecmp(gpio
->name
, "led_") == 0) {
116 par
->gpio
.led
[0] = gpio
->gpio
;
117 return GPIOF_OUT_INIT_HIGH
;
120 return FBTFT_GPIO_NO_MATCH
;
123 static int fbtft_request_gpios(struct fbtft_par
*par
)
125 struct fbtft_platform_data
*pdata
= par
->pdata
;
126 const struct fbtft_gpio
*gpio
;
130 if (pdata
&& pdata
->gpios
) {
132 while (gpio
->name
[0]) {
133 flags
= FBTFT_GPIO_NO_MATCH
;
134 /* if driver provides match function, try it first,
135 if no match use our own */
136 if (par
->fbtftops
.request_gpios_match
)
137 flags
= par
->fbtftops
.request_gpios_match(par
, gpio
);
138 if (flags
== FBTFT_GPIO_NO_MATCH
)
139 flags
= fbtft_request_gpios_match(par
, gpio
);
140 if (flags
!= FBTFT_GPIO_NO_MATCH
) {
141 ret
= devm_gpio_request_one(par
->info
->device
,
143 par
->info
->device
->driver
->name
);
145 dev_err(par
->info
->device
,
146 "%s: gpio_request_one('%s'=%d) failed with %d\n",
147 __func__
, gpio
->name
,
151 fbtft_par_dbg(DEBUG_REQUEST_GPIOS
, par
,
152 "%s: '%s' = GPIO%d\n",
153 __func__
, gpio
->name
, gpio
->gpio
);
163 static int fbtft_request_one_gpio(struct fbtft_par
*par
,
164 const char *name
, int index
, int *gpiop
)
166 struct device
*dev
= par
->info
->device
;
167 struct device_node
*node
= dev
->of_node
;
168 int gpio
, flags
, ret
= 0;
169 enum of_gpio_flags of_flags
;
171 if (of_find_property(node
, name
, NULL
)) {
172 gpio
= of_get_named_gpio_flags(node
, name
, index
, &of_flags
);
175 if (gpio
== -EPROBE_DEFER
)
179 "failed to get '%s' from DT\n", name
);
183 /* active low translates to initially low */
184 flags
= (of_flags
& OF_GPIO_ACTIVE_LOW
) ? GPIOF_OUT_INIT_LOW
:
186 ret
= devm_gpio_request_one(dev
, gpio
, flags
,
190 "gpio_request_one('%s'=%d) failed with %d\n",
196 fbtft_par_dbg(DEBUG_REQUEST_GPIOS
, par
, "%s: '%s' = GPIO%d\n",
197 __func__
, name
, gpio
);
203 static int fbtft_request_gpios_dt(struct fbtft_par
*par
)
208 if (!par
->info
->device
->of_node
)
211 ret
= fbtft_request_one_gpio(par
, "reset-gpios", 0, &par
->gpio
.reset
);
214 ret
= fbtft_request_one_gpio(par
, "dc-gpios", 0, &par
->gpio
.dc
);
217 ret
= fbtft_request_one_gpio(par
, "rd-gpios", 0, &par
->gpio
.rd
);
220 ret
= fbtft_request_one_gpio(par
, "wr-gpios", 0, &par
->gpio
.wr
);
223 ret
= fbtft_request_one_gpio(par
, "cs-gpios", 0, &par
->gpio
.cs
);
226 ret
= fbtft_request_one_gpio(par
, "latch-gpios", 0, &par
->gpio
.latch
);
229 for (i
= 0; i
< 16; i
++) {
230 ret
= fbtft_request_one_gpio(par
, "db-gpios", i
,
234 ret
= fbtft_request_one_gpio(par
, "led-gpios", i
,
238 ret
= fbtft_request_one_gpio(par
, "aux-gpios", i
,
248 #ifdef CONFIG_FB_BACKLIGHT
249 static int fbtft_backlight_update_status(struct backlight_device
*bd
)
251 struct fbtft_par
*par
= bl_get_data(bd
);
252 bool polarity
= !!(bd
->props
.state
& BL_CORE_DRIVER1
);
254 fbtft_par_dbg(DEBUG_BACKLIGHT
, par
,
255 "%s: polarity=%d, power=%d, fb_blank=%d\n",
256 __func__
, polarity
, bd
->props
.power
, bd
->props
.fb_blank
);
258 if ((bd
->props
.power
== FB_BLANK_UNBLANK
) && (bd
->props
.fb_blank
== FB_BLANK_UNBLANK
))
259 gpio_set_value(par
->gpio
.led
[0], polarity
);
261 gpio_set_value(par
->gpio
.led
[0], !polarity
);
266 static int fbtft_backlight_get_brightness(struct backlight_device
*bd
)
268 return bd
->props
.brightness
;
271 void fbtft_unregister_backlight(struct fbtft_par
*par
)
273 const struct backlight_ops
*bl_ops
;
275 fbtft_par_dbg(DEBUG_BACKLIGHT
, par
, "%s()\n", __func__
);
277 if (par
->info
->bl_dev
) {
278 par
->info
->bl_dev
->props
.power
= FB_BLANK_POWERDOWN
;
279 backlight_update_status(par
->info
->bl_dev
);
280 bl_ops
= par
->info
->bl_dev
->ops
;
281 backlight_device_unregister(par
->info
->bl_dev
);
282 par
->info
->bl_dev
= NULL
;
286 void fbtft_register_backlight(struct fbtft_par
*par
)
288 struct backlight_device
*bd
;
289 struct backlight_properties bl_props
= { 0, };
290 struct backlight_ops
*bl_ops
;
292 fbtft_par_dbg(DEBUG_BACKLIGHT
, par
, "%s()\n", __func__
);
294 if (par
->gpio
.led
[0] == -1) {
295 fbtft_par_dbg(DEBUG_BACKLIGHT
, par
,
296 "%s(): led pin not set, exiting.\n", __func__
);
300 bl_ops
= devm_kzalloc(par
->info
->device
, sizeof(struct backlight_ops
),
305 bl_ops
->get_brightness
= fbtft_backlight_get_brightness
;
306 bl_ops
->update_status
= fbtft_backlight_update_status
;
307 bl_props
.type
= BACKLIGHT_RAW
;
308 /* Assume backlight is off, get polarity from current state of pin */
309 bl_props
.power
= FB_BLANK_POWERDOWN
;
310 if (!gpio_get_value(par
->gpio
.led
[0]))
311 bl_props
.state
|= BL_CORE_DRIVER1
;
313 bd
= backlight_device_register(dev_driver_string(par
->info
->device
),
314 par
->info
->device
, par
, bl_ops
, &bl_props
);
316 dev_err(par
->info
->device
,
317 "cannot register backlight device (%ld)\n",
321 par
->info
->bl_dev
= bd
;
323 if (!par
->fbtftops
.unregister_backlight
)
324 par
->fbtftops
.unregister_backlight
= fbtft_unregister_backlight
;
327 void fbtft_register_backlight(struct fbtft_par
*par
) { };
328 void fbtft_unregister_backlight(struct fbtft_par
*par
) { };
330 EXPORT_SYMBOL(fbtft_register_backlight
);
331 EXPORT_SYMBOL(fbtft_unregister_backlight
);
333 static void fbtft_set_addr_win(struct fbtft_par
*par
, int xs
, int ys
, int xe
,
336 fbtft_par_dbg(DEBUG_SET_ADDR_WIN
, par
,
337 "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__
, xs
, ys
, xe
, ye
);
339 /* Column address set */
341 (xs
>> 8) & 0xFF, xs
& 0xFF, (xe
>> 8) & 0xFF, xe
& 0xFF);
343 /* Row address set */
345 (ys
>> 8) & 0xFF, ys
& 0xFF, (ye
>> 8) & 0xFF, ye
& 0xFF);
348 write_reg(par
, 0x2C);
352 static void fbtft_reset(struct fbtft_par
*par
)
354 if (par
->gpio
.reset
== -1)
356 fbtft_par_dbg(DEBUG_RESET
, par
, "%s()\n", __func__
);
357 gpio_set_value(par
->gpio
.reset
, 0);
359 gpio_set_value(par
->gpio
.reset
, 1);
364 static void fbtft_update_display(struct fbtft_par
*par
, unsigned start_line
,
368 struct timespec ts_start
, ts_end
, ts_fps
, ts_duration
;
369 long fps_ms
, fps_us
, duration_ms
, duration_us
;
370 long fps
, throughput
;
374 if (unlikely(par
->debug
& (DEBUG_TIME_FIRST_UPDATE
| DEBUG_TIME_EACH_UPDATE
))) {
375 if ((par
->debug
& DEBUG_TIME_EACH_UPDATE
) ||
376 ((par
->debug
& DEBUG_TIME_FIRST_UPDATE
) && !par
->first_update_done
)) {
377 getnstimeofday(&ts_start
);
383 if (start_line
> end_line
) {
384 dev_warn(par
->info
->device
,
385 "%s: start_line=%u is larger than end_line=%u. Shouldn't happen, will do full display update\n",
386 __func__
, start_line
, end_line
);
388 end_line
= par
->info
->var
.yres
- 1;
390 if (start_line
> par
->info
->var
.yres
- 1 || end_line
> par
->info
->var
.yres
- 1) {
391 dev_warn(par
->info
->device
,
392 "%s: start_line=%u or end_line=%u is larger than max=%d. Shouldn't happen, will do full display update\n",
393 __func__
, start_line
, end_line
, par
->info
->var
.yres
- 1);
395 end_line
= par
->info
->var
.yres
- 1;
398 fbtft_par_dbg(DEBUG_UPDATE_DISPLAY
, par
, "%s(start_line=%u, end_line=%u)\n",
399 __func__
, start_line
, end_line
);
401 if (par
->fbtftops
.set_addr_win
)
402 par
->fbtftops
.set_addr_win(par
, 0, start_line
,
403 par
->info
->var
.xres
-1, end_line
);
405 offset
= start_line
* par
->info
->fix
.line_length
;
406 len
= (end_line
- start_line
+ 1) * par
->info
->fix
.line_length
;
407 ret
= par
->fbtftops
.write_vmem(par
, offset
, len
);
409 dev_err(par
->info
->device
,
410 "%s: write_vmem failed to update display buffer\n",
413 if (unlikely(timeit
)) {
414 getnstimeofday(&ts_end
);
415 if (par
->update_time
.tv_nsec
== 0 && par
->update_time
.tv_sec
== 0) {
416 par
->update_time
.tv_sec
= ts_start
.tv_sec
;
417 par
->update_time
.tv_nsec
= ts_start
.tv_nsec
;
419 ts_fps
= timespec_sub(ts_start
, par
->update_time
);
420 par
->update_time
.tv_sec
= ts_start
.tv_sec
;
421 par
->update_time
.tv_nsec
= ts_start
.tv_nsec
;
422 fps_ms
= (ts_fps
.tv_sec
* 1000) + ((ts_fps
.tv_nsec
/ 1000000) % 1000);
423 fps_us
= (ts_fps
.tv_nsec
/ 1000) % 1000;
424 fps
= fps_ms
* 1000 + fps_us
;
425 fps
= fps
? 1000000 / fps
: 0;
427 ts_duration
= timespec_sub(ts_end
, ts_start
);
428 duration_ms
= (ts_duration
.tv_sec
* 1000) + ((ts_duration
.tv_nsec
/ 1000000) % 1000);
429 duration_us
= (ts_duration
.tv_nsec
/ 1000) % 1000;
430 throughput
= duration_ms
* 1000 + duration_us
;
431 throughput
= throughput
? (len
* 1000) / throughput
: 0;
432 throughput
= throughput
* 1000 / 1024;
434 dev_info(par
->info
->device
,
435 "Display update: %ld kB/s (%ld.%.3ld ms), fps=%ld (%ld.%.3ld ms)\n",
436 throughput
, duration_ms
, duration_us
,
437 fps
, fps_ms
, fps_us
);
438 par
->first_update_done
= true;
443 static void fbtft_mkdirty(struct fb_info
*info
, int y
, int height
)
445 struct fbtft_par
*par
= info
->par
;
446 struct fb_deferred_io
*fbdefio
= info
->fbdefio
;
448 /* special case, needed ? */
451 height
= info
->var
.yres
- 1;
454 /* Mark display lines/area as dirty */
455 spin_lock(&par
->dirty_lock
);
456 if (y
< par
->dirty_lines_start
)
457 par
->dirty_lines_start
= y
;
458 if (y
+ height
- 1 > par
->dirty_lines_end
)
459 par
->dirty_lines_end
= y
+ height
- 1;
460 spin_unlock(&par
->dirty_lock
);
462 /* Schedule deferred_io to update display (no-op if already on queue)*/
463 schedule_delayed_work(&info
->deferred_work
, fbdefio
->delay
);
466 static void fbtft_deferred_io(struct fb_info
*info
, struct list_head
*pagelist
)
468 struct fbtft_par
*par
= info
->par
;
469 unsigned dirty_lines_start
, dirty_lines_end
;
472 unsigned y_low
= 0, y_high
= 0;
475 spin_lock(&par
->dirty_lock
);
476 dirty_lines_start
= par
->dirty_lines_start
;
477 dirty_lines_end
= par
->dirty_lines_end
;
478 /* set display line markers as clean */
479 par
->dirty_lines_start
= par
->info
->var
.yres
- 1;
480 par
->dirty_lines_end
= 0;
481 spin_unlock(&par
->dirty_lock
);
483 /* Mark display lines as dirty */
484 list_for_each_entry(page
, pagelist
, lru
) {
486 index
= page
->index
<< PAGE_SHIFT
;
487 y_low
= index
/ info
->fix
.line_length
;
488 y_high
= (index
+ PAGE_SIZE
- 1) / info
->fix
.line_length
;
489 dev_dbg(info
->device
,
490 "page->index=%lu y_low=%d y_high=%d\n",
491 page
->index
, y_low
, y_high
);
492 if (y_high
> info
->var
.yres
- 1)
493 y_high
= info
->var
.yres
- 1;
494 if (y_low
< dirty_lines_start
)
495 dirty_lines_start
= y_low
;
496 if (y_high
> dirty_lines_end
)
497 dirty_lines_end
= y_high
;
500 par
->fbtftops
.update_display(info
->par
,
501 dirty_lines_start
, dirty_lines_end
);
505 static void fbtft_fb_fillrect(struct fb_info
*info
,
506 const struct fb_fillrect
*rect
)
508 struct fbtft_par
*par
= info
->par
;
511 "%s: dx=%d, dy=%d, width=%d, height=%d\n",
512 __func__
, rect
->dx
, rect
->dy
, rect
->width
, rect
->height
);
513 sys_fillrect(info
, rect
);
515 par
->fbtftops
.mkdirty(info
, rect
->dy
, rect
->height
);
518 static void fbtft_fb_copyarea(struct fb_info
*info
,
519 const struct fb_copyarea
*area
)
521 struct fbtft_par
*par
= info
->par
;
524 "%s: dx=%d, dy=%d, width=%d, height=%d\n",
525 __func__
, area
->dx
, area
->dy
, area
->width
, area
->height
);
526 sys_copyarea(info
, area
);
528 par
->fbtftops
.mkdirty(info
, area
->dy
, area
->height
);
531 static void fbtft_fb_imageblit(struct fb_info
*info
,
532 const struct fb_image
*image
)
534 struct fbtft_par
*par
= info
->par
;
537 "%s: dx=%d, dy=%d, width=%d, height=%d\n",
538 __func__
, image
->dx
, image
->dy
, image
->width
, image
->height
);
539 sys_imageblit(info
, image
);
541 par
->fbtftops
.mkdirty(info
, image
->dy
, image
->height
);
544 static ssize_t
fbtft_fb_write(struct fb_info
*info
, const char __user
*buf
,
545 size_t count
, loff_t
*ppos
)
547 struct fbtft_par
*par
= info
->par
;
551 "%s: count=%zd, ppos=%llu\n", __func__
, count
, *ppos
);
552 res
= fb_sys_write(info
, buf
, count
, ppos
);
554 /* TODO: only mark changed area
555 update all for now */
556 par
->fbtftops
.mkdirty(info
, -1, 0);
562 static unsigned int chan_to_field(unsigned chan
, struct fb_bitfield
*bf
)
565 chan
>>= 16 - bf
->length
;
566 return chan
<< bf
->offset
;
569 static int fbtft_fb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
570 unsigned blue
, unsigned transp
,
571 struct fb_info
*info
)
577 "%s(regno=%u, red=0x%X, green=0x%X, blue=0x%X, trans=0x%X)\n",
578 __func__
, regno
, red
, green
, blue
, transp
);
580 switch (info
->fix
.visual
) {
581 case FB_VISUAL_TRUECOLOR
:
583 u32
*pal
= info
->pseudo_palette
;
585 val
= chan_to_field(red
, &info
->var
.red
);
586 val
|= chan_to_field(green
, &info
->var
.green
);
587 val
|= chan_to_field(blue
, &info
->var
.blue
);
598 static int fbtft_fb_blank(int blank
, struct fb_info
*info
)
600 struct fbtft_par
*par
= info
->par
;
603 dev_dbg(info
->dev
, "%s(blank=%d)\n",
606 if (!par
->fbtftops
.blank
)
610 case FB_BLANK_POWERDOWN
:
611 case FB_BLANK_VSYNC_SUSPEND
:
612 case FB_BLANK_HSYNC_SUSPEND
:
613 case FB_BLANK_NORMAL
:
614 ret
= par
->fbtftops
.blank(par
, true);
616 case FB_BLANK_UNBLANK
:
617 ret
= par
->fbtftops
.blank(par
, false);
623 static void fbtft_merge_fbtftops(struct fbtft_ops
*dst
, struct fbtft_ops
*src
)
626 dst
->write
= src
->write
;
628 dst
->read
= src
->read
;
630 dst
->write_vmem
= src
->write_vmem
;
631 if (src
->write_register
)
632 dst
->write_register
= src
->write_register
;
633 if (src
->set_addr_win
)
634 dst
->set_addr_win
= src
->set_addr_win
;
636 dst
->reset
= src
->reset
;
638 dst
->mkdirty
= src
->mkdirty
;
639 if (src
->update_display
)
640 dst
->update_display
= src
->update_display
;
641 if (src
->init_display
)
642 dst
->init_display
= src
->init_display
;
644 dst
->blank
= src
->blank
;
645 if (src
->request_gpios_match
)
646 dst
->request_gpios_match
= src
->request_gpios_match
;
647 if (src
->request_gpios
)
648 dst
->request_gpios
= src
->request_gpios
;
649 if (src
->verify_gpios
)
650 dst
->verify_gpios
= src
->verify_gpios
;
651 if (src
->register_backlight
)
652 dst
->register_backlight
= src
->register_backlight
;
653 if (src
->unregister_backlight
)
654 dst
->unregister_backlight
= src
->unregister_backlight
;
656 dst
->set_var
= src
->set_var
;
658 dst
->set_gamma
= src
->set_gamma
;
662 * fbtft_framebuffer_alloc - creates a new frame buffer info structure
664 * @display: pointer to structure describing the display
665 * @dev: pointer to the device for this fb, this can be NULL
667 * Creates a new frame buffer info structure.
669 * Also creates and populates the following structures:
672 * info->pseudo_palette
676 * Returns the new structure, or NULL if an error occurred.
679 struct fb_info
*fbtft_framebuffer_alloc(struct fbtft_display
*display
,
681 struct fbtft_platform_data
*pdata
)
683 struct fb_info
*info
;
684 struct fbtft_par
*par
;
685 struct fb_ops
*fbops
= NULL
;
686 struct fb_deferred_io
*fbdefio
= NULL
;
692 int txbuflen
= display
->txbuflen
;
693 unsigned bpp
= display
->bpp
;
694 unsigned fps
= display
->fps
;
696 int *init_sequence
= display
->init_sequence
;
697 char *gamma
= display
->gamma
;
698 unsigned long *gamma_curves
= NULL
;
701 if (display
->gamma_num
* display
->gamma_len
> FBTFT_GAMMA_MAX_VALUES_TOTAL
) {
702 dev_err(dev
, "FBTFT_GAMMA_MAX_VALUES_TOTAL=%d is exceeded\n",
703 FBTFT_GAMMA_MAX_VALUES_TOTAL
);
714 dev_err(dev
, "platform data is missing\n");
718 /* override driver values? */
722 txbuflen
= pdata
->txbuflen
;
723 if (pdata
->display
.init_sequence
)
724 init_sequence
= pdata
->display
.init_sequence
;
726 gamma
= pdata
->gamma
;
727 if (pdata
->display
.debug
)
728 display
->debug
= pdata
->display
.debug
;
729 if (pdata
->display
.backlight
)
730 display
->backlight
= pdata
->display
.backlight
;
731 if (pdata
->display
.width
)
732 display
->width
= pdata
->display
.width
;
733 if (pdata
->display
.height
)
734 display
->height
= pdata
->display
.height
;
735 if (pdata
->display
.buswidth
)
736 display
->buswidth
= pdata
->display
.buswidth
;
737 if (pdata
->display
.regwidth
)
738 display
->regwidth
= pdata
->display
.regwidth
;
740 display
->debug
|= debug
;
741 fbtft_expand_debug_value(&display
->debug
);
743 switch (pdata
->rotate
) {
746 width
= display
->height
;
747 height
= display
->width
;
750 width
= display
->width
;
751 height
= display
->height
;
754 vmem_size
= display
->width
* display
->height
* bpp
/ 8;
755 vmem
= vzalloc(vmem_size
);
759 fbops
= devm_kzalloc(dev
, sizeof(struct fb_ops
), GFP_KERNEL
);
763 fbdefio
= devm_kzalloc(dev
, sizeof(struct fb_deferred_io
), GFP_KERNEL
);
767 buf
= devm_kzalloc(dev
, 128, GFP_KERNEL
);
771 if (display
->gamma_num
&& display
->gamma_len
) {
772 gamma_curves
= devm_kzalloc(dev
, display
->gamma_num
* display
->gamma_len
* sizeof(gamma_curves
[0]),
778 info
= framebuffer_alloc(sizeof(struct fbtft_par
), dev
);
782 info
->screen_base
= (u8 __force __iomem
*)vmem
;
784 info
->fbdefio
= fbdefio
;
786 fbops
->owner
= dev
->driver
->owner
;
787 fbops
->fb_read
= fb_sys_read
;
788 fbops
->fb_write
= fbtft_fb_write
;
789 fbops
->fb_fillrect
= fbtft_fb_fillrect
;
790 fbops
->fb_copyarea
= fbtft_fb_copyarea
;
791 fbops
->fb_imageblit
= fbtft_fb_imageblit
;
792 fbops
->fb_setcolreg
= fbtft_fb_setcolreg
;
793 fbops
->fb_blank
= fbtft_fb_blank
;
795 fbdefio
->delay
= HZ
/fps
;
796 fbdefio
->deferred_io
= fbtft_deferred_io
;
797 fb_deferred_io_init(info
);
799 strncpy(info
->fix
.id
, dev
->driver
->name
, 16);
800 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
801 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
802 info
->fix
.xpanstep
= 0;
803 info
->fix
.ypanstep
= 0;
804 info
->fix
.ywrapstep
= 0;
805 info
->fix
.line_length
= width
*bpp
/8;
806 info
->fix
.accel
= FB_ACCEL_NONE
;
807 info
->fix
.smem_len
= vmem_size
;
809 info
->var
.rotate
= pdata
->rotate
;
810 info
->var
.xres
= width
;
811 info
->var
.yres
= height
;
812 info
->var
.xres_virtual
= info
->var
.xres
;
813 info
->var
.yres_virtual
= info
->var
.yres
;
814 info
->var
.bits_per_pixel
= bpp
;
815 info
->var
.nonstd
= 1;
818 info
->var
.red
.offset
= 11;
819 info
->var
.red
.length
= 5;
820 info
->var
.green
.offset
= 5;
821 info
->var
.green
.length
= 6;
822 info
->var
.blue
.offset
= 0;
823 info
->var
.blue
.length
= 5;
824 info
->var
.transp
.offset
= 0;
825 info
->var
.transp
.length
= 0;
827 info
->flags
= FBINFO_FLAG_DEFAULT
| FBINFO_VIRTFB
;
832 par
->debug
= display
->debug
;
834 spin_lock_init(&par
->dirty_lock
);
835 par
->bgr
= pdata
->bgr
;
836 par
->startbyte
= pdata
->startbyte
;
837 par
->init_sequence
= init_sequence
;
838 par
->gamma
.curves
= gamma_curves
;
839 par
->gamma
.num_curves
= display
->gamma_num
;
840 par
->gamma
.num_values
= display
->gamma_len
;
841 mutex_init(&par
->gamma
.lock
);
842 info
->pseudo_palette
= par
->pseudo_palette
;
844 if (par
->gamma
.curves
&& gamma
) {
845 if (fbtft_gamma_parse_str(par
,
846 par
->gamma
.curves
, gamma
, strlen(gamma
)))
850 /* Transmit buffer */
852 txbuflen
= vmem_size
+ 2; /* add in case startbyte is used */
854 #ifdef __LITTLE_ENDIAN
855 if ((!txbuflen
) && (bpp
> 8))
856 txbuflen
= PAGE_SIZE
; /* need buffer for byteswapping */
860 #ifdef CONFIG_HAS_DMA
862 dev
->coherent_dma_mask
= ~0;
863 txbuf
= dmam_alloc_coherent(dev
, txbuflen
, &par
->txbuf
.dma
, GFP_DMA
);
867 txbuf
= devm_kzalloc(par
->info
->device
, txbuflen
, GFP_KERNEL
);
871 par
->txbuf
.buf
= txbuf
;
872 par
->txbuf
.len
= txbuflen
;
875 /* Initialize gpios to disabled */
876 par
->gpio
.reset
= -1;
881 par
->gpio
.latch
= -1;
882 for (i
= 0; i
< 16; i
++) {
883 par
->gpio
.db
[i
] = -1;
884 par
->gpio
.led
[i
] = -1;
885 par
->gpio
.aux
[i
] = -1;
888 /* default fbtft operations */
889 par
->fbtftops
.write
= fbtft_write_spi
;
890 par
->fbtftops
.read
= fbtft_read_spi
;
891 par
->fbtftops
.write_vmem
= fbtft_write_vmem16_bus8
;
892 par
->fbtftops
.write_register
= fbtft_write_reg8_bus8
;
893 par
->fbtftops
.set_addr_win
= fbtft_set_addr_win
;
894 par
->fbtftops
.reset
= fbtft_reset
;
895 par
->fbtftops
.mkdirty
= fbtft_mkdirty
;
896 par
->fbtftops
.update_display
= fbtft_update_display
;
897 par
->fbtftops
.request_gpios
= fbtft_request_gpios
;
898 if (display
->backlight
)
899 par
->fbtftops
.register_backlight
= fbtft_register_backlight
;
901 /* use driver provided functions */
902 fbtft_merge_fbtftops(&par
->fbtftops
, &display
->fbtftops
);
911 EXPORT_SYMBOL(fbtft_framebuffer_alloc
);
914 * fbtft_framebuffer_release - frees up all memory used by the framebuffer
916 * @info: frame buffer info structure
919 void fbtft_framebuffer_release(struct fb_info
*info
)
921 fb_deferred_io_cleanup(info
);
922 vfree(info
->screen_base
);
923 framebuffer_release(info
);
925 EXPORT_SYMBOL(fbtft_framebuffer_release
);
928 * fbtft_register_framebuffer - registers a tft frame buffer device
929 * @fb_info: frame buffer info structure
931 * Sets SPI driverdata if needed
932 * Requests needed gpios.
933 * Initializes display
935 * Registers a frame buffer device @fb_info.
937 * Returns negative errno on error, or zero for success.
940 int fbtft_register_framebuffer(struct fb_info
*fb_info
)
945 struct fbtft_par
*par
= fb_info
->par
;
946 struct spi_device
*spi
= par
->spi
;
949 if (!par
->fbtftops
.init_display
) {
950 dev_err(fb_info
->device
, "missing fbtftops.init_display()\n");
955 spi_set_drvdata(spi
, fb_info
);
957 platform_set_drvdata(par
->pdev
, fb_info
);
959 ret
= par
->fbtftops
.request_gpios(par
);
963 if (par
->fbtftops
.verify_gpios
) {
964 ret
= par
->fbtftops
.verify_gpios(par
);
969 ret
= par
->fbtftops
.init_display(par
);
972 if (par
->fbtftops
.set_var
) {
973 ret
= par
->fbtftops
.set_var(par
);
978 /* update the entire display */
979 par
->fbtftops
.update_display(par
, 0, par
->info
->var
.yres
- 1);
981 if (par
->fbtftops
.set_gamma
&& par
->gamma
.curves
) {
982 ret
= par
->fbtftops
.set_gamma(par
, par
->gamma
.curves
);
987 if (par
->fbtftops
.register_backlight
)
988 par
->fbtftops
.register_backlight(par
);
990 ret
= register_framebuffer(fb_info
);
994 fbtft_sysfs_init(par
);
997 sprintf(text1
, ", %zu KiB %sbuffer memory",
998 par
->txbuf
.len
>> 10, par
->txbuf
.dma
? "DMA " : "");
1000 sprintf(text2
, ", spi%d.%d at %d MHz", spi
->master
->bus_num
,
1001 spi
->chip_select
, spi
->max_speed_hz
/1000000);
1002 dev_info(fb_info
->dev
,
1003 "%s frame buffer, %dx%d, %d KiB video memory%s, fps=%lu%s\n",
1004 fb_info
->fix
.id
, fb_info
->var
.xres
, fb_info
->var
.yres
,
1005 fb_info
->fix
.smem_len
>> 10, text1
,
1006 HZ
/fb_info
->fbdefio
->delay
, text2
);
1008 #ifdef CONFIG_FB_BACKLIGHT
1009 /* Turn on backlight if available */
1010 if (fb_info
->bl_dev
) {
1011 fb_info
->bl_dev
->props
.power
= FB_BLANK_UNBLANK
;
1012 fb_info
->bl_dev
->ops
->update_status(fb_info
->bl_dev
);
1019 if (par
->fbtftops
.unregister_backlight
)
1020 par
->fbtftops
.unregister_backlight(par
);
1022 spi_set_drvdata(spi
, NULL
);
1024 platform_set_drvdata(par
->pdev
, NULL
);
1028 EXPORT_SYMBOL(fbtft_register_framebuffer
);
1031 * fbtft_unregister_framebuffer - releases a tft frame buffer device
1032 * @fb_info: frame buffer info structure
1034 * Frees SPI driverdata if needed
1036 * Unregisters frame buffer device.
1039 int fbtft_unregister_framebuffer(struct fb_info
*fb_info
)
1041 struct fbtft_par
*par
= fb_info
->par
;
1042 struct spi_device
*spi
= par
->spi
;
1045 spi_set_drvdata(spi
, NULL
);
1047 platform_set_drvdata(par
->pdev
, NULL
);
1048 if (par
->fbtftops
.unregister_backlight
)
1049 par
->fbtftops
.unregister_backlight(par
);
1050 fbtft_sysfs_exit(par
);
1051 return unregister_framebuffer(fb_info
);
1053 EXPORT_SYMBOL(fbtft_unregister_framebuffer
);
1057 * fbtft_init_display_dt() - Device Tree init_display() function
1060 * Return: 0 if successful, negative if error
1062 static int fbtft_init_display_dt(struct fbtft_par
*par
)
1064 struct device_node
*node
= par
->info
->device
->of_node
;
1065 struct property
*prop
;
1070 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
, "%s()\n", __func__
);
1075 prop
= of_find_property(node
, "init", NULL
);
1076 p
= of_prop_next_u32(prop
, NULL
, &val
);
1080 par
->fbtftops
.reset(par
);
1081 if (par
->gpio
.cs
!= -1)
1082 gpio_set_value(par
->gpio
.cs
, 0); /* Activate chip */
1085 if (val
& FBTFT_OF_INIT_CMD
) {
1088 while (p
&& !(val
& 0xFFFF0000)) {
1090 dev_err(par
->info
->device
,
1091 "%s: Maximum register values exceeded\n",
1096 p
= of_prop_next_u32(prop
, p
, &val
);
1098 /* make debug message */
1099 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
,
1100 "init: write_register:\n");
1101 for (j
= 0; j
< i
; j
++)
1102 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
,
1103 "buf[%d] = %02X\n", j
, buf
[j
]);
1105 par
->fbtftops
.write_register(par
, i
,
1106 buf
[0], buf
[1], buf
[2], buf
[3],
1107 buf
[4], buf
[5], buf
[6], buf
[7],
1108 buf
[8], buf
[9], buf
[10], buf
[11],
1109 buf
[12], buf
[13], buf
[14], buf
[15],
1110 buf
[16], buf
[17], buf
[18], buf
[19],
1111 buf
[20], buf
[21], buf
[22], buf
[23],
1112 buf
[24], buf
[25], buf
[26], buf
[27],
1113 buf
[28], buf
[29], buf
[30], buf
[31],
1114 buf
[32], buf
[33], buf
[34], buf
[35],
1115 buf
[36], buf
[37], buf
[38], buf
[39],
1116 buf
[40], buf
[41], buf
[42], buf
[43],
1117 buf
[44], buf
[45], buf
[46], buf
[47],
1118 buf
[48], buf
[49], buf
[50], buf
[51],
1119 buf
[52], buf
[53], buf
[54], buf
[55],
1120 buf
[56], buf
[57], buf
[58], buf
[59],
1121 buf
[60], buf
[61], buf
[62], buf
[63]);
1122 } else if (val
& FBTFT_OF_INIT_DELAY
) {
1123 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
,
1124 "init: msleep(%u)\n", val
& 0xFFFF);
1125 msleep(val
& 0xFFFF);
1126 p
= of_prop_next_u32(prop
, p
, &val
);
1128 dev_err(par
->info
->device
, "illegal init value 0x%X\n",
1139 * fbtft_init_display() - Generic init_display() function
1142 * Uses par->init_sequence to do the initialization
1144 * Return: 0 if successful, negative if error
1146 int fbtft_init_display(struct fbtft_par
*par
)
1154 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
, "%s()\n", __func__
);
1157 if (!par
->init_sequence
) {
1158 dev_err(par
->info
->device
,
1159 "error: init_sequence is not set\n");
1163 /* make sure stop marker exists */
1164 for (i
= 0; i
< FBTFT_MAX_INIT_SEQUENCE
; i
++)
1165 if (par
->init_sequence
[i
] == -3)
1167 if (i
== FBTFT_MAX_INIT_SEQUENCE
) {
1168 dev_err(par
->info
->device
,
1169 "missing stop marker at end of init sequence\n");
1173 par
->fbtftops
.reset(par
);
1174 if (par
->gpio
.cs
!= -1)
1175 gpio_set_value(par
->gpio
.cs
, 0); /* Activate chip */
1178 while (i
< FBTFT_MAX_INIT_SEQUENCE
) {
1179 if (par
->init_sequence
[i
] == -3) {
1183 if (par
->init_sequence
[i
] >= 0) {
1184 dev_err(par
->info
->device
,
1185 "missing delimiter at position %d\n", i
);
1188 if (par
->init_sequence
[i
+1] < 0) {
1189 dev_err(par
->info
->device
,
1190 "missing value after delimiter %d at position %d\n",
1191 par
->init_sequence
[i
], i
);
1194 switch (par
->init_sequence
[i
]) {
1197 /* make debug message */
1200 while (par
->init_sequence
[j
] >= 0) {
1201 sprintf(str
, "0x%02X ", par
->init_sequence
[j
]);
1205 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
,
1206 "init: write(0x%02X) %s\n",
1207 par
->init_sequence
[i
], msg
);
1211 while (par
->init_sequence
[i
] >= 0) {
1213 dev_err(par
->info
->device
,
1214 "%s: Maximum register values exceeded\n",
1218 buf
[j
++] = par
->init_sequence
[i
++];
1220 par
->fbtftops
.write_register(par
, j
,
1221 buf
[0], buf
[1], buf
[2], buf
[3],
1222 buf
[4], buf
[5], buf
[6], buf
[7],
1223 buf
[8], buf
[9], buf
[10], buf
[11],
1224 buf
[12], buf
[13], buf
[14], buf
[15],
1225 buf
[16], buf
[17], buf
[18], buf
[19],
1226 buf
[20], buf
[21], buf
[22], buf
[23],
1227 buf
[24], buf
[25], buf
[26], buf
[27],
1228 buf
[28], buf
[29], buf
[30], buf
[31],
1229 buf
[32], buf
[33], buf
[34], buf
[35],
1230 buf
[36], buf
[37], buf
[38], buf
[39],
1231 buf
[40], buf
[41], buf
[42], buf
[43],
1232 buf
[44], buf
[45], buf
[46], buf
[47],
1233 buf
[48], buf
[49], buf
[50], buf
[51],
1234 buf
[52], buf
[53], buf
[54], buf
[55],
1235 buf
[56], buf
[57], buf
[58], buf
[59],
1236 buf
[60], buf
[61], buf
[62], buf
[63]);
1240 fbtft_par_dbg(DEBUG_INIT_DISPLAY
, par
,
1241 "init: mdelay(%d)\n", par
->init_sequence
[i
]);
1242 mdelay(par
->init_sequence
[i
++]);
1245 dev_err(par
->info
->device
,
1246 "unknown delimiter %d at position %d\n",
1247 par
->init_sequence
[i
], i
);
1252 dev_err(par
->info
->device
,
1253 "%s: something is wrong. Shouldn't get here.\n", __func__
);
1256 EXPORT_SYMBOL(fbtft_init_display
);
1259 * fbtft_verify_gpios() - Generic verify_gpios() function
1262 * Uses @spi, @pdev and @buswidth to determine which GPIOs is needed
1264 * Return: 0 if successful, negative if error
1266 static int fbtft_verify_gpios(struct fbtft_par
*par
)
1268 struct fbtft_platform_data
*pdata
= par
->pdata
;
1271 fbtft_par_dbg(DEBUG_VERIFY_GPIOS
, par
, "%s()\n", __func__
);
1273 if (pdata
->display
.buswidth
!= 9 && par
->startbyte
== 0 &&
1275 dev_err(par
->info
->device
,
1276 "Missing info about 'dc' gpio. Aborting.\n");
1283 if (par
->gpio
.wr
< 0) {
1284 dev_err(par
->info
->device
, "Missing 'wr' gpio. Aborting.\n");
1287 for (i
= 0; i
< pdata
->display
.buswidth
; i
++) {
1288 if (par
->gpio
.db
[i
] < 0) {
1289 dev_err(par
->info
->device
,
1290 "Missing 'db%02d' gpio. Aborting.\n", i
);
1299 /* returns 0 if the property is not present */
1300 static u32
fbtft_of_value(struct device_node
*node
, const char *propname
)
1305 ret
= of_property_read_u32(node
, propname
, &val
);
1307 pr_info("%s: %s = %u\n", __func__
, propname
, val
);
1312 static struct fbtft_platform_data
*fbtft_probe_dt(struct device
*dev
)
1314 struct device_node
*node
= dev
->of_node
;
1315 struct fbtft_platform_data
*pdata
;
1318 dev_err(dev
, "Missing platform data or DT\n");
1319 return ERR_PTR(-EINVAL
);
1322 pdata
= devm_kzalloc(dev
, sizeof(*pdata
), GFP_KERNEL
);
1324 return ERR_PTR(-ENOMEM
);
1326 pdata
->display
.width
= fbtft_of_value(node
, "width");
1327 pdata
->display
.height
= fbtft_of_value(node
, "height");
1328 pdata
->display
.regwidth
= fbtft_of_value(node
, "regwidth");
1329 pdata
->display
.buswidth
= fbtft_of_value(node
, "buswidth");
1330 pdata
->display
.backlight
= fbtft_of_value(node
, "backlight");
1331 pdata
->display
.bpp
= fbtft_of_value(node
, "bpp");
1332 pdata
->display
.debug
= fbtft_of_value(node
, "debug");
1333 pdata
->rotate
= fbtft_of_value(node
, "rotate");
1334 pdata
->bgr
= of_property_read_bool(node
, "bgr");
1335 pdata
->fps
= fbtft_of_value(node
, "fps");
1336 pdata
->txbuflen
= fbtft_of_value(node
, "txbuflen");
1337 pdata
->startbyte
= fbtft_of_value(node
, "startbyte");
1338 of_property_read_string(node
, "gamma", (const char **)&pdata
->gamma
);
1340 if (of_find_property(node
, "led-gpios", NULL
))
1341 pdata
->display
.backlight
= 1;
1342 if (of_find_property(node
, "init", NULL
))
1343 pdata
->display
.fbtftops
.init_display
= fbtft_init_display_dt
;
1344 pdata
->display
.fbtftops
.request_gpios
= fbtft_request_gpios_dt
;
1349 static struct fbtft_platform_data
*fbtft_probe_dt(struct device
*dev
)
1351 dev_err(dev
, "Missing platform data\n");
1352 return ERR_PTR(-EINVAL
);
1357 * fbtft_probe_common() - Generic device probe() helper function
1358 * @display: Display properties
1360 * @pdev: Platform device
1362 * Allocates, initializes and registers a framebuffer
1364 * Either @sdev or @pdev should be NULL
1366 * Return: 0 if successful, negative if error
1368 int fbtft_probe_common(struct fbtft_display
*display
,
1369 struct spi_device
*sdev
, struct platform_device
*pdev
)
1372 struct fb_info
*info
;
1373 struct fbtft_par
*par
;
1374 struct fbtft_platform_data
*pdata
;
1382 if (unlikely(display
->debug
& DEBUG_DRIVER_INIT_FUNCTIONS
))
1383 dev_info(dev
, "%s()\n", __func__
);
1385 pdata
= dev
->platform_data
;
1387 pdata
= fbtft_probe_dt(dev
);
1389 return PTR_ERR(pdata
);
1392 info
= fbtft_framebuffer_alloc(display
, dev
, pdata
);
1400 if (display
->buswidth
== 0) {
1401 dev_err(dev
, "buswidth is not set\n");
1405 /* write register functions */
1406 if (display
->regwidth
== 8 && display
->buswidth
== 8) {
1407 par
->fbtftops
.write_register
= fbtft_write_reg8_bus8
;
1409 if (display
->regwidth
== 8 && display
->buswidth
== 9 && par
->spi
) {
1410 par
->fbtftops
.write_register
= fbtft_write_reg8_bus9
;
1411 } else if (display
->regwidth
== 16 && display
->buswidth
== 8) {
1412 par
->fbtftops
.write_register
= fbtft_write_reg16_bus8
;
1413 } else if (display
->regwidth
== 16 && display
->buswidth
== 16) {
1414 par
->fbtftops
.write_register
= fbtft_write_reg16_bus16
;
1417 "no default functions for regwidth=%d and buswidth=%d\n",
1418 display
->regwidth
, display
->buswidth
);
1421 /* write_vmem() functions */
1422 if (display
->buswidth
== 8)
1423 par
->fbtftops
.write_vmem
= fbtft_write_vmem16_bus8
;
1424 else if (display
->buswidth
== 9)
1425 par
->fbtftops
.write_vmem
= fbtft_write_vmem16_bus9
;
1426 else if (display
->buswidth
== 16)
1427 par
->fbtftops
.write_vmem
= fbtft_write_vmem16_bus16
;
1429 /* GPIO write() functions */
1431 if (display
->buswidth
== 8)
1432 par
->fbtftops
.write
= fbtft_write_gpio8_wr
;
1433 else if (display
->buswidth
== 16)
1434 par
->fbtftops
.write
= fbtft_write_gpio16_wr
;
1437 /* 9-bit SPI setup */
1438 if (par
->spi
&& display
->buswidth
== 9) {
1439 par
->spi
->bits_per_word
= 9;
1440 ret
= par
->spi
->master
->setup(par
->spi
);
1442 dev_warn(&par
->spi
->dev
,
1443 "9-bit SPI not available, emulating using 8-bit.\n");
1444 par
->spi
->bits_per_word
= 8;
1445 ret
= par
->spi
->master
->setup(par
->spi
);
1448 /* allocate buffer with room for dc bits */
1449 par
->extra
= devm_kzalloc(par
->info
->device
,
1450 par
->txbuf
.len
+ (par
->txbuf
.len
/ 8) + 8,
1456 par
->fbtftops
.write
= fbtft_write_spi_emulate_9
;
1460 if (!par
->fbtftops
.verify_gpios
)
1461 par
->fbtftops
.verify_gpios
= fbtft_verify_gpios
;
1463 /* make sure we still use the driver provided functions */
1464 fbtft_merge_fbtftops(&par
->fbtftops
, &display
->fbtftops
);
1466 /* use init_sequence if provided */
1467 if (par
->init_sequence
)
1468 par
->fbtftops
.init_display
= fbtft_init_display
;
1470 /* use platform_data provided functions above all */
1471 fbtft_merge_fbtftops(&par
->fbtftops
, &pdata
->display
.fbtftops
);
1473 ret
= fbtft_register_framebuffer(info
);
1480 fbtft_framebuffer_release(info
);
1484 EXPORT_SYMBOL(fbtft_probe_common
);
1487 * fbtft_remove_common() - Generic device remove() helper function
1489 * @info: Framebuffer
1491 * Unregisters and releases the framebuffer
1493 * Return: 0 if successful, negative if error
1495 int fbtft_remove_common(struct device
*dev
, struct fb_info
*info
)
1497 struct fbtft_par
*par
;
1503 fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS
, par
,
1504 "%s()\n", __func__
);
1505 fbtft_unregister_framebuffer(info
);
1506 fbtft_framebuffer_release(info
);
1510 EXPORT_SYMBOL(fbtft_remove_common
);
1512 MODULE_LICENSE("GPL");