Chameleon

Chameleon Svn Source Tree

Root/branches/autoResolution/i386/libsaio/autoresolution.c

1
2/* Copied from 915 resolution created by steve tomljenovic
3 *
4 * This code is based on the techniques used in :
5 *
6 * - 855patch. Many thanks to Christian Zietz (czietz gmx net)
7 * for demonstrating how to shadow the VBIOS into system RAM
8 * and then modify it.
9 *
10 * - 1280patch by Andrew Tipton (andrewtipton null li).
11 *
12 * - 855resolution by Alain Poirier
13 *
14 * This source code is into the public domain.
15 */
16
17#include "libsaio.h"
18#include "autoresolution.h"
19#include "nvidia_resolution.h"
20#include "ati_resolution.h"
21#include "gma_resolution.h"
22#include "../boot2/graphics.h"
23
24char * chipset_type_names[] = {
25"UNKNOWN", "830", "845G", "855GM", "865G", "915G", "915GM", "945G", "945GM", "945GME",
26"946GZ", "955X", "G965", "Q965", "965GM", "975X",
27"P35", "X48", "B43", "Q45", "P45", "GM45", "G41", "G31", "G45", "500"
28};
29
30UInt32 get_chipset_id(void) {
31outl(0xcf8, 0x80000000);
32return inl(0xcfc);
33}
34
35chipset_type get_chipset(UInt32 id) {
36chipset_type type;
37
38switch (id) {
39case 0x35758086:
40type = CT_830;
41break;
42
43case 0x25608086:
44type = CT_845G;
45break;
46
47case 0x35808086:
48type = CT_855GM;
49break;
50
51case 0x25708086:
52type = CT_865G;
53break;
54
55case 0x25808086:
56type = CT_915G;
57break;
58
59case 0x25908086:
60type = CT_915GM;
61break;
62
63case 0x27708086:
64type = CT_945G;
65break;
66
67case 0x27748086:
68type = CT_955X;
69break;
70
71case 0x277c8086:
72type = CT_975X;
73break;
74
75case 0x27a08086:
76type = CT_945GM;
77break;
78
79case 0x27ac8086:
80type = CT_945GME;
81break;
82
83case 0x29708086:
84type = CT_946GZ;
85break;
86
87case 0x29a08086:
88type = CT_G965;
89break;
90
91case 0x29908086:
92type = CT_Q965;
93break;
94
95case 0x2a008086:
96type = CT_965GM;
97break;
98
99case 0x29e08086:
100type = CT_X48;
101break;
102
103case 0x2a408086:
104type = CT_GM45;
105break;
106
107case 0x2e108086:
108case 0X2e908086:
109type = CT_B43;
110break;
111
112case 0x2e208086:
113type = CT_P45;
114break;
115
116case 0x2e308086:
117type = CT_G41;
118break;
119
120case 0x29c08086:
121type = CT_G31;
122break;
123
124case 0x29208086:
125type = CT_G45;
126break;
127
128case 0x81008086:
129type = CT_500;
130break;
131
132default:
133type = CT_UNKWN;
134break;
135}
136return type;
137}
138
139
140void gtf_timings(UInt32 x, UInt32 y, UInt32 freq,
141 unsigned long *clock,
142 UInt16 *hsyncstart, UInt16 *hsyncend, UInt16 *hblank,
143 UInt16 *vsyncstart, UInt16 *vsyncend, UInt16 *vblank)
144{
145UInt32 hbl, vbl, vfreq;
146
147vbl = y + (y+1)/(20000/(11*freq) - 1) + 1;
148
149vfreq = vbl * freq;
150hbl = 16 * (int)(x * (30 - 300000 / vfreq) /
151 + (70 + 300000 / vfreq) / 16 + 0);
152
153*vsyncstart = y;
154*vsyncend = y + 3;
155*vblank = vbl;
156*hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 ;
157*hsyncend = x + hbl / 2;
158*hblank = x + hbl;
159*clock = (x + hbl) * vfreq / 1000;
160}
161
162
163void get_aspect_ratio(s_aspect* aspect, UInt32 x, UInt32 y)
164{
165if ((y * 16 / 9) == x) {
166aspect->width = 16;
167aspect->height = 9;
168} else if ((y * 16 / 10) == x) {
169aspect->width = 16;
170aspect->height = 10;
171} else if ((y * 5 / 4) == x) {
172aspect->width = 5;
173aspect->height = 4;
174} else if ((y * 15 / 9) == x) {
175aspect->width = 15;
176aspect->height = 9;
177} else {
178aspect->width = 4;
179aspect->height = 3;
180}
181verbose("Aspect Ratio is %d/%d\n", aspect->width, aspect->height);
182}
183
184void cvt_timings(UInt32 x, UInt32 y, UInt32 freq,
185 unsigned long *clock,
186 UInt16 *hsyncstart, UInt16 *hsyncend, UInt16 *hblank,
187 UInt16 *vsyncstart, UInt16 *vsyncend, UInt16 *vblank, bool reduced)
188{
189UInt32 hbl, hbp, vbl, vsync, hperiod;
190
191if (!(y % 3) && ((y * 4 / 3) == x))
192 vsync = 4;
193 else if (!(y % 9) && ((y * 16 / 9) == x))
194 vsync = 5;
195 else if (!(y % 10) && ((y * 16 / 10) == x))
196 vsync = 6;
197 else if (!(y % 4) && ((y * 5 / 4) == x))
198 vsync = 7;
199 else if (!(y % 9) && ((y * 15 / 9) == x))
200 vsync = 7;
201 else /* Custom */
202 vsync = 10;
203
204if (!reduced) {
205hperiod = (1000000/freq - 550) / (y + 3);
206vbl = y + (550/hperiod) + 3;
207hbp = 30 - ((300*hperiod)/1000);
208hbl = (x * hbp) / (100 - hbp);
209
210*vsyncstart = y + 6;
211*vsyncend = *vsyncstart + vsync;
212*vblank = vbl - 1;
213*hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1;
214*hsyncend = x + hbl / 2 - 1;
215*hblank = x + hbl - 1;
216
217} else {
218hperiod = (1000000/freq - 460) / y;
219vbl = y + 460/hperiod + 1;
220hbl = 160;
221
222*vsyncstart = y + 3;
223*vsyncend = *vsyncstart + vsync;
224*vblank = vbl - 1;
225*hsyncstart = x + hbl / 2 - 32;
226*hsyncend = x + hbl / 2 - 1;
227*hblank = x + hbl - 1;
228
229}
230*clock = (x + hbl) * 1000 / hperiod;
231}
232
233
234
235void close_vbios(vbios_map * map);
236
237vbios_map * open_vbios(chipset_type forced_chipset) {
238UInt32 z;
239vbios_map * map = NEW(vbios_map);
240for(z=0; z<sizeof(vbios_map); z++) ((char*)map)[z]=0;
241
242/*
243 * Determine chipset
244 */
245
246if (forced_chipset == CT_UNKWN) {
247map->chipset_id = get_chipset_id();
248map->chipset = get_chipset(map->chipset_id);
249verbose("Chipset is %s (pci id 0x%x)\n",chipset_type_names[map->chipset], map->chipset_id);
250}
251else if (forced_chipset != CT_UNKWN) {
252map->chipset = forced_chipset;
253}
254else {
255map->chipset = CT_915GM;
256}
257
258/*
259 * Map the video bios to memory
260 */
261
262map->bios_ptr=(unsigned char*)VBIOS_START;
263
264/*
265 * check if we have ATI Radeon and open atombios
266 */
267bios_tables_t ati_tables;
268
269ati_tables.base = map->bios_ptr;
270ati_tables.AtomRomHeader = (ATOM_ROM_HEADER *) (map->bios_ptr + *(unsigned short *) (map->bios_ptr + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER));
271if (strcmp ((char *) ati_tables.AtomRomHeader->uaFirmWareSignature, "ATOM") == 0) {
272map->bios = BT_ATI_1;
273verbose("We have an AtomBios Card\n");
274return open_ati_vbios(map, ati_tables);
275}
276
277
278/*
279 * check if we have NVidia
280 */
281if (map->bios != BT_ATI_1) {
282int i = 0;
283while (i < 512) { // we don't need to look through the whole bios, just the firs 512 bytes
284if ((map->bios_ptr[i] == 'N')
285&& (map->bios_ptr[i+1] == 'V')
286&& (map->bios_ptr[i+2] == 'I')
287&& (map->bios_ptr[i+3] == 'D'))
288{
289map->bios = BT_NVDA;
290verbose("We have an NVIDIA Card\n");
291return open_nvidia_vbios(map);
292break;
293}
294i++;
295}
296}
297
298/*
299 * check if we have Intel
300 */
301
302if ((map->bios != BT_ATI_1) && (map->bios != BT_NVDA)) {
303int i = 0;
304while (i < VBIOS_SIZE) { // we don't need to look through the whole bios, just the firs 512 bytes
305if ((map->bios_ptr[i] == 'I')
306&& (map->bios_ptr[i+1] == 'n')
307&& (map->bios_ptr[i+2] == 't')
308&& (map->bios_ptr[i+3] == 'e')
309&& (map->bios_ptr[i+4] == 'l'))
310{
311map->bios = BT_1;
312verbose("We have an Intel Card\n");
313return open_intel_vbios(map);
314break;
315}
316i++;
317}
318}
319
320/*
321 * Unidentified Chipset
322 */
323
324if ( (map->chipset == CT_UNKWN) || ((map->bios != BT_ATI_1) && (map->bios != BT_NVDA) && (map->bios != BT_1)) )
325{
326printf("Unknown chipset type and unrecognized bios.\n");
327
328printf("autoresolution only works with Intel 800/900 series graphic chipsets.\n");
329
330printf("Chipset Id: %x\n", map->chipset_id);
331close_vbios(map);
332return 0;
333}
334
335/*
336 * Should never get there
337 */
338return 0;
339}
340
341void close_vbios(vbios_map * map) {
342if (autoResolution == TRUE) autoResolution = FALSE;
343FREE(map);
344}
345
346void unlock_vbios(vbios_map * map) {
347
348map->unlocked = TRUE;
349
350switch (map->chipset) {
351case CT_UNKWN:
352break;
353case CT_830:
354case CT_855GM:
355outl(0xcf8, 0x8000005a);
356map->b1 = inb(0xcfe);
357
358outl(0xcf8, 0x8000005a);
359outb(0xcfe, 0x33);
360break;
361case CT_845G:
362case CT_865G:
363case CT_915G:
364case CT_915GM:
365case CT_945G:
366case CT_945GM:
367case CT_945GME:
368case CT_946GZ:
369case CT_955X:
370case CT_G965:
371case CT_Q965:
372case CT_965GM:
373case CT_975X:
374case CT_P35:
375case CT_X48:
376case CT_B43:
377case CT_Q45:
378case CT_P45:
379case CT_GM45:
380case CT_G41:
381case CT_G31:
382case CT_G45:
383case CT_500:
384
385outl(0xcf8, 0x80000090);
386map->b1 = inb(0xcfd);
387map->b2 = inb(0xcfe);
388outl(0xcf8, 0x80000090);
389outb(0xcfd, 0x33);
390outb(0xcfe, 0x33);
391break;
392}
393
394#if DEBUG
395{
396UInt32 t = inl(0xcfc);
397printf("unlock PAM: (0x%08x)\n", t);
398}
399#endif
400}
401
402void relock_vbios(vbios_map * map) {
403
404map->unlocked = FALSE;
405
406switch (map->chipset) {
407case CT_UNKWN:
408break;
409case CT_830:
410case CT_855GM:
411outl(0xcf8, 0x8000005a);
412outb(0xcfe, map->b1);
413break;
414case CT_845G:
415case CT_865G:
416case CT_915G:
417case CT_915GM:
418case CT_945G:
419case CT_945GM:
420case CT_945GME:
421case CT_946GZ:
422case CT_955X:
423case CT_G965:
424case CT_Q965:
425case CT_965GM:
426case CT_975X:
427case CT_P35:
428case CT_X48:
429case CT_B43:
430case CT_Q45:
431case CT_P45:
432case CT_GM45:
433case CT_G41:
434case CT_G31:
435case CT_G45:
436case CT_500:
437
438outl(0xcf8, 0x80000090);
439outb(0xcfd, map->b1);
440outb(0xcfe, map->b2);
441break;
442}
443
444#if DEBUG
445{
446 UInt32 t = inl(0xcfc);
447printf("relock PAM: (0x%08x)\n", t);
448}
449#endif
450}
451
452
453void save_vbios(vbios_map * map)
454{
455map->bios_backup_ptr = malloc(VBIOS_SIZE);
456bcopy((const unsigned char *)0xC0000, map->bios_backup_ptr, VBIOS_SIZE);
457}
458
459void restore_vbios(vbios_map * map)
460{
461bcopy(map->bios_backup_ptr,(unsigned char *)0xC0000, VBIOS_SIZE);
462}
463
464
465void patch_vbios(vbios_map * map, UInt32 x, UInt32 y, UInt32 bp, UInt32 htotal, UInt32 vtotal) {
466UInt32 i = 0;
467/*
468 * Get the aspect ratio for the requested mode
469 */
470get_aspect_ratio(&map->aspect_ratio, x, y);
471
472i = x = y = 0;
473
474if (map->bios != BT_NVDA) {
475verbose("%d modes to pacth\n", map->modeline_num);
476while (i < map->modeline_num) {
477if (x == 1400) x = 1440;
478if (x == 1600) x = 1680;
479
480y = x * map->aspect_ratio.height / map->aspect_ratio.width;
481switch (map->bios) {
482case BT_1:
483intel_set_mode_1(map, i, &x, &y);
484break;
485case BT_2:
486intel_set_mode_2(map, i, &x, &y);
487break;
488case BT_3:
489intel_set_mode_3(map, i, &x, &y);
490break;
491case BT_ATI_1:
492ati_set_mode_1(map, i, &x, &y);
493break;
494case BT_ATI_2:
495ati_set_mode_2(map, i, &x, &y);
496break;
497default:
498break;
499}
500i++;
501}
502}
503
504if (map->bios == BT_NVDA) {
505
506i = x = y = 0;
507while (i < map->modeline_num) {
508if (x == 0)x = 1024;
509if (x == 1400)x = 1440;
510if (x == 1600)x = 1680;
511
512y = x * map->aspect_ratio.height / map->aspect_ratio.width;
513nvidia_set_mode(map, i, &x, &y, MAIN_VESA_TABLE);
514i++;
515}
516
517i = x = y = 0;
518while (i < map->nv_modeline_num_2) {
519if (x == 1400) x = 1440;
520if (x == 1600) x = 1680;
521
522y = x * map->aspect_ratio.height / map->aspect_ratio.width;
523nvidia_set_mode(map, i, &x, &y, SECOND_VESA_TABLE);
524i++;
525}
526}
527}

Archive Download this file

Revision: 135