2 * framebuffer-coreboot.c
4 * Memory based framebuffer accessed through coreboot table.
6 * Copyright 2012-2013 David Herrmann <dh.herrmann@gmail.com>
7 * Copyright 2017 Google Inc.
8 * Copyright 2017 Samuel Holland <samuel@sholland.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License v2.0 as published by
12 * the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
20 #include <linux/device.h>
21 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/platform_data/simplefb.h>
25 #include <linux/platform_device.h>
27 #include "coreboot_table.h"
29 #define CB_TAG_FRAMEBUFFER 0x12
31 static const struct simplefb_format formats
[] = SIMPLEFB_FORMATS
;
33 static int framebuffer_probe(struct coreboot_device
*dev
)
37 struct lb_framebuffer
*fb
= &dev
->framebuffer
;
38 struct platform_device
*pdev
;
40 struct simplefb_platform_data pdata
= {
41 .width
= fb
->x_resolution
,
42 .height
= fb
->y_resolution
,
43 .stride
= fb
->bytes_per_line
,
47 for (i
= 0; i
< ARRAY_SIZE(formats
); ++i
) {
48 if (fb
->bits_per_pixel
== formats
[i
].bits_per_pixel
&&
49 fb
->red_mask_pos
== formats
[i
].red
.offset
&&
50 fb
->red_mask_size
== formats
[i
].red
.length
&&
51 fb
->green_mask_pos
== formats
[i
].green
.offset
&&
52 fb
->green_mask_size
== formats
[i
].green
.length
&&
53 fb
->blue_mask_pos
== formats
[i
].blue
.offset
&&
54 fb
->blue_mask_size
== formats
[i
].blue
.length
&&
55 fb
->reserved_mask_pos
== formats
[i
].transp
.offset
&&
56 fb
->reserved_mask_size
== formats
[i
].transp
.length
)
57 pdata
.format
= formats
[i
].name
;
62 memset(&res
, 0, sizeof(res
));
63 res
.flags
= IORESOURCE_MEM
| IORESOURCE_BUSY
;
64 res
.name
= "Coreboot Framebuffer";
65 res
.start
= fb
->physical_address
;
66 length
= PAGE_ALIGN(fb
->y_resolution
* fb
->bytes_per_line
);
67 res
.end
= res
.start
+ length
- 1;
68 if (res
.end
<= res
.start
)
71 pdev
= platform_device_register_resndata(&dev
->dev
,
72 "simple-framebuffer", 0,
76 pr_warn("coreboot: could not register framebuffer\n");
78 dev_set_drvdata(&dev
->dev
, pdev
);
80 return PTR_ERR_OR_ZERO(pdev
);
83 static int framebuffer_remove(struct coreboot_device
*dev
)
85 struct platform_device
*pdev
= dev_get_drvdata(&dev
->dev
);
87 platform_device_unregister(pdev
);
92 static struct coreboot_driver framebuffer_driver
= {
93 .probe
= framebuffer_probe
,
94 .remove
= framebuffer_remove
,
96 .name
= "framebuffer",
98 .tag
= CB_TAG_FRAMEBUFFER
,
101 static int __init
coreboot_framebuffer_init(void)
103 return coreboot_driver_register(&framebuffer_driver
);
106 static void coreboot_framebuffer_exit(void)
108 coreboot_driver_unregister(&framebuffer_driver
);
111 module_init(coreboot_framebuffer_init
);
112 module_exit(coreboot_framebuffer_exit
);
114 MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
115 MODULE_LICENSE("GPL");