2 * linux/drivers/video/bcm2708_fb.c
4 * Copyright (C) 2010 Broadcom
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
10 * Broadcom simple framebuffer driver
12 * This file is derived from cirrusfb.c
13 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/errno.h>
19 #include <linux/string.h>
20 #include <linux/slab.h>
23 #include <linux/init.h>
24 #include <linux/interrupt.h>
25 #include <linux/ioport.h>
26 #include <linux/list.h>
27 #include <linux/platform_data/dma-bcm2708.h>
28 #include <linux/platform_device.h>
29 #include <linux/clk.h>
30 #include <linux/printk.h>
31 #include <linux/console.h>
32 #include <linux/debugfs.h>
33 #include <asm/sizes.h>
35 #include <linux/dma-mapping.h>
36 #include <soc/bcm2835/raspberrypi-firmware.h>
38 //#define BCM2708_FB_DEBUG
39 #define MODULE_NAME "bcm2708_fb"
41 #ifdef BCM2708_FB_DEBUG
42 #define print_debug(fmt,...) pr_debug("%s:%s:%d: "fmt, MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)
44 #define print_debug(fmt,...)
47 /* This is limited to 16 characters when displayed by X startup */
48 static const char *bcm2708_name
= "BCM2708 FB";
50 #define DRIVER_NAME "bcm2708_fb"
52 static int fbwidth
= 800; /* module parameter */
53 static int fbheight
= 480; /* module parameter */
54 static int fbdepth
= 32; /* module parameter */
55 static int fbswap
= 0; /* module parameter */
57 static u32 dma_busy_wait_threshold
= 1<<15;
58 module_param(dma_busy_wait_threshold
, int, 0644);
59 MODULE_PARM_DESC(dma_busy_wait_threshold
, "Busy-wait for DMA completion below this area");
61 struct fb_alloc_tags
{
62 struct rpi_firmware_property_tag_header tag1
;
64 struct rpi_firmware_property_tag_header tag2
;
65 u32 xres_virtual
, yres_virtual
;
66 struct rpi_firmware_property_tag_header tag3
;
68 struct rpi_firmware_property_tag_header tag4
;
70 struct rpi_firmware_property_tag_header tag5
;
71 u32 base
, screen_size
;
72 struct rpi_firmware_property_tag_header tag6
;
76 struct bcm2708_fb_stats
{
77 struct debugfs_regset32 regset
;
84 struct platform_device
*dev
;
85 struct rpi_firmware
*fw
;
90 void __iomem
*dma_chan_base
;
91 void *cb_base
; /* DMA control blocks */
93 struct dentry
*debugfs_dir
;
94 wait_queue_head_t dma_waitq
;
95 struct bcm2708_fb_stats stats
;
96 unsigned long fb_bus_address
;
99 #define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb)
101 static void bcm2708_fb_debugfs_deinit(struct bcm2708_fb
*fb
)
103 debugfs_remove_recursive(fb
->debugfs_dir
);
104 fb
->debugfs_dir
= NULL
;
107 static int bcm2708_fb_debugfs_init(struct bcm2708_fb
*fb
)
109 static struct debugfs_reg32 stats_registers
[] = {
112 offsetof(struct bcm2708_fb_stats
, dma_copies
)
116 offsetof(struct bcm2708_fb_stats
, dma_irqs
)
120 fb
->debugfs_dir
= debugfs_create_dir(DRIVER_NAME
, NULL
);
121 if (!fb
->debugfs_dir
) {
122 pr_warn("%s: could not create debugfs entry\n",
127 fb
->stats
.regset
.regs
= stats_registers
;
128 fb
->stats
.regset
.nregs
= ARRAY_SIZE(stats_registers
);
129 fb
->stats
.regset
.base
= &fb
->stats
;
131 if (!debugfs_create_regset32(
132 "stats", 0444, fb
->debugfs_dir
, &fb
->stats
.regset
)) {
133 pr_warn("%s: could not create statistics registers\n",
140 bcm2708_fb_debugfs_deinit(fb
);
144 static int bcm2708_fb_set_bitfields(struct fb_var_screeninfo
*var
)
148 memset(&var
->transp
, 0, sizeof(var
->transp
));
150 var
->red
.msb_right
= 0;
151 var
->green
.msb_right
= 0;
152 var
->blue
.msb_right
= 0;
154 switch (var
->bits_per_pixel
) {
159 var
->red
.length
= var
->bits_per_pixel
;
161 var
->green
.length
= var
->bits_per_pixel
;
162 var
->green
.offset
= 0;
163 var
->blue
.length
= var
->bits_per_pixel
;
164 var
->blue
.offset
= 0;
168 var
->blue
.length
= 5;
170 * Green length can be 5 or 6 depending whether
171 * we're operating in RGB555 or RGB565 mode.
173 if (var
->green
.length
!= 5 && var
->green
.length
!= 6)
174 var
->green
.length
= 6;
178 var
->blue
.length
= 8;
179 var
->green
.length
= 8;
183 var
->green
.length
= 8;
184 var
->blue
.length
= 8;
185 var
->transp
.length
= 8;
193 * >= 16bpp displays have separate colour component bitfields
194 * encoded in the pixel data. Calculate their position from
195 * the bitfield length defined above.
197 if (ret
== 0 && var
->bits_per_pixel
>= 24 && fbswap
) {
198 var
->blue
.offset
= 0;
199 var
->green
.offset
= var
->blue
.offset
+ var
->blue
.length
;
200 var
->red
.offset
= var
->green
.offset
+ var
->green
.length
;
201 var
->transp
.offset
= var
->red
.offset
+ var
->red
.length
;
202 } else if (ret
== 0 && var
->bits_per_pixel
>= 24) {
204 var
->green
.offset
= var
->red
.offset
+ var
->red
.length
;
205 var
->blue
.offset
= var
->green
.offset
+ var
->green
.length
;
206 var
->transp
.offset
= var
->blue
.offset
+ var
->blue
.length
;
207 } else if (ret
== 0 && var
->bits_per_pixel
>= 16) {
208 var
->blue
.offset
= 0;
209 var
->green
.offset
= var
->blue
.offset
+ var
->blue
.length
;
210 var
->red
.offset
= var
->green
.offset
+ var
->green
.length
;
211 var
->transp
.offset
= var
->red
.offset
+ var
->red
.length
;
217 static int bcm2708_fb_check_var(struct fb_var_screeninfo
*var
,
218 struct fb_info
*info
)
220 /* info input, var output */
221 print_debug("bcm2708_fb_check_var info(%p) %dx%d (%dx%d), %d, %d\n", info
,
222 info
->var
.xres
, info
->var
.yres
, info
->var
.xres_virtual
,
223 info
->var
.yres_virtual
, (int)info
->screen_size
,
224 info
->var
.bits_per_pixel
);
225 print_debug("bcm2708_fb_check_var var(%p) %dx%d (%dx%d), %d\n", var
,
226 var
->xres
, var
->yres
, var
->xres_virtual
, var
->yres_virtual
,
227 var
->bits_per_pixel
);
229 if (!var
->bits_per_pixel
)
230 var
->bits_per_pixel
= 16;
232 if (bcm2708_fb_set_bitfields(var
) != 0) {
233 pr_err("bcm2708_fb_check_var: invalid bits_per_pixel %d\n",
234 var
->bits_per_pixel
);
239 if (var
->xres_virtual
< var
->xres
)
240 var
->xres_virtual
= var
->xres
;
241 /* use highest possible virtual resolution */
242 if (var
->yres_virtual
== -1) {
243 var
->yres_virtual
= 480;
246 ("bcm2708_fb_check_var: virtual resolution set to maximum of %dx%d\n",
247 var
->xres_virtual
, var
->yres_virtual
);
249 if (var
->yres_virtual
< var
->yres
)
250 var
->yres_virtual
= var
->yres
;
252 if (var
->xoffset
< 0)
254 if (var
->yoffset
< 0)
257 /* truncate xoffset and yoffset to maximum if too high */
258 if (var
->xoffset
> var
->xres_virtual
- var
->xres
)
259 var
->xoffset
= var
->xres_virtual
- var
->xres
- 1;
260 if (var
->yoffset
> var
->yres_virtual
- var
->yres
)
261 var
->yoffset
= var
->yres_virtual
- var
->yres
- 1;
266 static int bcm2708_fb_set_par(struct fb_info
*info
)
268 struct bcm2708_fb
*fb
= to_bcm2708(info
);
269 struct fb_alloc_tags fbinfo
= {
270 .tag1
= { RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT
,
272 .xres
= info
->var
.xres
,
273 .yres
= info
->var
.yres
,
274 .tag2
= { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT
,
276 .xres_virtual
= info
->var
.xres_virtual
,
277 .yres_virtual
= info
->var
.yres_virtual
,
278 .tag3
= { RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH
, 4, 0 },
279 .bpp
= info
->var
.bits_per_pixel
,
280 .tag4
= { RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET
, 8, 0 },
281 .xoffset
= info
->var
.xoffset
,
282 .yoffset
= info
->var
.yoffset
,
283 .tag5
= { RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE
, 8, 0 },
286 .tag6
= { RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH
, 4, 0 },
291 print_debug("bcm2708_fb_set_par info(%p) %dx%d (%dx%d), %d, %d\n", info
,
292 info
->var
.xres
, info
->var
.yres
, info
->var
.xres_virtual
,
293 info
->var
.yres_virtual
, (int)info
->screen_size
,
294 info
->var
.bits_per_pixel
);
296 ret
= rpi_firmware_property_list(fb
->fw
, &fbinfo
, sizeof(fbinfo
));
298 dev_err(info
->device
,
299 "Failed to allocate GPU framebuffer (%d)\n", ret
);
303 if (info
->var
.bits_per_pixel
<= 8)
304 fb
->fb
.fix
.visual
= FB_VISUAL_PSEUDOCOLOR
;
306 fb
->fb
.fix
.visual
= FB_VISUAL_TRUECOLOR
;
308 fb
->fb
.fix
.line_length
= fbinfo
.pitch
;
309 fbinfo
.base
|= 0x40000000;
310 fb
->fb_bus_address
= fbinfo
.base
;
311 fbinfo
.base
&= ~0xc0000000;
312 fb
->fb
.fix
.smem_start
= fbinfo
.base
;
313 fb
->fb
.fix
.smem_len
= fbinfo
.pitch
* fbinfo
.yres_virtual
;
314 fb
->fb
.screen_size
= fbinfo
.screen_size
;
315 if (fb
->fb
.screen_base
)
316 iounmap(fb
->fb
.screen_base
);
317 fb
->fb
.screen_base
= ioremap_wc(fbinfo
.base
, fb
->fb
.screen_size
);
318 if (!fb
->fb
.screen_base
) {
319 /* the console may currently be locked */
322 dev_err(info
->device
, "Failed to set screen_base\n");
327 ("BCM2708FB: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d\n",
328 (void *)fb
->fb
.screen_base
, (void *)fb
->fb_bus_address
,
329 fbinfo
.xres
, fbinfo
.yres
, fbinfo
.bpp
,
330 fbinfo
.pitch
, (int)fb
->fb
.screen_size
);
335 static inline u32
convert_bitfield(int val
, struct fb_bitfield
*bf
)
337 unsigned int mask
= (1 << bf
->length
) - 1;
339 return (val
>> (16 - bf
->length
) & mask
) << bf
->offset
;
343 static int bcm2708_fb_setcolreg(unsigned int regno
, unsigned int red
,
344 unsigned int green
, unsigned int blue
,
345 unsigned int transp
, struct fb_info
*info
)
347 struct bcm2708_fb
*fb
= to_bcm2708(info
);
349 /*print_debug("BCM2708FB: setcolreg %d:(%02x,%02x,%02x,%02x) %x\n", regno, red, green, blue, transp, fb->fb.fix.visual);*/
350 if (fb
->fb
.var
.bits_per_pixel
<= 8) {
352 /* blue [23:16], green [15:8], red [7:0] */
353 fb
->gpu_cmap
[regno
] = ((red
>> 8) & 0xff) << 0 |
354 ((green
>> 8) & 0xff) << 8 |
355 ((blue
>> 8) & 0xff) << 16;
357 /* Hack: we need to tell GPU the palette has changed, but currently bcm2708_fb_set_par takes noticable time when called for every (256) colour */
358 /* So just call it for what looks like the last colour in a list for now. */
359 if (regno
== 15 || regno
== 255) {
367 packet
= kmalloc(sizeof(*packet
), GFP_KERNEL
);
371 packet
->length
= regno
+ 1;
372 memcpy(packet
->cmap
, fb
->gpu_cmap
, sizeof(packet
->cmap
));
373 ret
= rpi_firmware_property(fb
->fw
, RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE
,
374 packet
, (2 + packet
->length
) * sizeof(u32
));
375 if (ret
|| packet
->offset
)
376 dev_err(info
->device
, "Failed to set palette (%d,%u)\n",
377 ret
, packet
->offset
);
380 } else if (regno
< 16) {
381 fb
->cmap
[regno
] = convert_bitfield(transp
, &fb
->fb
.var
.transp
) |
382 convert_bitfield(blue
, &fb
->fb
.var
.blue
) |
383 convert_bitfield(green
, &fb
->fb
.var
.green
) |
384 convert_bitfield(red
, &fb
->fb
.var
.red
);
389 static int bcm2708_fb_blank(int blank_mode
, struct fb_info
*info
)
391 struct bcm2708_fb
*fb
= to_bcm2708(info
);
395 switch (blank_mode
) {
396 case FB_BLANK_UNBLANK
:
399 case FB_BLANK_NORMAL
:
400 case FB_BLANK_VSYNC_SUSPEND
:
401 case FB_BLANK_HSYNC_SUSPEND
:
402 case FB_BLANK_POWERDOWN
:
409 ret
= rpi_firmware_property(fb
->fw
, RPI_FIRMWARE_FRAMEBUFFER_BLANK
,
410 &value
, sizeof(value
));
412 dev_err(info
->device
, "bcm2708_fb_blank(%d) failed: %d\n",
418 static int bcm2708_fb_pan_display(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
421 info
->var
.xoffset
= var
->xoffset
;
422 info
->var
.yoffset
= var
->yoffset
;
423 result
= bcm2708_fb_set_par(info
);
425 pr_err("bcm2708_fb_pan_display(%d,%d) returns=%d\n", var
->xoffset
, var
->yoffset
, result
);
429 static int bcm2708_ioctl(struct fb_info
*info
, unsigned int cmd
, unsigned long arg
)
431 struct bcm2708_fb
*fb
= to_bcm2708(info
);
436 case FBIO_WAITFORVSYNC
:
437 ret
= rpi_firmware_property(fb
->fw
,
438 RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC
,
439 &dummy
, sizeof(dummy
));
442 dev_dbg(info
->device
, "Unknown ioctl 0x%x\n", cmd
);
447 dev_err(info
->device
, "ioctl 0x%x failed (%d)\n", cmd
, ret
);
451 static void bcm2708_fb_fillrect(struct fb_info
*info
,
452 const struct fb_fillrect
*rect
)
454 /* (is called) print_debug("bcm2708_fb_fillrect\n"); */
455 cfb_fillrect(info
, rect
);
458 /* A helper function for configuring dma control block */
459 static void set_dma_cb(struct bcm2708_dma_cb
*cb
,
468 cb
->info
= BCM2708_DMA_BURST(burst_size
) | BCM2708_DMA_S_WIDTH
|
469 BCM2708_DMA_S_INC
| BCM2708_DMA_D_WIDTH
|
470 BCM2708_DMA_D_INC
| BCM2708_DMA_TDMODE
;
474 * This is not really obvious from the DMA documentation,
475 * but the top 16 bits must be programmmed to "height -1"
476 * and not "height" in 2D mode.
478 cb
->length
= ((h
- 1) << 16) | w
;
479 cb
->stride
= ((dst_stride
- w
) << 16) | (u16
)(src_stride
- w
);
484 static void bcm2708_fb_copyarea(struct fb_info
*info
,
485 const struct fb_copyarea
*region
)
487 struct bcm2708_fb
*fb
= to_bcm2708(info
);
488 struct bcm2708_dma_cb
*cb
= fb
->cb_base
;
489 int bytes_per_pixel
= (info
->var
.bits_per_pixel
+ 7) >> 3;
490 /* Channel 0 supports larger bursts and is a bit faster */
491 int burst_size
= (fb
->dma_chan
== 0) ? 8 : 2;
492 int pixels
= region
->width
* region
->height
;
494 /* Fallback to cfb_copyarea() if we don't like something */
496 bytes_per_pixel
> 4 ||
497 info
->var
.xres
* info
->var
.yres
> 1920 * 1200 ||
498 region
->width
<= 0 || region
->width
> info
->var
.xres
||
499 region
->height
<= 0 || region
->height
> info
->var
.yres
||
500 region
->sx
< 0 || region
->sx
>= info
->var
.xres
||
501 region
->sy
< 0 || region
->sy
>= info
->var
.yres
||
502 region
->dx
< 0 || region
->dx
>= info
->var
.xres
||
503 region
->dy
< 0 || region
->dy
>= info
->var
.yres
||
504 region
->sx
+ region
->width
> info
->var
.xres
||
505 region
->dx
+ region
->width
> info
->var
.xres
||
506 region
->sy
+ region
->height
> info
->var
.yres
||
507 region
->dy
+ region
->height
> info
->var
.yres
) {
508 cfb_copyarea(info
, region
);
512 if (region
->dy
== region
->sy
&& region
->dx
> region
->sx
) {
514 * A difficult case of overlapped copy. Because DMA can't
515 * copy individual scanlines in backwards direction, we need
516 * two-pass processing. We do it by programming a chain of dma
517 * control blocks in the first 16K part of the buffer and use
518 * the remaining 48K as the intermediate temporary scratch
519 * buffer. The buffer size is sufficient to handle up to
520 * 1920x1200 resolution at 32bpp pixel depth.
523 dma_addr_t control_block_pa
= fb
->cb_handle
;
524 dma_addr_t scratchbuf
= fb
->cb_handle
+ 16 * 1024;
525 int scanline_size
= bytes_per_pixel
* region
->width
;
526 int scanlines_per_cb
= (64 * 1024 - 16 * 1024) / scanline_size
;
528 for (y
= 0; y
< region
->height
; y
+= scanlines_per_cb
) {
531 bytes_per_pixel
* region
->sx
+
532 (region
->sy
+ y
) * fb
->fb
.fix
.line_length
;
535 bytes_per_pixel
* region
->dx
+
536 (region
->dy
+ y
) * fb
->fb
.fix
.line_length
;
538 if (region
->height
- y
< scanlines_per_cb
)
539 scanlines_per_cb
= region
->height
- y
;
541 set_dma_cb(cb
, burst_size
, scratchbuf
, scanline_size
,
542 src
, fb
->fb
.fix
.line_length
,
543 scanline_size
, scanlines_per_cb
);
544 control_block_pa
+= sizeof(struct bcm2708_dma_cb
);
545 cb
->next
= control_block_pa
;
548 set_dma_cb(cb
, burst_size
, dst
, fb
->fb
.fix
.line_length
,
549 scratchbuf
, scanline_size
,
550 scanline_size
, scanlines_per_cb
);
551 control_block_pa
+= sizeof(struct bcm2708_dma_cb
);
552 cb
->next
= control_block_pa
;
555 /* move the pointer back to the last dma control block */
558 /* A single dma control block is enough. */
560 if (region
->dy
<= region
->sy
) {
561 /* processing from top to bottom */
564 stride
= fb
->fb
.fix
.line_length
;
566 /* processing from bottom to top */
567 dy
= region
->dy
+ region
->height
- 1;
568 sy
= region
->sy
+ region
->height
- 1;
569 stride
= -fb
->fb
.fix
.line_length
;
571 set_dma_cb(cb
, burst_size
,
572 fb
->fb_bus_address
+ dy
* fb
->fb
.fix
.line_length
+
573 bytes_per_pixel
* region
->dx
,
575 fb
->fb_bus_address
+ sy
* fb
->fb
.fix
.line_length
+
576 bytes_per_pixel
* region
->sx
,
578 region
->width
* bytes_per_pixel
,
582 /* end of dma control blocks chain */
586 if (pixels
< dma_busy_wait_threshold
) {
587 bcm_dma_start(fb
->dma_chan_base
, fb
->cb_handle
);
588 bcm_dma_wait_idle(fb
->dma_chan_base
);
590 void __iomem
*dma_chan
= fb
->dma_chan_base
;
591 cb
->info
|= BCM2708_DMA_INT_EN
;
592 bcm_dma_start(fb
->dma_chan_base
, fb
->cb_handle
);
593 while (bcm_dma_is_busy(dma_chan
)) {
594 wait_event_interruptible(
596 !bcm_dma_is_busy(dma_chan
));
598 fb
->stats
.dma_irqs
++;
600 fb
->stats
.dma_copies
++;
603 static void bcm2708_fb_imageblit(struct fb_info
*info
,
604 const struct fb_image
*image
)
606 /* (is called) print_debug("bcm2708_fb_imageblit\n"); */
607 cfb_imageblit(info
, image
);
610 static irqreturn_t
bcm2708_fb_dma_irq(int irq
, void *cxt
)
612 struct bcm2708_fb
*fb
= cxt
;
614 /* FIXME: should read status register to check if this is
615 * actually interrupting us or not, in case this interrupt
616 * ever becomes shared amongst several DMA channels
618 * readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_IRQ;
621 /* acknowledge the interrupt */
622 writel(BCM2708_DMA_INT
, fb
->dma_chan_base
+ BCM2708_DMA_CS
);
624 wake_up(&fb
->dma_waitq
);
628 static struct fb_ops bcm2708_fb_ops
= {
629 .owner
= THIS_MODULE
,
630 .fb_check_var
= bcm2708_fb_check_var
,
631 .fb_set_par
= bcm2708_fb_set_par
,
632 .fb_setcolreg
= bcm2708_fb_setcolreg
,
633 .fb_blank
= bcm2708_fb_blank
,
634 .fb_fillrect
= bcm2708_fb_fillrect
,
635 .fb_copyarea
= bcm2708_fb_copyarea
,
636 .fb_imageblit
= bcm2708_fb_imageblit
,
637 .fb_pan_display
= bcm2708_fb_pan_display
,
638 .fb_ioctl
= bcm2708_ioctl
,
641 static int bcm2708_fb_register(struct bcm2708_fb
*fb
)
645 fb
->fb
.fbops
= &bcm2708_fb_ops
;
646 fb
->fb
.flags
= FBINFO_FLAG_DEFAULT
| FBINFO_HWACCEL_COPYAREA
;
647 fb
->fb
.pseudo_palette
= fb
->cmap
;
649 strncpy(fb
->fb
.fix
.id
, bcm2708_name
, sizeof(fb
->fb
.fix
.id
));
650 fb
->fb
.fix
.type
= FB_TYPE_PACKED_PIXELS
;
651 fb
->fb
.fix
.type_aux
= 0;
652 fb
->fb
.fix
.xpanstep
= 1;
653 fb
->fb
.fix
.ypanstep
= 1;
654 fb
->fb
.fix
.ywrapstep
= 0;
655 fb
->fb
.fix
.accel
= FB_ACCEL_NONE
;
657 fb
->fb
.var
.xres
= fbwidth
;
658 fb
->fb
.var
.yres
= fbheight
;
659 fb
->fb
.var
.xres_virtual
= fbwidth
;
660 fb
->fb
.var
.yres_virtual
= fbheight
;
661 fb
->fb
.var
.bits_per_pixel
= fbdepth
;
662 fb
->fb
.var
.vmode
= FB_VMODE_NONINTERLACED
;
663 fb
->fb
.var
.activate
= FB_ACTIVATE_NOW
;
664 fb
->fb
.var
.nonstd
= 0;
665 fb
->fb
.var
.height
= -1; /* height of picture in mm */
666 fb
->fb
.var
.width
= -1; /* width of picture in mm */
667 fb
->fb
.var
.accel_flags
= 0;
669 fb
->fb
.monspecs
.hfmin
= 0;
670 fb
->fb
.monspecs
.hfmax
= 100000;
671 fb
->fb
.monspecs
.vfmin
= 0;
672 fb
->fb
.monspecs
.vfmax
= 400;
673 fb
->fb
.monspecs
.dclkmin
= 1000000;
674 fb
->fb
.monspecs
.dclkmax
= 100000000;
676 bcm2708_fb_set_bitfields(&fb
->fb
.var
);
677 init_waitqueue_head(&fb
->dma_waitq
);
680 * Allocate colourmap.
683 fb_set_var(&fb
->fb
, &fb
->fb
.var
);
684 ret
= bcm2708_fb_set_par(&fb
->fb
);
688 print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n", fbwidth
,
689 fbheight
, fbdepth
, fbswap
);
691 ret
= register_framebuffer(&fb
->fb
);
692 print_debug("BCM2708FB: register framebuffer (%d)\n", ret
);
696 print_debug("BCM2708FB: cannot register framebuffer (%d)\n", ret
);
701 static int bcm2708_fb_probe(struct platform_device
*dev
)
703 struct device_node
*fw_np
;
704 struct rpi_firmware
*fw
;
705 struct bcm2708_fb
*fb
;
708 fw_np
= of_parse_phandle(dev
->dev
.of_node
, "firmware", 0);
709 /* Remove comment when booting without Device Tree is no longer supported
711 dev_err(&dev->dev, "Missing firmware node\n");
715 fw
= rpi_firmware_get(fw_np
);
717 return -EPROBE_DEFER
;
719 fb
= kzalloc(sizeof(struct bcm2708_fb
), GFP_KERNEL
);
722 "could not allocate new bcm2708_fb struct\n");
728 bcm2708_fb_debugfs_init(fb
);
730 fb
->cb_base
= dma_alloc_writecombine(&dev
->dev
, SZ_64K
,
731 &fb
->cb_handle
, GFP_KERNEL
);
733 dev_err(&dev
->dev
, "cannot allocate DMA CBs\n");
738 pr_info("BCM2708FB: allocated DMA memory %08x\n",
741 ret
= bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK
,
742 &fb
->dma_chan_base
, &fb
->dma_irq
);
744 dev_err(&dev
->dev
, "couldn't allocate a DMA channel\n");
749 ret
= request_irq(fb
->dma_irq
, bcm2708_fb_dma_irq
,
750 0, "bcm2708_fb dma", fb
);
752 pr_err("%s: failed to request DMA irq\n", __func__
);
757 pr_info("BCM2708FB: allocated DMA channel %d @ %p\n",
758 fb
->dma_chan
, fb
->dma_chan_base
);
761 fb
->fb
.device
= &dev
->dev
;
763 ret
= bcm2708_fb_register(fb
);
765 platform_set_drvdata(dev
, fb
);
770 bcm_dma_chan_free(fb
->dma_chan
);
772 dma_free_writecombine(&dev
->dev
, SZ_64K
, fb
->cb_base
, fb
->cb_handle
);
776 dev_err(&dev
->dev
, "probe failed, err %d\n", ret
);
781 static int bcm2708_fb_remove(struct platform_device
*dev
)
783 struct bcm2708_fb
*fb
= platform_get_drvdata(dev
);
785 platform_set_drvdata(dev
, NULL
);
787 if (fb
->fb
.screen_base
)
788 iounmap(fb
->fb
.screen_base
);
789 unregister_framebuffer(&fb
->fb
);
791 dma_free_writecombine(&dev
->dev
, SZ_64K
, fb
->cb_base
, fb
->cb_handle
);
792 bcm_dma_chan_free(fb
->dma_chan
);
794 bcm2708_fb_debugfs_deinit(fb
);
796 free_irq(fb
->dma_irq
, fb
);
803 static const struct of_device_id bcm2708_fb_of_match_table
[] = {
804 { .compatible
= "brcm,bcm2708-fb", },
807 MODULE_DEVICE_TABLE(of
, bcm2708_fb_of_match_table
);
809 static struct platform_driver bcm2708_fb_driver
= {
810 .probe
= bcm2708_fb_probe
,
811 .remove
= bcm2708_fb_remove
,
814 .owner
= THIS_MODULE
,
815 .of_match_table
= bcm2708_fb_of_match_table
,
819 static int __init
bcm2708_fb_init(void)
821 return platform_driver_register(&bcm2708_fb_driver
);
824 module_init(bcm2708_fb_init
);
826 static void __exit
bcm2708_fb_exit(void)
828 platform_driver_unregister(&bcm2708_fb_driver
);
831 module_exit(bcm2708_fb_exit
);
833 module_param(fbwidth
, int, 0644);
834 module_param(fbheight
, int, 0644);
835 module_param(fbdepth
, int, 0644);
836 module_param(fbswap
, int, 0644);
838 MODULE_DESCRIPTION("BCM2708 framebuffer driver");
839 MODULE_LICENSE("GPL");
841 MODULE_PARM_DESC(fbwidth
, "Width of ARM Framebuffer");
842 MODULE_PARM_DESC(fbheight
, "Height of ARM Framebuffer");
843 MODULE_PARM_DESC(fbdepth
, "Bit depth of ARM Framebuffer");
844 MODULE_PARM_DESC(fbswap
, "Swap order of red and blue in 24 and 32 bit modes");