]>
Commit | Line | Data |
---|---|---|
94bf3dd5 VS |
1 | /* |
2 | * GRUB -- GRand Unified Bootloader | |
3 | * Copyright (C) 2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. | |
4 | * | |
5 | * GRUB is free software: you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation, either version 3 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * GRUB is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with GRUB. If not, see <http://www.gnu.org/licenses/>. | |
17 | */ | |
18 | ||
19 | #define grub_video_render_target grub_video_fbrender_target | |
20 | ||
21 | #include <grub/err.h> | |
22 | #include <grub/types.h> | |
23 | #include <grub/dl.h> | |
24 | #include <grub/misc.h> | |
25 | #include <grub/mm.h> | |
26 | #include <grub/video.h> | |
27 | #include <grub/video_fb.h> | |
28 | #include <grub/pci.h> | |
967828eb | 29 | #include <grub/vga.h> |
94bf3dd5 VS |
30 | |
31 | static struct | |
32 | { | |
33 | struct grub_video_mode_info mode_info; | |
d00b0b3f | 34 | grub_size_t page_size; /* The size of a page in bytes. */ |
94bf3dd5 VS |
35 | |
36 | grub_uint8_t *ptr; | |
37 | int mapped; | |
38 | grub_uint32_t base; | |
39 | grub_pci_device_t dev; | |
40 | } framebuffer; | |
41 | ||
9a3e298a | 42 | #define CIRRUS_APERTURE_SIZE 0x1000000 |
94bf3dd5 | 43 | |
94bf3dd5 | 44 | #define CIRRUS_MAX_WIDTH 0x800 |
94bf3dd5 | 45 | #define CIRRUS_MAX_HEIGHT 0x800 |
967828eb | 46 | #define CIRRUS_MAX_PITCH (0x1ff * GRUB_VGA_CR_PITCH_DIVISOR) |
94bf3dd5 VS |
47 | |
48 | enum | |
49 | { | |
94bf3dd5 | 50 | CIRRUS_CR_EXTENDED_DISPLAY = 0x1b, |
d00b0b3f | 51 | CIRRUS_CR_EXTENDED_OVERLAY = 0x1d, |
94bf3dd5 VS |
52 | CIRRUS_CR_MAX |
53 | }; | |
54 | ||
d00b0b3f VS |
55 | #define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK 0x10 |
56 | #define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT 4 | |
57 | #define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1 0x1 | |
58 | #define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT1 16 | |
59 | #define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2 0xc | |
60 | #define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT2 15 | |
61 | ||
62 | #define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK 0x80 | |
63 | #define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT 12 | |
64 | ||
94bf3dd5 VS |
65 | enum |
66 | { | |
94bf3dd5 VS |
67 | CIRRUS_SR_EXTENDED_MODE = 7, |
68 | CIRRUS_SR_MAX | |
69 | }; | |
967828eb | 70 | |
94bf3dd5 VS |
71 | #define CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE 0xf0 |
72 | #define CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT 0x01 | |
31e0ce4d | 73 | #define CIRRUS_SR_EXTENDED_MODE_8BPP 0x00 |
94bf3dd5 | 74 | #define CIRRUS_SR_EXTENDED_MODE_16BPP 0x06 |
31e0ce4d | 75 | #define CIRRUS_SR_EXTENDED_MODE_24BPP 0x04 |
94bf3dd5 VS |
76 | #define CIRRUS_SR_EXTENDED_MODE_32BPP 0x08 |
77 | ||
63c1b71c VS |
78 | #define CIRRUS_HIDDEN_DAC_ENABLE_EXT 0x80 |
79 | #define CIRRUS_HIDDEN_DAC_ENABLE_ALL 0x40 | |
31e0ce4d | 80 | #define CIRRUS_HIDDEN_DAC_8BPP 0 |
63c1b71c VS |
81 | #define CIRRUS_HIDDEN_DAC_15BPP (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ |
82 | | CIRRUS_HIDDEN_DAC_ENABLE_ALL | 0) | |
83 | #define CIRRUS_HIDDEN_DAC_16BPP (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ | |
84 | | CIRRUS_HIDDEN_DAC_ENABLE_ALL | 1) | |
85 | #define CIRRUS_HIDDEN_DAC_888COLOR (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ | |
86 | | CIRRUS_HIDDEN_DAC_ENABLE_ALL | 5) | |
87 | ||
94bf3dd5 VS |
88 | static void |
89 | write_hidden_dac (grub_uint8_t data) | |
90 | { | |
967828eb VS |
91 | grub_inb (GRUB_VGA_IO_PALLETTE_WRITE_INDEX); |
92 | grub_inb (GRUB_VGA_IO_PIXEL_MASK); | |
93 | grub_inb (GRUB_VGA_IO_PIXEL_MASK); | |
94 | grub_inb (GRUB_VGA_IO_PIXEL_MASK); | |
95 | grub_inb (GRUB_VGA_IO_PIXEL_MASK); | |
96 | grub_outb (data, GRUB_VGA_IO_PIXEL_MASK); | |
94bf3dd5 VS |
97 | } |
98 | ||
99 | static grub_uint8_t | |
100 | read_hidden_dac (void) | |
101 | { | |
967828eb VS |
102 | grub_inb (GRUB_VGA_IO_PALLETTE_WRITE_INDEX); |
103 | grub_inb (GRUB_VGA_IO_PIXEL_MASK); | |
104 | grub_inb (GRUB_VGA_IO_PIXEL_MASK); | |
105 | grub_inb (GRUB_VGA_IO_PIXEL_MASK); | |
106 | grub_inb (GRUB_VGA_IO_PIXEL_MASK); | |
107 | return grub_inb (GRUB_VGA_IO_PIXEL_MASK); | |
94bf3dd5 VS |
108 | } |
109 | ||
110 | struct saved_state | |
111 | { | |
112 | grub_uint8_t cr[CIRRUS_CR_MAX]; | |
967828eb | 113 | grub_uint8_t gr[GRUB_VGA_GR_MAX]; |
94bf3dd5 VS |
114 | grub_uint8_t sr[CIRRUS_SR_MAX]; |
115 | grub_uint8_t hidden_dac; | |
116 | /* We need to preserve VGA font and VGA text. */ | |
117 | grub_uint8_t vram[32 * 4 * 256]; | |
31e0ce4d VS |
118 | grub_uint8_t r[256]; |
119 | grub_uint8_t g[256]; | |
120 | grub_uint8_t b[256]; | |
94bf3dd5 VS |
121 | }; |
122 | ||
123 | static struct saved_state initial_state; | |
124 | static int state_saved = 0; | |
125 | ||
126 | static void | |
127 | save_state (struct saved_state *st) | |
128 | { | |
129 | unsigned i; | |
130 | for (i = 0; i < ARRAY_SIZE (st->cr); i++) | |
967828eb | 131 | st->cr[i] = grub_vga_cr_read (i); |
94bf3dd5 | 132 | for (i = 0; i < ARRAY_SIZE (st->sr); i++) |
967828eb | 133 | st->sr[i] = grub_vga_sr_read (i); |
94bf3dd5 | 134 | for (i = 0; i < ARRAY_SIZE (st->gr); i++) |
967828eb | 135 | st->gr[i] = grub_vga_gr_read (i); |
31e0ce4d | 136 | for (i = 0; i < 256; i++) |
967828eb | 137 | grub_vga_palette_read (i, st->r + i, st->g + i, st->b + i); |
31e0ce4d | 138 | |
94bf3dd5 | 139 | st->hidden_dac = read_hidden_dac (); |
967828eb | 140 | grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE); |
94bf3dd5 VS |
141 | grub_memcpy (st->vram, framebuffer.ptr, sizeof (st->vram)); |
142 | } | |
143 | ||
144 | static void | |
145 | restore_state (struct saved_state *st) | |
146 | { | |
147 | unsigned i; | |
967828eb | 148 | grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE); |
94bf3dd5 VS |
149 | grub_memcpy (framebuffer.ptr, st->vram, sizeof (st->vram)); |
150 | for (i = 0; i < ARRAY_SIZE (st->cr); i++) | |
967828eb | 151 | grub_vga_cr_write (st->cr[i], i); |
94bf3dd5 | 152 | for (i = 0; i < ARRAY_SIZE (st->sr); i++) |
967828eb | 153 | grub_vga_sr_write (st->sr[i], i); |
94bf3dd5 | 154 | for (i = 0; i < ARRAY_SIZE (st->gr); i++) |
967828eb | 155 | grub_vga_gr_write (st->gr[i], i); |
31e0ce4d | 156 | for (i = 0; i < 256; i++) |
967828eb | 157 | grub_vga_palette_write (i, st->r[i], st->g[i], st->b[i]); |
31e0ce4d | 158 | |
94bf3dd5 VS |
159 | write_hidden_dac (st->hidden_dac); |
160 | } | |
161 | ||
162 | static grub_err_t | |
163 | grub_video_cirrus_video_init (void) | |
164 | { | |
165 | /* Reset frame buffer. */ | |
166 | grub_memset (&framebuffer, 0, sizeof(framebuffer)); | |
167 | ||
168 | return grub_video_fb_init (); | |
169 | } | |
170 | ||
171 | static grub_err_t | |
172 | grub_video_cirrus_video_fini (void) | |
173 | { | |
174 | if (framebuffer.mapped) | |
175 | grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, | |
176 | CIRRUS_APERTURE_SIZE); | |
177 | ||
178 | if (state_saved) | |
179 | { | |
180 | restore_state (&initial_state); | |
181 | state_saved = 0; | |
182 | } | |
183 | ||
184 | return grub_video_fb_fini (); | |
185 | } | |
186 | ||
d00b0b3f VS |
187 | static grub_err_t |
188 | doublebuf_pageflipping_set_page (int page) | |
189 | { | |
190 | int start = framebuffer.page_size * page / 4; | |
191 | grub_uint8_t cr_ext, cr_overlay; | |
192 | ||
967828eb VS |
193 | grub_vga_cr_write (start & 0xff, GRUB_VGA_CR_START_ADDR_LOW_REGISTER); |
194 | grub_vga_cr_write ((start & 0xff00) >> 8, | |
195 | GRUB_VGA_CR_START_ADDR_HIGH_REGISTER); | |
d00b0b3f | 196 | |
967828eb | 197 | cr_ext = grub_vga_cr_read (CIRRUS_CR_EXTENDED_DISPLAY); |
d00b0b3f VS |
198 | cr_ext &= ~(CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1 |
199 | | CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2); | |
200 | cr_ext |= ((start >> CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT1) | |
201 | & CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1); | |
202 | cr_ext |= ((start >> CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT2) | |
203 | & CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2); | |
967828eb | 204 | grub_vga_cr_write (cr_ext, CIRRUS_CR_EXTENDED_DISPLAY); |
d00b0b3f | 205 | |
967828eb | 206 | cr_overlay = grub_vga_cr_read (CIRRUS_CR_EXTENDED_OVERLAY); |
d00b0b3f VS |
207 | cr_overlay &= ~(CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK); |
208 | cr_overlay |= ((start >> CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT) | |
209 | & CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK); | |
967828eb | 210 | grub_vga_cr_write (cr_overlay, CIRRUS_CR_EXTENDED_OVERLAY); |
d00b0b3f VS |
211 | |
212 | return GRUB_ERR_NONE; | |
213 | } | |
214 | ||
31e0ce4d VS |
215 | static grub_err_t |
216 | grub_video_cirrus_set_palette (unsigned int start, unsigned int count, | |
217 | struct grub_video_palette_data *palette_data) | |
218 | { | |
219 | if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) | |
220 | { | |
221 | unsigned i; | |
222 | if (start >= 0x100) | |
223 | return GRUB_ERR_NONE; | |
224 | if (start + count >= 0x100) | |
225 | count = 0x100 - start; | |
226 | ||
227 | for (i = 0; i < count; i++) | |
967828eb VS |
228 | grub_vga_palette_write (start + i, palette_data[i].r, palette_data[i].g, |
229 | palette_data[i].b); | |
31e0ce4d VS |
230 | } |
231 | ||
232 | /* Then set color to emulated palette. */ | |
233 | return grub_video_fb_set_palette (start, count, palette_data); | |
234 | } | |
235 | ||
94bf3dd5 VS |
236 | static grub_err_t |
237 | grub_video_cirrus_setup (unsigned int width, unsigned int height, | |
31e0ce4d | 238 | unsigned int mode_type, unsigned int mode_mask) |
94bf3dd5 VS |
239 | { |
240 | int depth; | |
241 | grub_err_t err; | |
242 | int found = 0; | |
243 | int pitch, bytes_per_pixel; | |
244 | ||
245 | auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))); | |
246 | int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid) | |
247 | { | |
248 | grub_pci_address_t addr; | |
249 | grub_uint32_t class; | |
250 | ||
251 | addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); | |
252 | class = grub_pci_read (addr); | |
253 | ||
254 | if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x00b81013) | |
255 | return 0; | |
256 | ||
257 | found = 1; | |
258 | ||
259 | addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); | |
260 | framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; | |
261 | framebuffer.dev = dev; | |
262 | ||
263 | return 1; | |
264 | } | |
265 | ||
266 | /* Decode depth from mode_type. If it is zero, then autodetect. */ | |
267 | depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) | |
268 | >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; | |
269 | ||
270 | if (width == 0 || height == 0) | |
271 | { | |
272 | width = 800; | |
273 | height = 600; | |
274 | } | |
275 | ||
967828eb | 276 | if (width & (GRUB_VGA_CR_WIDTH_DIVISOR - 1)) |
94bf3dd5 VS |
277 | return grub_error (GRUB_ERR_IO, |
278 | "screen width must be a multiple of %d", | |
967828eb | 279 | GRUB_VGA_CR_WIDTH_DIVISOR); |
94bf3dd5 VS |
280 | |
281 | if (width > CIRRUS_MAX_WIDTH) | |
282 | return grub_error (GRUB_ERR_IO, | |
283 | "screen width must be at most %d", CIRRUS_MAX_WIDTH); | |
284 | ||
285 | if (height > CIRRUS_MAX_HEIGHT) | |
286 | return grub_error (GRUB_ERR_IO, | |
287 | "screen height must be at most %d", CIRRUS_MAX_HEIGHT); | |
288 | ||
31e0ce4d VS |
289 | if (depth == 0 |
290 | && !grub_video_check_mode_flag (mode_type, mode_mask, | |
291 | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR, 0)) | |
94bf3dd5 VS |
292 | depth = 24; |
293 | ||
31e0ce4d VS |
294 | if (depth == 0) |
295 | depth = 8; | |
296 | ||
297 | if (depth != 32 && depth != 24 && depth != 16 && depth != 15 && depth != 8) | |
298 | return grub_error (GRUB_ERR_IO, "only 32, 24, 16, 15 and 8-bit bpp are" | |
299 | " supported by cirrus video"); | |
94bf3dd5 VS |
300 | |
301 | bytes_per_pixel = (depth + 7) / 8; | |
302 | pitch = width * bytes_per_pixel; | |
303 | ||
304 | if (pitch > CIRRUS_MAX_PITCH) | |
305 | return grub_error (GRUB_ERR_IO, | |
306 | "screen width must be at most %d at bitdepth %d", | |
307 | CIRRUS_MAX_PITCH / bytes_per_pixel, depth); | |
308 | ||
d00b0b3f VS |
309 | framebuffer.page_size = pitch * height; |
310 | ||
311 | if (framebuffer.page_size > CIRRUS_APERTURE_SIZE) | |
312 | return grub_error (GRUB_ERR_IO, "Not enough video memory for this mode"); | |
313 | ||
94bf3dd5 VS |
314 | grub_pci_iterate (find_card); |
315 | if (!found) | |
316 | return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); | |
317 | ||
318 | if (found && framebuffer.base == 0) | |
319 | { | |
320 | /* FIXME: change framebuffer base */ | |
d00b0b3f | 321 | return grub_error (GRUB_ERR_IO, "PCI BAR not set"); |
94bf3dd5 VS |
322 | } |
323 | ||
324 | /* We can safely discard volatile attribute. */ | |
325 | framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev, | |
326 | framebuffer.base, | |
327 | CIRRUS_APERTURE_SIZE); | |
328 | framebuffer.mapped = 1; | |
329 | ||
330 | if (!state_saved) | |
331 | { | |
332 | save_state (&initial_state); | |
333 | state_saved = 1; | |
334 | } | |
335 | ||
336 | { | |
337 | int pitch_reg, overflow_reg = 0, line_compare = 0x3ff; | |
63c1b71c | 338 | grub_uint8_t sr_ext = 0, hidden_dac = 0; |
94bf3dd5 | 339 | |
967828eb | 340 | pitch_reg = pitch / GRUB_VGA_CR_PITCH_DIVISOR; |
94bf3dd5 | 341 | |
967828eb VS |
342 | grub_vga_gr_write (GRUB_VGA_GR_MODE_256_COLOR | GRUB_VGA_GR_MODE_READ_MODE1, |
343 | GRUB_VGA_GR_MODE); | |
344 | grub_vga_gr_write (GRUB_VGA_GR_GR6_GRAPHICS_MODE, GRUB_VGA_GR_GR6); | |
94bf3dd5 | 345 | |
967828eb | 346 | grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE); |
94bf3dd5 VS |
347 | |
348 | /* Disable CR0-7 write protection. */ | |
967828eb | 349 | grub_vga_cr_write (0, GRUB_VGA_CR_VSYNC_END); |
94bf3dd5 | 350 | |
967828eb VS |
351 | grub_vga_cr_write (width / GRUB_VGA_CR_WIDTH_DIVISOR - 1, |
352 | GRUB_VGA_CR_WIDTH); | |
353 | grub_vga_cr_write ((height - 1) & 0xff, GRUB_VGA_CR_HEIGHT); | |
354 | overflow_reg |= (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT) & | |
355 | GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK) | |
356 | | (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT) & | |
357 | GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK); | |
94bf3dd5 | 358 | |
967828eb | 359 | grub_vga_cr_write (pitch_reg & 0xff, GRUB_VGA_CR_PITCH); |
94bf3dd5 | 360 | |
967828eb VS |
361 | grub_vga_cr_write (line_compare & 0xff, GRUB_VGA_CR_LINE_COMPARE); |
362 | overflow_reg |= (line_compare >> GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT) | |
363 | & GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK; | |
94bf3dd5 | 364 | |
967828eb | 365 | grub_vga_cr_write (overflow_reg, GRUB_VGA_CR_OVERFLOW); |
94bf3dd5 | 366 | |
967828eb | 367 | grub_vga_cr_write ((pitch_reg >> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT) |
94bf3dd5 VS |
368 | & CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK, |
369 | CIRRUS_CR_EXTENDED_DISPLAY); | |
370 | ||
967828eb VS |
371 | grub_vga_cr_write ((line_compare >> GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT) |
372 | & GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK, GRUB_VGA_CR_CELL_HEIGHT); | |
94bf3dd5 | 373 | |
967828eb VS |
374 | grub_vga_cr_write (GRUB_VGA_CR_MODE_TIMING_ENABLE |
375 | | GRUB_VGA_CR_MODE_BYTE_MODE | |
376 | | GRUB_VGA_CR_MODE_NO_HERCULES | GRUB_VGA_CR_MODE_NO_CGA, | |
377 | GRUB_VGA_CR_MODE); | |
94bf3dd5 | 378 | |
d00b0b3f VS |
379 | doublebuf_pageflipping_set_page (0); |
380 | ||
94bf3dd5 VS |
381 | sr_ext = CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE |
382 | | CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT; | |
383 | switch (depth) | |
384 | { | |
63c1b71c | 385 | /* FIXME: support 8-bit grayscale and 8-bit RGB. */ |
94bf3dd5 | 386 | case 32: |
63c1b71c | 387 | hidden_dac = CIRRUS_HIDDEN_DAC_888COLOR; |
94bf3dd5 VS |
388 | sr_ext |= CIRRUS_SR_EXTENDED_MODE_32BPP; |
389 | break; | |
390 | case 24: | |
63c1b71c | 391 | hidden_dac = CIRRUS_HIDDEN_DAC_888COLOR; |
94bf3dd5 VS |
392 | sr_ext |= CIRRUS_SR_EXTENDED_MODE_24BPP; |
393 | break; | |
394 | case 16: | |
63c1b71c VS |
395 | hidden_dac = CIRRUS_HIDDEN_DAC_16BPP; |
396 | sr_ext |= CIRRUS_SR_EXTENDED_MODE_16BPP; | |
397 | break; | |
94bf3dd5 | 398 | case 15: |
63c1b71c | 399 | hidden_dac = CIRRUS_HIDDEN_DAC_15BPP; |
94bf3dd5 VS |
400 | sr_ext |= CIRRUS_SR_EXTENDED_MODE_16BPP; |
401 | break; | |
31e0ce4d VS |
402 | case 8: |
403 | hidden_dac = CIRRUS_HIDDEN_DAC_8BPP; | |
404 | sr_ext |= CIRRUS_SR_EXTENDED_MODE_8BPP; | |
405 | break; | |
94bf3dd5 | 406 | } |
967828eb | 407 | grub_vga_sr_write (sr_ext, CIRRUS_SR_EXTENDED_MODE); |
63c1b71c | 408 | write_hidden_dac (hidden_dac); |
94bf3dd5 VS |
409 | } |
410 | ||
411 | /* Fill mode info details. */ | |
412 | framebuffer.mode_info.width = width; | |
413 | framebuffer.mode_info.height = height; | |
414 | framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; | |
415 | framebuffer.mode_info.bpp = depth; | |
416 | framebuffer.mode_info.bytes_per_pixel = bytes_per_pixel; | |
417 | framebuffer.mode_info.pitch = pitch; | |
418 | framebuffer.mode_info.number_of_colors = 256; | |
419 | framebuffer.mode_info.reserved_mask_size = 0; | |
420 | framebuffer.mode_info.reserved_field_pos = 0; | |
421 | ||
422 | switch (depth) | |
423 | { | |
31e0ce4d VS |
424 | case 8: |
425 | framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; | |
426 | break; | |
94bf3dd5 VS |
427 | case 16: |
428 | framebuffer.mode_info.red_mask_size = 5; | |
429 | framebuffer.mode_info.red_field_pos = 11; | |
430 | framebuffer.mode_info.green_mask_size = 6; | |
431 | framebuffer.mode_info.green_field_pos = 5; | |
432 | framebuffer.mode_info.blue_mask_size = 5; | |
433 | framebuffer.mode_info.blue_field_pos = 0; | |
434 | break; | |
435 | ||
436 | case 15: | |
437 | framebuffer.mode_info.red_mask_size = 5; | |
438 | framebuffer.mode_info.red_field_pos = 10; | |
439 | framebuffer.mode_info.green_mask_size = 5; | |
440 | framebuffer.mode_info.green_field_pos = 5; | |
441 | framebuffer.mode_info.blue_mask_size = 5; | |
442 | framebuffer.mode_info.blue_field_pos = 0; | |
443 | break; | |
444 | ||
445 | case 32: | |
446 | framebuffer.mode_info.reserved_mask_size = 8; | |
447 | framebuffer.mode_info.reserved_field_pos = 24; | |
448 | ||
449 | case 24: | |
450 | framebuffer.mode_info.red_mask_size = 8; | |
451 | framebuffer.mode_info.red_field_pos = 16; | |
452 | framebuffer.mode_info.green_mask_size = 8; | |
453 | framebuffer.mode_info.green_field_pos = 8; | |
454 | framebuffer.mode_info.blue_mask_size = 8; | |
455 | framebuffer.mode_info.blue_field_pos = 0; | |
456 | break; | |
457 | } | |
458 | ||
459 | framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); | |
460 | ||
d00b0b3f VS |
461 | if (CIRRUS_APERTURE_SIZE >= 2 * framebuffer.page_size) |
462 | err = grub_video_fb_setup (mode_type, mode_mask, | |
463 | &framebuffer.mode_info, | |
464 | framebuffer.ptr, | |
465 | doublebuf_pageflipping_set_page, | |
466 | framebuffer.ptr + framebuffer.page_size); | |
467 | else | |
468 | err = grub_video_fb_setup (mode_type, mode_mask, | |
469 | &framebuffer.mode_info, | |
470 | framebuffer.ptr, 0, 0); | |
94bf3dd5 | 471 | |
94bf3dd5 VS |
472 | |
473 | /* Copy default palette to initialize emulated palette. */ | |
31e0ce4d VS |
474 | err = grub_video_cirrus_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, |
475 | grub_video_fbstd_colors); | |
94bf3dd5 VS |
476 | return err; |
477 | } | |
478 | ||
94bf3dd5 VS |
479 | static struct grub_video_adapter grub_video_cirrus_adapter = |
480 | { | |
481 | .name = "Cirrus CLGD 5446 PCI Video Driver", | |
482 | .id = GRUB_VIDEO_DRIVER_CIRRUS, | |
483 | ||
05e51879 VS |
484 | .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE, |
485 | ||
94bf3dd5 VS |
486 | .init = grub_video_cirrus_video_init, |
487 | .fini = grub_video_cirrus_video_fini, | |
488 | .setup = grub_video_cirrus_setup, | |
489 | .get_info = grub_video_fb_get_info, | |
d00b0b3f | 490 | .get_info_and_fini = grub_video_fb_get_info_and_fini, |
94bf3dd5 VS |
491 | .set_palette = grub_video_cirrus_set_palette, |
492 | .get_palette = grub_video_fb_get_palette, | |
493 | .set_viewport = grub_video_fb_set_viewport, | |
494 | .get_viewport = grub_video_fb_get_viewport, | |
495 | .map_color = grub_video_fb_map_color, | |
496 | .map_rgb = grub_video_fb_map_rgb, | |
497 | .map_rgba = grub_video_fb_map_rgba, | |
498 | .unmap_color = grub_video_fb_unmap_color, | |
499 | .fill_rect = grub_video_fb_fill_rect, | |
500 | .blit_bitmap = grub_video_fb_blit_bitmap, | |
501 | .blit_render_target = grub_video_fb_blit_render_target, | |
502 | .scroll = grub_video_fb_scroll, | |
d00b0b3f | 503 | .swap_buffers = grub_video_fb_swap_buffers, |
94bf3dd5 VS |
504 | .create_render_target = grub_video_fb_create_render_target, |
505 | .delete_render_target = grub_video_fb_delete_render_target, | |
d00b0b3f | 506 | .set_active_render_target = grub_video_fb_set_active_render_target, |
94bf3dd5 VS |
507 | .get_active_render_target = grub_video_fb_get_active_render_target, |
508 | ||
509 | .next = 0 | |
510 | }; | |
511 | ||
512 | GRUB_MOD_INIT(video_cirrus) | |
513 | { | |
514 | grub_video_register (&grub_video_cirrus_adapter); | |
515 | } | |
516 | ||
517 | GRUB_MOD_FINI(video_cirrus) | |
518 | { | |
519 | grub_video_unregister (&grub_video_cirrus_adapter); | |
520 | } |