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