Home | History | Annotate | Download | only in vesa
      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
    204 static inline void good_marker(int x) { (void)x; }
    205 static inline void bad_marker(int x) { (void)x; }
    206 static inline void status(const char *fmt, ...) { (void)fmt; }
    207 #endif
    208 
    209 static unsigned int get_chipset_id(void) {
    210     return pci_readl(0x80000000);
    211 }
    212 
    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 
    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 
    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 
    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 
    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 
    314 static inline void close_vbios(vbios_map *map)
    315 {
    316     (void)map;
    317 }
    318 
    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 (at) 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 
    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 
    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 
    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 
    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 
    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 
    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