1 /* ----------------------------------------------------------------------- *
3 * Copyright 2010 Intel Corporation; author: H. Peter Anvin
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
14 * The above copyright notice and this permission notice shall
15 * be included in all copies or substantial portions of the Software.
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.
26 * ----------------------------------------------------------------------- */
31 * 915 resolution by steve tomljenovic
33 * This was tested only on Sony VGN-FS550. Use at your own risk
35 * This code is based on the techniques used in :
37 * - 855patch. Many thanks to Christian Zietz (czietz gmx net)
38 * for demonstrating how to shadow the VBIOS into system RAM
41 * - 1280patch by Andrew Tipton (andrewtipton null li).
43 * - 855resolution by Alain Poirier
45 * This source code is into the public domain.
62 #define VBIOS_START 0xc0000
63 #define VBIOS_SIZE 0x10000
65 #define MODE_TABLE_OFFSET_845G 617
67 #define VERSION "0.5.3"
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"
74 typedef unsigned char * address
;
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
,
83 BT_UNKWN
, BT_1
, BT_2
, BT_3
86 static int freqs
[] = { 60, 75, 85 };
90 uint8_t bits_per_pixel
;
93 } __attribute__((packed
)) vbios_mode
;
96 uint16_t clock
; /* Clock frequency in 10 kHz */
103 } __attribute__((packed
)) vbios_resolution_type1
;
121 } __attribute__((packed
)) vbios_modeline_type2
;
128 vbios_modeline_type2 modelines
[];
129 } __attribute__((packed
)) vbios_resolution_type2
;
152 } __attribute__((packed
)) vbios_modeline_type3
;
155 unsigned char unknown
[6];
157 vbios_modeline_type3 modelines
[];
158 } __attribute__((packed
)) vbios_resolution_type3
;
162 unsigned int chipset_id
;
163 chipset_type chipset
;
168 vbios_mode
* mode_table
;
169 unsigned int mode_table_size
;
176 #if 0 /* Debugging hacks */
177 static void good_marker(int x
)
179 ((uint16_t *)0xb8000)[x
] = 0x2f30 - ((x
& 0xf0) << 4) + (x
& 0x0f);
182 static void bad_marker(int x
)
184 ((uint16_t *)0xb8000)[x
] = 0x4f30 - ((x
& 0xf0) << 4) + (x
& 0x0f);
187 static void status(const char *fmt
, ...)
194 memset(msg
, 0, sizeof msg
);
196 vsnprintf(msg
, sizeof msg
, fmt
, ap
);
199 q
= (uint16_t *)0xb8000 + 80;
200 for (i
= 0; i
< 80; i
++)
201 *q
++ = *p
++ + 0x1f00;
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
; }
209 static unsigned int get_chipset_id(void) {
210 return pci_readl(0x80000000);
213 static chipset_type
get_chipset(unsigned int id
) {
274 static vbios_resolution_type1
* map_type1_resolution(vbios_map
* map
,
277 vbios_resolution_type1
* ptr
= ((vbios_resolution_type1
*)(map
->bios_ptr
+ res
));
281 static vbios_resolution_type2
* map_type2_resolution(vbios_map
* map
,
284 vbios_resolution_type2
* ptr
= ((vbios_resolution_type2
*)(map
->bios_ptr
+ res
));
288 static vbios_resolution_type3
* map_type3_resolution(vbios_map
* map
,
291 vbios_resolution_type3
* ptr
= ((vbios_resolution_type3
*)(map
->bios_ptr
+ res
));
296 static bool detect_bios_type(vbios_map
* map
, int entry_size
)
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
;
311 return ((r2
-r1
-6) % entry_size
) == 0;
314 static inline void close_vbios(vbios_map
*map
)
319 static vbios_map
* open_vbios(void)
321 static vbios_map _map
;
322 vbios_map
* const map
= &_map
;
324 memset(&_map
, 0, sizeof _map
);
329 map
->chipset_id
= get_chipset_id();
331 map
->chipset
= get_chipset(map
->chipset_id
);
335 * Map the video bios to memory
337 map
->bios_ptr
= (void *)VBIOS_START
;
340 * check if we have ATI Radeon
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");
350 * check if we have NVIDIA
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");
359 * check if we have Intel
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");
365 debug("Chipset Id: %x\r\n", map
->chipset_id
);
367 debug("Please report this problem to stomljen@yahoo.com\r\n");
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");
381 debug("Chipset Id: %x\r\n", map
->chipset_id
);
387 * Figure out where the mode table is
392 address p
= map
->bios_ptr
+ 16;
393 address limit
= map
->bios_ptr
+ VBIOS_SIZE
- (3 * sizeof(vbios_mode
));
395 while (p
< limit
&& map
->mode_table
== 0) {
396 vbios_mode
* mode_ptr
= (vbios_mode
*) p
;
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)) {
401 map
->mode_table
= mode_ptr
;
407 if (map
->mode_table
== 0) {
408 debug("Unable to locate the mode table.\r\n");
416 * Determine size of mode table
420 vbios_mode
* mode_ptr
= map
->mode_table
;
422 while (mode_ptr
->mode
!= 0xff) {
423 map
->mode_table_size
++;
428 status("mode_table_size = %d", map
->mode_table_size
);
431 * Figure out what type of bios we have
432 * order of detection is important
435 if (detect_bios_type(map
, sizeof(vbios_modeline_type3
))) {
438 else if (detect_bios_type(map
, sizeof(vbios_modeline_type2
))) {
441 else if (detect_bios_type(map
, sizeof(vbios_resolution_type1
))) {
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
);
456 static void unlock_vbios(vbios_map
* map
)
458 assert(!map
->unlocked
);
460 map
->unlocked
= true;
462 switch (map
->chipset
) {
464 case CHIPSET_TYPES
: /* Shut up gcc */
468 map
->b1
= pci_readb(0x8000005a);
469 pci_writeb(0x33, 0x8000005a);
481 map
->b1
= pci_readb(0x80000091);
482 map
->b2
= pci_readb(0x80000092);
483 pci_writeb(0x33, 0x80000091);
484 pci_writeb(0x33, 0x80000092);
490 unsigned int t
= inl(0xcfc);
491 debug("unlock PAM: (0x%08x)\r\n", t
);
496 static void relock_vbios(vbios_map
* map
)
498 assert(map
->unlocked
);
499 map
->unlocked
= false;
501 switch (map
->chipset
) {
503 case CHIPSET_TYPES
: /* Shut up gcc */
507 pci_writeb(map
->b1
, 0x8000005a);
519 pci_writeb(map
->b1
, 0x80000091);
520 pci_writeb(map
->b2
, 0x80000092);
526 unsigned int t
= inl(0xcfc);
527 debug("relock PAM: (0x%08x)\r\n", t
);
533 static void list_modes(vbios_map
*map
, unsigned int raw
)
535 unsigned int i
, x
, y
;
537 for (i
=0; i
< map
->mode_table_size
; i
++) {
541 vbios_resolution_type1
* res
= map_type1_resolution(map
, map
->mode_table
[i
].resolution
);
543 x
= ((((unsigned int) res
->x2
) & 0xf0) << 4) | res
->x1
;
544 y
= ((((unsigned int) res
->y2
) & 0xf0) << 4) | res
->y1
;
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
);
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
);
559 vbios_resolution_type2
* res
= map_type2_resolution(map
, map
->mode_table
[i
].resolution
);
561 x
= res
->modelines
[0].x1
+1;
562 y
= res
->modelines
[0].y1
+1;
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
);
571 vbios_resolution_type3
* res
= map_type3_resolution(map
, map
->mode_table
[i
].resolution
);
573 x
= res
->modelines
[0].x1
+1;
574 y
= res
->modelines
[0].y1
+1;
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
);
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
)
594 vbl
= y
+ (y
+1)/(20000.0/(11*freq
) - 1) + 1.5;
596 hbl
= 16 * (int)(x
* (30.0 - 300000.0 / vfreq
) /
597 (70.0 + 300000.0 / vfreq
) / 16.0 + 0.5);
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;
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
)
616 for (i
=0; i
< map
->mode_table_size
; i
++) {
617 if (map
->mode_table
[i
].mode
== mode
) {
621 vbios_resolution_type1
* res
= map_type1_resolution(map
, map
->mode_table
[i
].resolution
);
623 uint16_t hsyncstart
, hsyncend
, hblank
;
624 uint16_t vsyncstart
, vsyncend
, vblank
;
627 map
->mode_table
[i
].bits_per_pixel
= bp
;
630 gtf_timings(x
, y
, freqs
[0], &clock
,
631 &hsyncstart
, &hsyncend
, &hblank
,
632 &vsyncstart
, &vsyncend
, &vblank
);
634 status("x = %d, y = %d, clock = %lu, h = %d %d %d, v = %d %d %d\n",
636 hsyncstart
, hsyncend
, hblank
,
637 vsyncstart
, vsyncend
, vblank
);
639 htotal
= htotal
? htotal
: (unsigned int)hblank
+1;
640 vtotal
= vtotal
? vtotal
: (unsigned int)vblank
+1;
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);
646 res
->y2
= (((vtotal
-y
) >> 8) & 0x0f) | ((y
>> 4) & 0xf0);
647 res
->y1
= (y
& 0xff);
649 res
->x_total
= ((htotal
-x
) & 0xff);
652 res
->y_total
= ((vtotal
-y
) & 0xff);
659 vbios_resolution_type2
* res
= map_type2_resolution(map
, map
->mode_table
[i
].resolution
);
662 res
->ychars
= y
/ 16 - 1;
663 xprev
= res
->modelines
[0].x1
;
664 yprev
= res
->modelines
[0].y1
;
666 for(j
=0; j
< 3; j
++) {
667 vbios_modeline_type2
* modeline
= &res
->modelines
[j
];
669 if (modeline
->x1
== xprev
&& modeline
->y1
== yprev
) {
670 modeline
->x1
= modeline
->x2
= x
-1;
671 modeline
->y1
= modeline
->y2
= y
-1;
673 gtf_timings(x
, y
, freqs
[j
], &modeline
->clock
,
674 &modeline
->hsyncstart
, &modeline
->hsyncend
,
675 &modeline
->hblank
, &modeline
->vsyncstart
,
676 &modeline
->vsyncend
, &modeline
->vblank
);
679 modeline
->htotal
= htotal
;
681 modeline
->htotal
= modeline
->hblank
;
684 modeline
->vtotal
= vtotal
;
686 modeline
->vtotal
= modeline
->vblank
;
695 vbios_resolution_type3
* res
= map_type3_resolution(map
, map
->mode_table
[i
].resolution
);
697 xprev
= res
->modelines
[0].x1
;
698 yprev
= res
->modelines
[0].y1
;
700 for (j
=0; j
< 3; j
++) {
701 vbios_modeline_type3
* modeline
= &res
->modelines
[j
];
703 if (modeline
->x1
== xprev
&& modeline
->y1
== yprev
) {
704 modeline
->x1
= modeline
->x2
= x
-1;
705 modeline
->y1
= modeline
->y2
= y
-1;
707 gtf_timings(x
, y
, freqs
[j
], &modeline
->clock
,
708 &modeline
->hsyncstart
, &modeline
->hsyncend
,
709 &modeline
->hblank
, &modeline
->vsyncstart
,
710 &modeline
->vsyncend
, &modeline
->vblank
);
712 modeline
->htotal
= htotal
;
714 modeline
->htotal
= modeline
->hblank
;
716 modeline
->vtotal
= vtotal
;
718 modeline
->vtotal
= modeline
->vblank
;
720 modeline
->timing_h
= y
-1;
721 modeline
->timing_v
= x
-1;
737 static inline void display_map_info(vbios_map
* map
) {
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"
746 debug("Chipset: %s\r\n", chipset_type_names
[map
->chipset
]);
747 debug("BIOS: %s\r\n", bios_type_names
[map
->bios
]);
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
);
756 int __vesacon_i915resolution(int x
, int y
)
759 unsigned int mode
= 0x52; /* 800x600x32 mode in known BIOSes */
760 unsigned int bp
= 32; /* 32 bits per pixel */
771 display_map_info(map
);
775 if (mode
&& x
&& y
) {
781 rv
= set_mode(map
, mode
, x
, y
, bp
, 0, 0);
790 debug("Patch mode %02x to resolution %dx%d complete\r\n", mode
, x
, y
);