File Index
Files and directories
Sign in
FILE

screen_info_generic.c

File preview with syntax highlighting.

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