framebuffer-coreboot.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * framebuffer-coreboot.c
  3. *
  4. * Memory based framebuffer accessed through coreboot table.
  5. *
  6. * Copyright 2012-2013 David Herrmann <dh.herrmann@gmail.com>
  7. * Copyright 2017 Google Inc.
  8. * Copyright 2017 Samuel Holland <samuel@sholland.org>
  9. *
  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.
  13. *
  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.
  18. */
  19. #include <linux/device.h>
  20. #include <linux/kernel.h>
  21. #include <linux/mm.h>
  22. #include <linux/module.h>
  23. #include <linux/platform_data/simplefb.h>
  24. #include <linux/platform_device.h>
  25. #include "coreboot_table.h"
  26. #define CB_TAG_FRAMEBUFFER 0x12
  27. static const struct simplefb_format formats[] = SIMPLEFB_FORMATS;
  28. static int framebuffer_probe(struct coreboot_device *dev)
  29. {
  30. int i;
  31. u32 length;
  32. struct lb_framebuffer *fb = &dev->framebuffer;
  33. struct platform_device *pdev;
  34. struct resource res;
  35. struct simplefb_platform_data pdata = {
  36. .width = fb->x_resolution,
  37. .height = fb->y_resolution,
  38. .stride = fb->bytes_per_line,
  39. .format = NULL,
  40. };
  41. for (i = 0; i < ARRAY_SIZE(formats); ++i) {
  42. if (fb->bits_per_pixel == formats[i].bits_per_pixel &&
  43. fb->red_mask_pos == formats[i].red.offset &&
  44. fb->red_mask_size == formats[i].red.length &&
  45. fb->green_mask_pos == formats[i].green.offset &&
  46. fb->green_mask_size == formats[i].green.length &&
  47. fb->blue_mask_pos == formats[i].blue.offset &&
  48. fb->blue_mask_size == formats[i].blue.length &&
  49. fb->reserved_mask_pos == formats[i].transp.offset &&
  50. fb->reserved_mask_size == formats[i].transp.length)
  51. pdata.format = formats[i].name;
  52. }
  53. if (!pdata.format)
  54. return -ENODEV;
  55. memset(&res, 0, sizeof(res));
  56. res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
  57. res.name = "Coreboot Framebuffer";
  58. res.start = fb->physical_address;
  59. length = PAGE_ALIGN(fb->y_resolution * fb->bytes_per_line);
  60. res.end = res.start + length - 1;
  61. if (res.end <= res.start)
  62. return -EINVAL;
  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. return PTR_ERR_OR_ZERO(pdev);
  72. }
  73. static int framebuffer_remove(struct coreboot_device *dev)
  74. {
  75. struct platform_device *pdev = dev_get_drvdata(&dev->dev);
  76. platform_device_unregister(pdev);
  77. return 0;
  78. }
  79. static struct coreboot_driver framebuffer_driver = {
  80. .probe = framebuffer_probe,
  81. .remove = framebuffer_remove,
  82. .drv = {
  83. .name = "framebuffer",
  84. },
  85. .tag = CB_TAG_FRAMEBUFFER,
  86. };
  87. static int __init coreboot_framebuffer_init(void)
  88. {
  89. return coreboot_driver_register(&framebuffer_driver);
  90. }
  91. static void coreboot_framebuffer_exit(void)
  92. {
  93. coreboot_driver_unregister(&framebuffer_driver);
  94. }
  95. module_init(coreboot_framebuffer_init);
  96. module_exit(coreboot_framebuffer_exit);
  97. MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
  98. MODULE_LICENSE("GPL");