drm_sysfb_screen_info.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. #include <linux/export.h>
  3. #include <linux/limits.h>
  4. #include <linux/minmax.h>
  5. #include <linux/screen_info.h>
  6. #include <drm/drm_fourcc.h>
  7. #include <drm/drm_print.h>
  8. #include "drm_sysfb_helper.h"
  9. static s64 drm_sysfb_get_validated_size0(struct drm_device *dev, const char *name,
  10. u64 value, u64 max)
  11. {
  12. if (!value) {
  13. drm_warn(dev, "%s of 0 not allowed\n", name);
  14. return -EINVAL;
  15. } else if (value > min(max, S64_MAX)) {
  16. drm_warn(dev, "%s of %llu exceeds maximum of %llu\n", name, value, max);
  17. return -EINVAL;
  18. }
  19. return value;
  20. }
  21. int drm_sysfb_get_width_si(struct drm_device *dev, const struct screen_info *si)
  22. {
  23. return drm_sysfb_get_validated_int0(dev, "width", si->lfb_width, U16_MAX);
  24. }
  25. EXPORT_SYMBOL(drm_sysfb_get_width_si);
  26. int drm_sysfb_get_height_si(struct drm_device *dev, const struct screen_info *si)
  27. {
  28. return drm_sysfb_get_validated_int0(dev, "height", si->lfb_height, U16_MAX);
  29. }
  30. EXPORT_SYMBOL(drm_sysfb_get_height_si);
  31. struct resource *drm_sysfb_get_memory_si(struct drm_device *dev,
  32. const struct screen_info *si,
  33. struct resource *res)
  34. {
  35. ssize_t num;
  36. num = screen_info_resources(si, res, 1);
  37. if (!num) {
  38. drm_warn(dev, "memory resource not found\n");
  39. return NULL;
  40. }
  41. return res;
  42. }
  43. EXPORT_SYMBOL(drm_sysfb_get_memory_si);
  44. int drm_sysfb_get_stride_si(struct drm_device *dev, const struct screen_info *si,
  45. const struct drm_format_info *format,
  46. unsigned int width, unsigned int height, u64 size)
  47. {
  48. u64 lfb_linelength = si->lfb_linelength;
  49. if (!lfb_linelength)
  50. lfb_linelength = drm_format_info_min_pitch(format, 0, width);
  51. return drm_sysfb_get_validated_int0(dev, "stride", lfb_linelength, div64_u64(size, height));
  52. }
  53. EXPORT_SYMBOL(drm_sysfb_get_stride_si);
  54. u64 drm_sysfb_get_visible_size_si(struct drm_device *dev, const struct screen_info *si,
  55. unsigned int height, unsigned int stride, u64 size)
  56. {
  57. u64 vsize = PAGE_ALIGN(height * stride);
  58. return drm_sysfb_get_validated_size0(dev, "visible size", vsize, size);
  59. }
  60. EXPORT_SYMBOL(drm_sysfb_get_visible_size_si);
  61. const struct drm_format_info *drm_sysfb_get_format_si(struct drm_device *dev,
  62. const struct drm_sysfb_format *formats,
  63. size_t nformats,
  64. const struct screen_info *si)
  65. {
  66. const struct drm_format_info *format = NULL;
  67. struct pixel_format pixel;
  68. size_t i;
  69. int ret;
  70. ret = screen_info_pixel_format(si, &pixel);
  71. if (ret)
  72. return NULL;
  73. for (i = 0; i < nformats; ++i) {
  74. const struct drm_sysfb_format *f = &formats[i];
  75. if (pixel_format_equal(&pixel, &f->pixel)) {
  76. format = drm_format_info(f->fourcc);
  77. break;
  78. }
  79. }
  80. if (!format)
  81. drm_warn(dev, "No compatible color format found\n");
  82. return format;
  83. }
  84. EXPORT_SYMBOL(drm_sysfb_get_format_si);