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 fb->reserved_mask_pos == formats[i].transp.offset && 48 fb->reserved_mask_size == formats[i].transp.length) 49 pdata.format = formats[i].name; 50 } 51 if (!pdata.format) 52 return -ENODEV; 53 54 memset(&res, 0, sizeof(res)); 55 res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; 56 res.name = "Coreboot Framebuffer"; 57 res.start = fb->physical_address; 58 length = PAGE_ALIGN(fb->y_resolution * fb->bytes_per_line); 59 res.end = res.start + length - 1; 60 if (res.end <= res.start) 61 return -EINVAL; 62 63 pdev = platform_device_register_resndata(&dev->dev, 64 "simple-framebuffer", 0, 65 &res, 1, &pdata, 66 sizeof(pdata)); 67 if (IS_ERR(pdev)) 68 pr_warn("coreboot: could not register framebuffer\n"); 69 else 70 dev_set_drvdata(&dev->dev, pdev); 71 72 return PTR_ERR_OR_ZERO(pdev); 73 } 74 75 static int framebuffer_remove(struct coreboot_device *dev) 76 { 77 struct platform_device *pdev = dev_get_drvdata(&dev->dev); 78 79 platform_device_unregister(pdev); 80 81 return 0; 82 } 83 84 static struct coreboot_driver framebuffer_driver = { 85 .probe = framebuffer_probe, 86 .remove = framebuffer_remove, 87 .drv = { 88 .name = "framebuffer", 89 }, 90 .tag = CB_TAG_FRAMEBUFFER, 91 }; 92 module_coreboot_driver(framebuffer_driver); 93 94 MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>"); 95 MODULE_LICENSE("GPL"); 96