1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/export.h> 4 #include <linux/ioport.h> 5 #include <linux/screen_info.h> 6 #include <linux/string.h> 7 8 static void resource_init_named(struct resource *r, 9 resource_size_t start, resource_size_t size, 10 const char *name, unsigned int flags) 11 { 12 memset(r, 0, sizeof(*r)); 13 14 r->start = start; 15 r->end = start + size - 1; 16 r->name = name; 17 r->flags = flags; 18 } 19 20 static void resource_init_io_named(struct resource *r, 21 resource_size_t start, resource_size_t size, 22 const char *name) 23 { 24 resource_init_named(r, start, size, name, IORESOURCE_IO); 25 } 26 27 static void resource_init_mem_named(struct resource *r, 28 resource_size_t start, resource_size_t size, 29 const char *name) 30 { 31 resource_init_named(r, start, size, name, IORESOURCE_MEM); 32 } 33 34 static inline bool __screen_info_has_ega_gfx(unsigned int mode) 35 { 36 switch (mode) { 37 case 0x0d: /* 320x200-4 */ 38 case 0x0e: /* 640x200-4 */ 39 case 0x0f: /* 640x350-1 */ 40 case 0x10: /* 640x350-4 */ 41 return true; 42 default: 43 return false; 44 } 45 } 46 47 static inline bool __screen_info_has_vga_gfx(unsigned int mode) 48 { 49 switch (mode) { 50 case 0x10: /* 640x480-1 */ 51 case 0x12: /* 640x480-4 */ 52 case 0x13: /* 320-200-8 */ 53 case 0x6a: /* 800x600-4 (VESA) */ 54 return true; 55 default: 56 return __screen_info_has_ega_gfx(mode); 57 } 58 } 59 60 /** 61 * screen_info_resources() - Get resources from screen_info structure 62 * @si: the screen_info 63 * @r: pointer to an array of resource structures 64 * @num: number of elements in @r: 65 * 66 * Returns: 67 * The number of resources stored in @r on success, or a negative errno code otherwise. 68 * 69 * A call to screen_info_resources() returns the resources consumed by the 70 * screen_info's device or framebuffer. The result is stored in the caller-supplied 71 * array @r with up to @num elements. The function returns the number of 72 * initialized elements. 73 */ 74 ssize_t screen_info_resources(const struct screen_info *si, struct resource *r, size_t num) 75 { 76 struct resource *pos = r; 77 unsigned int type = screen_info_video_type(si); 78 u64 base, size; 79 80 switch (type) { 81 case VIDEO_TYPE_MDA: 82 if (num > 0) 83 resource_init_io_named(pos++, 0x3b0, 12, "mda"); 84 if (num > 1) 85 resource_init_io_named(pos++, 0x3bf, 0x01, "mda"); 86 if (num > 2) 87 resource_init_mem_named(pos++, 0xb0000, 0x2000, "mda"); 88 break; 89 case VIDEO_TYPE_CGA: 90 if (num > 0) 91 resource_init_io_named(pos++, 0x3d4, 0x02, "cga"); 92 if (num > 1) 93 resource_init_mem_named(pos++, 0xb8000, 0x2000, "cga"); 94 break; 95 case VIDEO_TYPE_EGAM: 96 if (num > 0) 97 resource_init_io_named(pos++, 0x3bf, 0x10, "ega"); 98 if (num > 1) 99 resource_init_mem_named(pos++, 0xb0000, 0x8000, "ega"); 100 break; 101 case VIDEO_TYPE_EGAC: 102 if (num > 0) 103 resource_init_io_named(pos++, 0x3c0, 0x20, "ega"); 104 if (num > 1) { 105 if (__screen_info_has_ega_gfx(si->orig_video_mode)) 106 resource_init_mem_named(pos++, 0xa0000, 0x10000, "ega"); 107 else 108 resource_init_mem_named(pos++, 0xb8000, 0x8000, "ega"); 109 } 110 break; 111 case VIDEO_TYPE_VGAC: 112 if (num > 0) 113 resource_init_io_named(pos++, 0x3c0, 0x20, "vga+"); 114 if (num > 1) { 115 if (__screen_info_has_vga_gfx(si->orig_video_mode)) 116 resource_init_mem_named(pos++, 0xa0000, 0x10000, "vga+"); 117 else 118 resource_init_mem_named(pos++, 0xb8000, 0x8000, "vga+"); 119 } 120 break; 121 case VIDEO_TYPE_VLFB: 122 case VIDEO_TYPE_EFI: 123 base = __screen_info_lfb_base(si); 124 if (!base) 125 break; 126 size = __screen_info_lfb_size(si, type); 127 if (!size) 128 break; 129 if (num > 0) 130 resource_init_mem_named(pos++, base, size, "lfb"); 131 break; 132 case VIDEO_TYPE_PICA_S3: 133 case VIDEO_TYPE_MIPS_G364: 134 case VIDEO_TYPE_SGI: 135 case VIDEO_TYPE_TGAC: 136 case VIDEO_TYPE_SUN: 137 case VIDEO_TYPE_SUNPCI: 138 case VIDEO_TYPE_PMAC: 139 default: 140 /* not supported */ 141 return -EINVAL; 142 } 143 144 return pos - r; 145 } 146 EXPORT_SYMBOL(screen_info_resources); 147 148 /* 149 * The meaning of depth and bpp for direct-color formats is 150 * inconsistent: 151 * 152 * - DRM format info specifies depth as the number of color 153 * bits; including alpha, but not including filler bits. 154 * - Linux' EFI platform code computes lfb_depth from the 155 * individual color channels, including the reserved bits. 156 * - VBE 1.1 defines lfb_depth for XRGB1555 as 16, but later 157 * versions use 15. 158 * - On the kernel command line, 'bpp' of 32 is usually 159 * XRGB8888 including the filler bits, but 15 is XRGB1555 160 * not including the filler bit. 161 * 162 * It is not easily possible to fix this in struct screen_info, 163 * as this could break UAPI. The best solution is to compute 164 * bits_per_pixel from the color bits, reserved bits and 165 * reported lfb_depth, whichever is highest. 166 */ 167 168 u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si) 169 { 170 u32 bits_per_pixel = si->lfb_depth; 171 172 if (bits_per_pixel > 8) { 173 bits_per_pixel = max(max3(si->red_size + si->red_pos, 174 si->green_size + si->green_pos, 175 si->blue_size + si->blue_pos), 176 si->rsvd_size + si->rsvd_pos); 177 bits_per_pixel = max_t(u32, bits_per_pixel, si->lfb_depth); 178 } 179 180 return bits_per_pixel; 181 } 182 EXPORT_SYMBOL(__screen_info_lfb_bits_per_pixel); 183