1 // SPDX-License-Identifier: GPL-2.0-only 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; /* stride or negative errno code */ 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); 82