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