2 * Generic System Framebuffers on x86
3 * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
12 * simple-framebuffer probing
13 * Try to convert "screen_info" into a "simple-framebuffer" compatible mode.
14 * If the mode is incompatible, we return "false" and let the caller create
15 * legacy nodes instead.
18 #include <linux/err.h>
19 #include <linux/init.h>
20 #include <linux/kernel.h>
22 #include <linux/platform_data/simplefb.h>
23 #include <linux/platform_device.h>
24 #include <linux/screen_info.h>
25 #include <asm/sysfb.h>
27 static const char simplefb_resname
[] = "BOOTFB";
28 static const struct simplefb_format formats
[] = SIMPLEFB_FORMATS
;
30 /* try parsing x86 screen_info into a simple-framebuffer mode struct */
31 __init
bool parse_mode(const struct screen_info
*si
,
32 struct simplefb_platform_data
*mode
)
34 const struct simplefb_format
*f
;
38 type
= si
->orig_video_isVGA
;
39 if (type
!= VIDEO_TYPE_VLFB
&& type
!= VIDEO_TYPE_EFI
)
42 for (i
= 0; i
< ARRAY_SIZE(formats
); ++i
) {
44 if (si
->lfb_depth
== f
->bits_per_pixel
&&
45 si
->red_size
== f
->red
.length
&&
46 si
->red_pos
== f
->red
.offset
&&
47 si
->green_size
== f
->green
.length
&&
48 si
->green_pos
== f
->green
.offset
&&
49 si
->blue_size
== f
->blue
.length
&&
50 si
->blue_pos
== f
->blue
.offset
&&
51 si
->rsvd_size
== f
->transp
.length
&&
52 si
->rsvd_pos
== f
->transp
.offset
) {
53 mode
->format
= f
->name
;
54 mode
->width
= si
->lfb_width
;
55 mode
->height
= si
->lfb_height
;
56 mode
->stride
= si
->lfb_linelength
;
64 __init
int create_simplefb(const struct screen_info
*si
,
65 const struct simplefb_platform_data
*mode
)
67 struct platform_device
*pd
;
73 * If the 64BIT_BASE capability is set, ext_lfb_base will contain the
74 * upper half of the base address. Assemble the address, then make sure
75 * it is valid and we can actually access it.
78 if (si
->capabilities
& VIDEO_CAPABILITY_64BIT_BASE
)
79 base
|= (u64
)si
->ext_lfb_base
<< 32;
80 if (!base
|| (u64
)(resource_size_t
)base
!= base
) {
81 printk(KERN_DEBUG
"sysfb: inaccessible VRAM base\n");
86 * Don't use lfb_size as IORESOURCE size, since it may contain the
87 * entire VMEM, and thus require huge mappings. Use just the part we
88 * need, that is, the part where the framebuffer is located. But verify
89 * that it does not exceed the advertised VMEM.
90 * Note that in case of VBE, the lfb_size is shifted by 16 bits for
94 if (si
->orig_video_isVGA
== VIDEO_TYPE_VLFB
)
96 length
= mode
->height
* mode
->stride
;
97 length
= PAGE_ALIGN(length
);
99 printk(KERN_WARNING
"sysfb: VRAM smaller than advertised\n");
103 /* setup IORESOURCE_MEM as framebuffer memory */
104 memset(&res
, 0, sizeof(res
));
105 res
.flags
= IORESOURCE_MEM
| IORESOURCE_BUSY
;
106 res
.name
= simplefb_resname
;
108 res
.end
= res
.start
+ length
- 1;
109 if (res
.end
<= res
.start
)
112 pd
= platform_device_register_resndata(NULL
, "simple-framebuffer", 0,
113 &res
, 1, mode
, sizeof(*mode
));
114 return PTR_ERR_OR_ZERO(pd
);