1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 2010 Intel Corporation; author: H. Peter Anvin
4 *
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use,
9 * copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following
12 * conditions:
13 *
14 * The above copyright notice and this permission notice shall
15 * be included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * ----------------------------------------------------------------------- */
27
28 /*
29 * Based on:
30 *
31 * 915 resolution by steve tomljenovic
32 *
33 * This was tested only on Sony VGN-FS550. Use at your own risk
34 *
35 * This code is based on the techniques used in :
36 *
37 * - 855patch. Many thanks to Christian Zietz (czietz gmx net)
38 * for demonstrating how to shadow the VBIOS into system RAM
39 * and then modify it.
40 *
41 * - 1280patch by Andrew Tipton (andrewtipton null li).
42 *
43 * - 855resolution by Alain Poirier
44 *
45 * This source code is into the public domain.
46 */
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #define __USE_GNU
52 #include <string.h>
53 #include <sys/io.h>
54 #include <sys/cpu.h>
55 #include <sys/pci.h>
56 #include <unistd.h>
57 #include <assert.h>
58 #include <stdbool.h>
59 #include "video.h"
60 #include "debug.h"
61
62 #define VBIOS_START 0xc0000
63 #define VBIOS_SIZE 0x10000
64
65 #define MODE_TABLE_OFFSET_845G 617
66
67 #define VERSION "0.5.3"
68
69 #define ATI_SIGNATURE1 "ATI MOBILITY RADEON"
70 #define ATI_SIGNATURE2 "ATI Technologies Inc"
71 #define NVIDIA_SIGNATURE "NVIDIA Corp"
72 #define INTEL_SIGNATURE "Intel Corp"
73
74 typedef unsigned char * address;
75
76 typedef enum {
77 CT_UNKWN, CT_830, CT_845G, CT_855GM, CT_865G, CT_915G, CT_915GM,
78 CT_945G, CT_945GM, CT_946GZ, CT_G965, CT_Q965, CT_945GME,
79 CHIPSET_TYPES
80 } chipset_type;
81
82 typedef enum {
83 BT_UNKWN, BT_1, BT_2, BT_3
84 } bios_type;
85
86 static int freqs[] = { 60, 75, 85 };
87
88 typedef struct {
89 uint8_t mode;
90 uint8_t bits_per_pixel;
91 uint16_t resolution;
92 uint8_t unknown;
93 } __attribute__((packed)) vbios_mode;
94
95 typedef struct {
96 uint16_t clock; /* Clock frequency in 10 kHz */
97 uint8_t x1;
98 uint8_t x_total;
99 uint8_t x2;
100 uint8_t y1;
101 uint8_t y_total;
102 uint8_t y2;
103 } __attribute__((packed)) vbios_resolution_type1;
104
105 typedef struct {
106 uint32_t clock;
107
108 uint16_t x1;
109 uint16_t htotal;
110 uint16_t x2;
111 uint16_t hblank;
112 uint16_t hsyncstart;
113 uint16_t hsyncend;
114
115 uint16_t y1;
116 uint16_t vtotal;
117 uint16_t y2;
118 uint16_t vblank;
119 uint16_t vsyncstart;
120 uint16_t vsyncend;
121 } __attribute__((packed)) vbios_modeline_type2;
122
123 typedef struct {
124 uint8_t xchars;
125 uint8_t ychars;
126 uint8_t unknown[4];
127
128 vbios_modeline_type2 modelines[];
129 } __attribute__((packed)) vbios_resolution_type2;
130
131 typedef struct {
132 uint32_t clock;
133
134 uint16_t x1;
135 uint16_t htotal;
136 uint16_t x2;
137 uint16_t hblank;
138 uint16_t hsyncstart;
139 uint16_t hsyncend;
140
141 uint16_t y1;
142 uint16_t vtotal;
143 uint16_t y2;
144 uint16_t vblank;
145 uint16_t vsyncstart;
146 uint16_t vsyncend;
147
148 uint16_t timing_h;
149 uint16_t timing_v;
150
151 uint8_t unknown[6];
152 } __attribute__((packed)) vbios_modeline_type3;
153
154 typedef struct {
155 unsigned char unknown[6];
156
157 vbios_modeline_type3 modelines[];
158 } __attribute__((packed)) vbios_resolution_type3;
159
160
161 typedef struct {
162 unsigned int chipset_id;
163 chipset_type chipset;
164 bios_type bios;
165
166 address bios_ptr;
167
168 vbios_mode * mode_table;
169 unsigned int mode_table_size;
170
171 uint8_t b1, b2;
172
173 bool unlocked;
174 } vbios_map;
175
176 #if 0 /* Debugging hacks */
177 static void good_marker(int x)
178 {
179 ((uint16_t *)0xb8000)[x] = 0x2f30 - ((x & 0xf0) << 4) + (x & 0x0f);
180 }
181
182 static void bad_marker(int x)
183 {
184 ((uint16_t *)0xb8000)[x] = 0x4f30 - ((x & 0xf0) << 4) + (x & 0x0f);
185 }
186
187 static void status(const char *fmt, ...)
188 {
189 va_list ap;
190 char msg[81], *p;
191 int i;
192 uint16_t *q;
193
194 memset(msg, 0, sizeof msg);
195 va_start(ap, fmt);
196 vsnprintf(msg, sizeof msg, fmt, ap);
197 va_end(ap);
198 p = msg;
199 q = (uint16_t *)0xb8000 + 80;
200 for (i = 0; i < 80; i++)
201 *q++ = *p++ + 0x1f00;
202 }
203 #else
good_marker(int x)204 static inline void good_marker(int x) { (void)x; }
bad_marker(int x)205 static inline void bad_marker(int x) { (void)x; }
status(const char * fmt,...)206 static inline void status(const char *fmt, ...) { (void)fmt; }
207 #endif
208
get_chipset_id(void)209 static unsigned int get_chipset_id(void) {
210 return pci_readl(0x80000000);
211 }
212
get_chipset(unsigned int id)213 static chipset_type get_chipset(unsigned int id) {
214 chipset_type type;
215
216 switch (id) {
217 case 0x35758086:
218 type = CT_830;
219 break;
220
221 case 0x25608086:
222 type = CT_845G;
223 break;
224
225 case 0x35808086:
226 type = CT_855GM;
227 break;
228
229 case 0x25708086:
230 type = CT_865G;
231 break;
232
233 case 0x25808086:
234 type = CT_915G;
235 break;
236
237 case 0x25908086:
238 type = CT_915GM;
239 break;
240
241 case 0x27708086:
242 type = CT_945G;
243 break;
244
245 case 0x27a08086:
246 type = CT_945GM;
247 break;
248
249 case 0x29708086:
250 type = CT_946GZ;
251 break;
252
253 case 0x29a08086:
254 type = CT_G965;
255 break;
256
257 case 0x29908086:
258 type = CT_Q965;
259 break;
260
261 case 0x27ac8086:
262 type = CT_945GME;
263 break;
264
265 default:
266 type = CT_UNKWN;
267 break;
268 }
269
270 return type;
271 }
272
273
map_type1_resolution(vbios_map * map,uint16_t res)274 static vbios_resolution_type1 * map_type1_resolution(vbios_map * map,
275 uint16_t res)
276 {
277 vbios_resolution_type1 * ptr = ((vbios_resolution_type1*)(map->bios_ptr + res));
278 return ptr;
279 }
280
map_type2_resolution(vbios_map * map,uint16_t res)281 static vbios_resolution_type2 * map_type2_resolution(vbios_map * map,
282 uint16_t res)
283 {
284 vbios_resolution_type2 * ptr = ((vbios_resolution_type2*)(map->bios_ptr + res));
285 return ptr;
286 }
287
map_type3_resolution(vbios_map * map,uint16_t res)288 static vbios_resolution_type3 * map_type3_resolution(vbios_map * map,
289 uint16_t res)
290 {
291 vbios_resolution_type3 * ptr = ((vbios_resolution_type3*)(map->bios_ptr + res));
292 return ptr;
293 }
294
295
detect_bios_type(vbios_map * map,int entry_size)296 static bool detect_bios_type(vbios_map * map, int entry_size)
297 {
298 unsigned int i;
299 uint16_t r1, r2;
300
301 r1 = r2 = 32000;
302
303 for (i = 0; i < map->mode_table_size; i++) {
304 if (map->mode_table[i].resolution <= r1) {
305 r1 = map->mode_table[i].resolution;
306 } else if (map->mode_table[i].resolution <= r2) {
307 r2 = map->mode_table[i].resolution;
308 }
309 }
310
311 return ((r2-r1-6) % entry_size) == 0;
312 }
313
close_vbios(vbios_map * map)314 static inline void close_vbios(vbios_map *map)
315 {
316 (void)map;
317 }
318
open_vbios(void)319 static vbios_map * open_vbios(void)
320 {
321 static vbios_map _map;
322 vbios_map * const map = &_map;
323
324 memset(&_map, 0, sizeof _map);
325
326 /*
327 * Determine chipset
328 */
329 map->chipset_id = get_chipset_id();
330 good_marker(0x10);
331 map->chipset = get_chipset(map->chipset_id);
332 good_marker(0x11);
333
334 /*
335 * Map the video bios to memory
336 */
337 map->bios_ptr = (void *)VBIOS_START;
338
339 /*
340 * check if we have ATI Radeon
341 */
342
343 if (memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE1, strlen(ATI_SIGNATURE1)) ||
344 memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE2, strlen(ATI_SIGNATURE2)) ) {
345 debug("ATI chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\r\n");
346 return NULL;
347 }
348
349 /*
350 * check if we have NVIDIA
351 */
352
353 if (memmem(map->bios_ptr, VBIOS_SIZE, NVIDIA_SIGNATURE, strlen(NVIDIA_SIGNATURE))) {
354 debug("NVIDIA chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\r\n");
355 return NULL;
356 }
357
358 /*
359 * check if we have Intel
360 */
361
362 if (map->chipset == CT_UNKWN && memmem(map->bios_ptr, VBIOS_SIZE, INTEL_SIGNATURE, strlen(INTEL_SIGNATURE))) {
363 debug("Intel chipset detected. However, 915resolution was unable to determine the chipset type.\r\n");
364
365 debug("Chipset Id: %x\r\n", map->chipset_id);
366
367 debug("Please report this problem to stomljen@yahoo.com\r\n");
368
369 close_vbios(map);
370 return NULL;
371 }
372
373 /*
374 * check for others
375 */
376
377 if (map->chipset == CT_UNKWN) {
378 debug("Unknown chipset type and unrecognized bios.\r\n");
379 debug("915resolution only works with Intel 800/900 series graphic chipsets.\r\n");
380
381 debug("Chipset Id: %x\r\n", map->chipset_id);
382 close_vbios(map);
383 return NULL;
384 }
385
386 /*
387 * Figure out where the mode table is
388 */
389 good_marker(0x12);
390
391 {
392 address p = map->bios_ptr + 16;
393 address limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode));
394
395 while (p < limit && map->mode_table == 0) {
396 vbios_mode * mode_ptr = (vbios_mode *) p;
397
398 if (((mode_ptr[0].mode & 0xf0) == 0x30) && ((mode_ptr[1].mode & 0xf0) == 0x30) &&
399 ((mode_ptr[2].mode & 0xf0) == 0x30) && ((mode_ptr[3].mode & 0xf0) == 0x30)) {
400
401 map->mode_table = mode_ptr;
402 }
403
404 p++;
405 }
406
407 if (map->mode_table == 0) {
408 debug("Unable to locate the mode table.\r\n");
409 close_vbios(map);
410 return NULL;
411 }
412 }
413 good_marker(0x13);
414
415 /*
416 * Determine size of mode table
417 */
418
419 {
420 vbios_mode * mode_ptr = map->mode_table;
421
422 while (mode_ptr->mode != 0xff) {
423 map->mode_table_size++;
424 mode_ptr++;
425 }
426 }
427 good_marker(0x14);
428 status("mode_table_size = %d", map->mode_table_size);
429
430 /*
431 * Figure out what type of bios we have
432 * order of detection is important
433 */
434
435 if (detect_bios_type(map, sizeof(vbios_modeline_type3))) {
436 map->bios = BT_3;
437 }
438 else if (detect_bios_type(map, sizeof(vbios_modeline_type2))) {
439 map->bios = BT_2;
440 }
441 else if (detect_bios_type(map, sizeof(vbios_resolution_type1))) {
442 map->bios = BT_1;
443 }
444 else {
445 debug("Unable to determine bios type.\r\n");
446 debug("Mode Table Offset: $C0000 + $%x\r\n", ((unsigned int)map->mode_table) - ((unsigned int)map->bios_ptr));
447 debug("Mode Table Entries: %u\r\n", map->mode_table_size);
448 bad_marker(0x15);
449 return NULL;
450 }
451 good_marker(0x15);
452
453 return map;
454 }
455
unlock_vbios(vbios_map * map)456 static void unlock_vbios(vbios_map * map)
457 {
458 assert(!map->unlocked);
459
460 map->unlocked = true;
461
462 switch (map->chipset) {
463 case CT_UNKWN:
464 case CHIPSET_TYPES: /* Shut up gcc */
465 break;
466 case CT_830:
467 case CT_855GM:
468 map->b1 = pci_readb(0x8000005a);
469 pci_writeb(0x33, 0x8000005a);
470 break;
471 case CT_845G:
472 case CT_865G:
473 case CT_915G:
474 case CT_915GM:
475 case CT_945G:
476 case CT_945GM:
477 case CT_945GME:
478 case CT_946GZ:
479 case CT_G965:
480 case CT_Q965:
481 map->b1 = pci_readb(0x80000091);
482 map->b2 = pci_readb(0x80000092);
483 pci_writeb(0x33, 0x80000091);
484 pci_writeb(0x33, 0x80000092);
485 break;
486 }
487
488 #if DEBUG
489 {
490 unsigned int t = inl(0xcfc);
491 debug("unlock PAM: (0x%08x)\r\n", t);
492 }
493 #endif
494 }
495
relock_vbios(vbios_map * map)496 static void relock_vbios(vbios_map * map)
497 {
498 assert(map->unlocked);
499 map->unlocked = false;
500
501 switch (map->chipset) {
502 case CT_UNKWN:
503 case CHIPSET_TYPES: /* Shut up gcc */
504 break;
505 case CT_830:
506 case CT_855GM:
507 pci_writeb(map->b1, 0x8000005a);
508 break;
509 case CT_845G:
510 case CT_865G:
511 case CT_915G:
512 case CT_915GM:
513 case CT_945G:
514 case CT_945GM:
515 case CT_945GME:
516 case CT_946GZ:
517 case CT_G965:
518 case CT_Q965:
519 pci_writeb(map->b1, 0x80000091);
520 pci_writeb(map->b2, 0x80000092);
521 break;
522 }
523
524 #if DEBUG
525 {
526 unsigned int t = inl(0xcfc);
527 debug("relock PAM: (0x%08x)\r\n", t);
528 }
529 #endif
530 }
531
532 #if 0
533 static void list_modes(vbios_map *map, unsigned int raw)
534 {
535 unsigned int i, x, y;
536
537 for (i=0; i < map->mode_table_size; i++) {
538 switch(map->bios) {
539 case BT_1:
540 {
541 vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);
542
543 x = ((((unsigned int) res->x2) & 0xf0) << 4) | res->x1;
544 y = ((((unsigned int) res->y2) & 0xf0) << 4) | res->y1;
545
546 if (x != 0 && y != 0) {
547 debug("Mode %02x : %dx%d, %d bits/pixel\r\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
548 }
549
550 if (raw)
551 {
552 debug("Mode %02x (raw) :\r\n\t%02x %02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n", map->mode_table[i].mode, res->unknow1[0],res->unknow1[1], res->x1,res->x_total,res->x2,res->y1,res->y_total,res->y2);
553 }
554
555 }
556 break;
557 case BT_2:
558 {
559 vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);
560
561 x = res->modelines[0].x1+1;
562 y = res->modelines[0].y1+1;
563
564 if (x != 0 && y != 0) {
565 debug("Mode %02x : %dx%d, %d bits/pixel\r\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
566 }
567 }
568 break;
569 case BT_3:
570 {
571 vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);
572
573 x = res->modelines[0].x1+1;
574 y = res->modelines[0].y1+1;
575
576 if (x != 0 && y != 0) {
577 debug("Mode %02x : %dx%d, %d bits/pixel\r\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
578 }
579 }
580 break;
581 case BT_UNKWN:
582 break;
583 }
584 }
585 }
586 #endif
587
gtf_timings(int x,int y,int freq,uint32_t * clock,uint16_t * hsyncstart,uint16_t * hsyncend,uint16_t * hblank,uint16_t * vsyncstart,uint16_t * vsyncend,uint16_t * vblank)588 static void gtf_timings(int x, int y, int freq, uint32_t *clock,
589 uint16_t *hsyncstart, uint16_t *hsyncend, uint16_t *hblank,
590 uint16_t *vsyncstart, uint16_t *vsyncend, uint16_t *vblank)
591 {
592 int hbl, vbl, vfreq;
593
594 vbl = y + (y+1)/(20000.0/(11*freq) - 1) + 1.5;
595 vfreq = vbl * freq;
596 hbl = 16 * (int)(x * (30.0 - 300000.0 / vfreq) /
597 (70.0 + 300000.0 / vfreq) / 16.0 + 0.5);
598
599 *vsyncstart = y;
600 *vsyncend = y + 3;
601 *vblank = vbl - 1;
602 *hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1;
603 *hsyncend = x + hbl / 2 - 1;
604 *hblank = x + hbl - 1;
605 *clock = (x + hbl) * vfreq / 1000;
606 }
607
set_mode(vbios_map * map,unsigned int mode,unsigned int x,unsigned int y,unsigned int bp,unsigned int htotal,unsigned int vtotal)608 static int set_mode(vbios_map * map, unsigned int mode,
609 unsigned int x, unsigned int y, unsigned int bp,
610 unsigned int htotal, unsigned int vtotal)
611 {
612 int xprev, yprev;
613 unsigned int i, j;
614 int rv = -1;
615
616 for (i=0; i < map->mode_table_size; i++) {
617 if (map->mode_table[i].mode == mode) {
618 switch(map->bios) {
619 case BT_1:
620 {
621 vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);
622 uint32_t clock;
623 uint16_t hsyncstart, hsyncend, hblank;
624 uint16_t vsyncstart, vsyncend, vblank;
625
626 if (bp) {
627 map->mode_table[i].bits_per_pixel = bp;
628 }
629
630 gtf_timings(x, y, freqs[0], &clock,
631 &hsyncstart, &hsyncend, &hblank,
632 &vsyncstart, &vsyncend, &vblank);
633
634 status("x = %d, y = %d, clock = %lu, h = %d %d %d, v = %d %d %d\n",
635 x, y, clock,
636 hsyncstart, hsyncend, hblank,
637 vsyncstart, vsyncend, vblank);
638
639 htotal = htotal ? htotal : (unsigned int)hblank+1;
640 vtotal = vtotal ? vtotal : (unsigned int)vblank+1;
641
642 res->clock = clock/10; /* Units appear to be 10 kHz */
643 res->x2 = (((htotal-x) >> 8) & 0x0f) | ((x >> 4) & 0xf0);
644 res->x1 = (x & 0xff);
645
646 res->y2 = (((vtotal-y) >> 8) & 0x0f) | ((y >> 4) & 0xf0);
647 res->y1 = (y & 0xff);
648 if (htotal)
649 res->x_total = ((htotal-x) & 0xff);
650
651 if (vtotal)
652 res->y_total = ((vtotal-y) & 0xff);
653
654 rv = 0;
655 }
656 break;
657 case BT_2:
658 {
659 vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);
660
661 res->xchars = x / 8;
662 res->ychars = y / 16 - 1;
663 xprev = res->modelines[0].x1;
664 yprev = res->modelines[0].y1;
665
666 for(j=0; j < 3; j++) {
667 vbios_modeline_type2 * modeline = &res->modelines[j];
668
669 if (modeline->x1 == xprev && modeline->y1 == yprev) {
670 modeline->x1 = modeline->x2 = x-1;
671 modeline->y1 = modeline->y2 = y-1;
672
673 gtf_timings(x, y, freqs[j], &modeline->clock,
674 &modeline->hsyncstart, &modeline->hsyncend,
675 &modeline->hblank, &modeline->vsyncstart,
676 &modeline->vsyncend, &modeline->vblank);
677
678 if (htotal)
679 modeline->htotal = htotal;
680 else
681 modeline->htotal = modeline->hblank;
682
683 if (vtotal)
684 modeline->vtotal = vtotal;
685 else
686 modeline->vtotal = modeline->vblank;
687 }
688 }
689
690 rv = 0;
691 }
692 break;
693 case BT_3:
694 {
695 vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);
696
697 xprev = res->modelines[0].x1;
698 yprev = res->modelines[0].y1;
699
700 for (j=0; j < 3; j++) {
701 vbios_modeline_type3 * modeline = &res->modelines[j];
702
703 if (modeline->x1 == xprev && modeline->y1 == yprev) {
704 modeline->x1 = modeline->x2 = x-1;
705 modeline->y1 = modeline->y2 = y-1;
706
707 gtf_timings(x, y, freqs[j], &modeline->clock,
708 &modeline->hsyncstart, &modeline->hsyncend,
709 &modeline->hblank, &modeline->vsyncstart,
710 &modeline->vsyncend, &modeline->vblank);
711 if (htotal)
712 modeline->htotal = htotal;
713 else
714 modeline->htotal = modeline->hblank;
715 if (vtotal)
716 modeline->vtotal = vtotal;
717 else
718 modeline->vtotal = modeline->vblank;
719
720 modeline->timing_h = y-1;
721 modeline->timing_v = x-1;
722 }
723 }
724
725 rv = 0;
726 }
727 break;
728 case BT_UNKWN:
729 break;
730 }
731 }
732 }
733
734 return rv;
735 }
736
display_map_info(vbios_map * map)737 static inline void display_map_info(vbios_map * map) {
738 #ifdef DEBUG
739 static const char * bios_type_names[] =
740 {"UNKNOWN", "TYPE 1", "TYPE 2", "TYPE 3"};
741 static const char * chipset_type_names[] = {
742 "UNKNOWN", "830", "845G", "855GM", "865G", "915G", "915GM", "945G",
743 "945GM", "946GZ", "G965", "Q965", "945GME"
744 };
745
746 debug("Chipset: %s\r\n", chipset_type_names[map->chipset]);
747 debug("BIOS: %s\r\n", bios_type_names[map->bios]);
748
749 debug("Mode Table Offset: $C0000 + $%x\r\n",
750 ((unsigned int)map->mode_table) - ((unsigned int)map->bios_ptr));
751 debug("Mode Table Entries: %u\r\n", map->mode_table_size);
752 #endif
753 (void)map;
754 }
755
__vesacon_i915resolution(int x,int y)756 int __vesacon_i915resolution(int x, int y)
757 {
758 vbios_map * map;
759 unsigned int mode = 0x52; /* 800x600x32 mode in known BIOSes */
760 unsigned int bp = 32; /* 32 bits per pixel */
761 int rv = 0;
762
763 good_marker(0);
764
765 map = open_vbios();
766 if (!map)
767 return -1;
768
769 good_marker(1);
770
771 display_map_info(map);
772
773 debug("\r\n");
774
775 if (mode && x && y) {
776 good_marker(2);
777 cli();
778 good_marker(3);
779 unlock_vbios(map);
780 good_marker(4);
781 rv = set_mode(map, mode, x, y, bp, 0, 0);
782 if (rv)
783 bad_marker(5);
784 else
785 good_marker(5);
786 relock_vbios(map);
787 good_marker(6);
788 sti();
789
790 debug("Patch mode %02x to resolution %dx%d complete\r\n", mode, x, y);
791 }
792 close_vbios(map);
793
794 return rv;
795 }
796