1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * framebuffer-coreboot.c 4 * 5 * Memory based framebuffer accessed through coreboot table. 6 * 7 * Copyright 2012-2013 David Herrmann <dh.herrmann@gmail.com> 8 * Copyright 2017 Google Inc. 9 * Copyright 2017 Samuel Holland <samuel@sholland.org> 10 */ 11 12 #include <linux/device.h> 13 #include <linux/kernel.h> 14 #include <linux/mm.h> 15 #include <linux/module.h> 16 #include <linux/platform_data/simplefb.h> 17 #include <linux/platform_device.h> 18 19 #include "coreboot_table.h" 20 21 #define CB_TAG_FRAMEBUFFER 0x12 22 23 static const struct simplefb_format formats[] = SIMPLEFB_FORMATS; 24 25 static int framebuffer_probe(struct coreboot_device *dev) 26 { 27 int i; 28 u32 length; 29 struct lb_framebuffer *fb = &dev->framebuffer; 30 struct platform_device *pdev; 31 struct resource res; 32 struct simplefb_platform_data pdata = { 33 .width = fb->x_resolution, 34 .height = fb->y_resolution, 35 .stride = fb->bytes_per_line, 36 .format = NULL, 37 }; 38 39 for (i = 0; i < ARRAY_SIZE(formats); ++i) { 40 if (fb->bits_per_pixel == formats[i].bits_per_pixel && 41 fb->red_mask_pos == formats[i].red.offset && 42 fb->red_mask_size == formats[i].red.length && 43 fb->green_mask_pos == formats[i].green.offset && 44 fb->green_mask_size == formats[i].green.length && 45 fb->blue_mask_pos == formats[i].blue.offset && 46 fb->blue_mask_size == formats[i].blue.length) 47 pdata.format = formats[i].name; 48 } 49 if (!pdata.format) 50 return -ENODEV; 51 52 memset(&res, 0, sizeof(res)); 53 res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; 54 res.name = "Coreboot Framebuffer"; 55 res.start = fb->physical_address; 56 length = PAGE_ALIGN(fb->y_resolution * fb->bytes_per_line); 57 res.end = res.start + length - 1; 58 if (res.end <= res.start) 59 return -EINVAL; 60 61 pdev = platform_device_register_resndata(&dev->dev, 62 "simple-framebuffer", 0, 63 &res, 1, &pdata, 64 sizeof(pdata)); 65 if (IS_ERR(pdev)) 66 pr_warn("coreboot: could not register framebuffer\n"); 67 else 68 dev_set_drvdata(&dev->dev, pdev); 69 70 return PTR_ERR_OR_ZERO(pdev); 71 } 72 73 static void framebuffer_remove(struct coreboot_device *dev) 74 { 75 struct platform_device *pdev = dev_get_drvdata(&dev->dev); 76 77 platform_device_unregister(pdev); 78 } 79 80 static struct coreboot_driver framebuffer_driver = { 81 .probe = framebuffer_probe, 82 .remove = framebuffer_remove, 83 .drv = { 84 .name = "framebuffer", 85 }, 86 .tag = CB_TAG_FRAMEBUFFER, 87 }; 88 module_coreboot_driver(framebuffer_driver); 89 90 MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>"); 91 MODULE_LICENSE("GPL"); 92