Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * framebuffer-coreboot.c
0004  *
0005  * Memory based framebuffer accessed through coreboot table.
0006  *
0007  * Copyright 2012-2013 David Herrmann <dh.herrmann@gmail.com>
0008  * Copyright 2017 Google Inc.
0009  * Copyright 2017 Samuel Holland <samuel@sholland.org>
0010  */
0011 
0012 #include <linux/device.h>
0013 #include <linux/kernel.h>
0014 #include <linux/mm.h>
0015 #include <linux/module.h>
0016 #include <linux/platform_data/simplefb.h>
0017 #include <linux/platform_device.h>
0018 
0019 #include "coreboot_table.h"
0020 
0021 #define CB_TAG_FRAMEBUFFER 0x12
0022 
0023 static const struct simplefb_format formats[] = SIMPLEFB_FORMATS;
0024 
0025 static int framebuffer_probe(struct coreboot_device *dev)
0026 {
0027     int i;
0028     u32 length;
0029     struct lb_framebuffer *fb = &dev->framebuffer;
0030     struct platform_device *pdev;
0031     struct resource res;
0032     struct simplefb_platform_data pdata = {
0033         .width = fb->x_resolution,
0034         .height = fb->y_resolution,
0035         .stride = fb->bytes_per_line,
0036         .format = NULL,
0037     };
0038 
0039     for (i = 0; i < ARRAY_SIZE(formats); ++i) {
0040         if (fb->bits_per_pixel     == formats[i].bits_per_pixel &&
0041             fb->red_mask_pos       == formats[i].red.offset &&
0042             fb->red_mask_size      == formats[i].red.length &&
0043             fb->green_mask_pos     == formats[i].green.offset &&
0044             fb->green_mask_size    == formats[i].green.length &&
0045             fb->blue_mask_pos      == formats[i].blue.offset &&
0046             fb->blue_mask_size     == formats[i].blue.length &&
0047             fb->reserved_mask_pos  == formats[i].transp.offset &&
0048             fb->reserved_mask_size == formats[i].transp.length)
0049             pdata.format = formats[i].name;
0050     }
0051     if (!pdata.format)
0052         return -ENODEV;
0053 
0054     memset(&res, 0, sizeof(res));
0055     res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
0056     res.name = "Coreboot Framebuffer";
0057     res.start = fb->physical_address;
0058     length = PAGE_ALIGN(fb->y_resolution * fb->bytes_per_line);
0059     res.end = res.start + length - 1;
0060     if (res.end <= res.start)
0061         return -EINVAL;
0062 
0063     pdev = platform_device_register_resndata(&dev->dev,
0064                          "simple-framebuffer", 0,
0065                          &res, 1, &pdata,
0066                          sizeof(pdata));
0067     if (IS_ERR(pdev))
0068         pr_warn("coreboot: could not register framebuffer\n");
0069     else
0070         dev_set_drvdata(&dev->dev, pdev);
0071 
0072     return PTR_ERR_OR_ZERO(pdev);
0073 }
0074 
0075 static void framebuffer_remove(struct coreboot_device *dev)
0076 {
0077     struct platform_device *pdev = dev_get_drvdata(&dev->dev);
0078 
0079     platform_device_unregister(pdev);
0080 }
0081 
0082 static struct coreboot_driver framebuffer_driver = {
0083     .probe = framebuffer_probe,
0084     .remove = framebuffer_remove,
0085     .drv = {
0086         .name = "framebuffer",
0087     },
0088     .tag = CB_TAG_FRAMEBUFFER,
0089 };
0090 module_coreboot_driver(framebuffer_driver);
0091 
0092 MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
0093 MODULE_LICENSE("GPL");