mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
2.6 KiB
95 lines
2.6 KiB
// SPDX-License-Identifier: GPL-2.0-only |
|
/* |
|
* framebuffer-coreboot.c |
|
* |
|
* Memory based framebuffer accessed through coreboot table. |
|
* |
|
* Copyright 2012-2013 David Herrmann <[email protected]> |
|
* Copyright 2017 Google Inc. |
|
* Copyright 2017 Samuel Holland <[email protected]> |
|
*/ |
|
|
|
#include <linux/device.h> |
|
#include <linux/kernel.h> |
|
#include <linux/mm.h> |
|
#include <linux/module.h> |
|
#include <linux/platform_data/simplefb.h> |
|
#include <linux/platform_device.h> |
|
|
|
#include "coreboot_table.h" |
|
|
|
#define CB_TAG_FRAMEBUFFER 0x12 |
|
|
|
static const struct simplefb_format formats[] = SIMPLEFB_FORMATS; |
|
|
|
static int framebuffer_probe(struct coreboot_device *dev) |
|
{ |
|
int i; |
|
u32 length; |
|
struct lb_framebuffer *fb = &dev->framebuffer; |
|
struct platform_device *pdev; |
|
struct resource res; |
|
struct simplefb_platform_data pdata = { |
|
.width = fb->x_resolution, |
|
.height = fb->y_resolution, |
|
.stride = fb->bytes_per_line, |
|
.format = NULL, |
|
}; |
|
|
|
for (i = 0; i < ARRAY_SIZE(formats); ++i) { |
|
if (fb->bits_per_pixel == formats[i].bits_per_pixel && |
|
fb->red_mask_pos == formats[i].red.offset && |
|
fb->red_mask_size == formats[i].red.length && |
|
fb->green_mask_pos == formats[i].green.offset && |
|
fb->green_mask_size == formats[i].green.length && |
|
fb->blue_mask_pos == formats[i].blue.offset && |
|
fb->blue_mask_size == formats[i].blue.length && |
|
fb->reserved_mask_pos == formats[i].transp.offset && |
|
fb->reserved_mask_size == formats[i].transp.length) |
|
pdata.format = formats[i].name; |
|
} |
|
if (!pdata.format) |
|
return -ENODEV; |
|
|
|
memset(&res, 0, sizeof(res)); |
|
res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; |
|
res.name = "Coreboot Framebuffer"; |
|
res.start = fb->physical_address; |
|
length = PAGE_ALIGN(fb->y_resolution * fb->bytes_per_line); |
|
res.end = res.start + length - 1; |
|
if (res.end <= res.start) |
|
return -EINVAL; |
|
|
|
pdev = platform_device_register_resndata(&dev->dev, |
|
"simple-framebuffer", 0, |
|
&res, 1, &pdata, |
|
sizeof(pdata)); |
|
if (IS_ERR(pdev)) |
|
pr_warn("coreboot: could not register framebuffer\n"); |
|
else |
|
dev_set_drvdata(&dev->dev, pdev); |
|
|
|
return PTR_ERR_OR_ZERO(pdev); |
|
} |
|
|
|
static int framebuffer_remove(struct coreboot_device *dev) |
|
{ |
|
struct platform_device *pdev = dev_get_drvdata(&dev->dev); |
|
|
|
platform_device_unregister(pdev); |
|
|
|
return 0; |
|
} |
|
|
|
static struct coreboot_driver framebuffer_driver = { |
|
.probe = framebuffer_probe, |
|
.remove = framebuffer_remove, |
|
.drv = { |
|
.name = "framebuffer", |
|
}, |
|
.tag = CB_TAG_FRAMEBUFFER, |
|
}; |
|
module_coreboot_driver(framebuffer_driver); |
|
|
|
MODULE_AUTHOR("Samuel Holland <[email protected]>"); |
|
MODULE_LICENSE("GPL");
|
|
|