• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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