1 | /*␊ |
2 | * resolution.h␊ |
3 | * ␊ |
4 | *␉NOTE: I don't beleive this code is production ready / should be in trunk␊ |
5 | * Atleast, not in it's current state. ␊ |
6 | *␊ |
7 | * Created by Evan Lojewski on 3/4/10.␊ |
8 | * Copyright 2009. All rights reserved.␊ |
9 | *␊ |
10 | */␊ |
11 | #ifndef _RESOLUTION_H_␊ |
12 | #define _RESOLUTION_H_␊ |
13 | ␊ |
14 | //#include "libsaio.h"␊ |
15 | //#include "edid.h" //included␊ |
16 | #include "915resolution.h"␊ |
17 | ␊ |
18 | ␊ |
19 | void patchVideoBios()␊ |
20 | {␊ |
21 | ␉UInt32 x = 0, y = 0, bp = 0;␊ |
22 | ␉␊ |
23 | ␉getResolution(&x, &y, &bp);␊ |
24 | ␉verbose("getResolution: %dx%dx%d\n", (int)x, (int)y, (int)bp);␊ |
25 | ␉␊ |
26 | ␉if (x != 0 && y != 0 && bp != 0)␊ |
27 | ␉{␊ |
28 | ␉␉vbios_map * map;␊ |
29 | ␉␉␊ |
30 | ␉␉map = open_vbios(CT_UNKNOWN);␊ |
31 | ␉//␉if(map)␊ |
32 | ␉␉{␊ |
33 | ␉␉␉unlock_vbios(map);␊ |
34 | char* bytes = (char *)VBIOS_START;␊ |
35 | int patchlocation = 0x0254;␊ |
36 | verbose("Addr: %X Before patch: %x - ", patchlocation, bytes[patchlocation] );␊ |
37 | bytes[patchlocation] = 0x8A;␊ |
38 | verbose("after patch: %x \n", bytes[patchlocation++] );␊ |
39 | bytes[patchlocation++] = 0x25;␊ |
40 | bytes[patchlocation++] = 0xA0;␊ |
41 | bytes[patchlocation++] = 0x20;␊ |
42 | bytes[patchlocation++] = 0x51;␊ |
43 | bytes[patchlocation++] = 0x84;␊ |
44 | bytes[patchlocation++] = 0x1A;␊ |
45 | bytes[patchlocation++] = 0x30;␊ |
46 | bytes[patchlocation++] = 0x30;␊ |
47 | bytes[patchlocation++] = 0x40;␊ |
48 | bytes[patchlocation++] = 0x36;␊ |
49 | bytes[patchlocation++] = 0x00;␊ |
50 | bytes[patchlocation++] = 0x30;␊ |
51 | bytes[patchlocation++] = 0xBE;␊ |
52 | bytes[patchlocation++] = 0x10;␊ |
53 | bytes[patchlocation++] = 0x00;␊ |
54 | bytes[patchlocation++] = 0x00;␊ |
55 | bytes[patchlocation++] = 0x1E;␊ |
56 | ␊ |
57 | int i=0;␊ |
58 | /* verbose("unlocked, patching starting at: %X \n", bytes );␊ |
59 | for (i=0; i< 0xfffe; i++){␊ |
60 | char origbytes [] = {0x00, 0x05};␊ |
61 | if ( bytes[i] == origbytes[0] && bytes[i+1] == origbytes[1])␊ |
62 | {␊ |
63 | verbose("Addr: %X Before patch: %x %x - ", bytes + i, bytes[i], bytes[i+1]);␊ |
64 | ␊ |
65 | bytes[i] = 0xA0;␊ |
66 | bytes[i+1] = 0x05;␊ |
67 | verbose("after patch: %x %x \n", bytes[i], bytes[i+1]);␊ |
68 | ␊ |
69 | }␊ |
70 | }␊ |
71 | for (i=0; i< 0xfffe; i++){␊ |
72 | char origbytes [] = {0x20, 0x03};␊ |
73 | if ( bytes[i] == origbytes[0] && bytes[i+1] == origbytes[1])␊ |
74 | {␊ |
75 | verbose("Addr: %X Before patch: %x %x - ", bytes + i, bytes[i], bytes[i+1]);␊ |
76 | ␊ |
77 | bytes[i] = 0x84;␊ |
78 | bytes[i+1] = 0x03;␊ |
79 | verbose("after patch: %x %x \n", bytes[i], bytes[i+1]);␊ |
80 | ␊ |
81 | }␊ |
82 | }␊ |
83 | ␊ |
84 | */ ␊ |
85 | //␉␉␉set_mode(map, x, y, bp, 0, 0);␊ |
86 | verbose("\nFinished Patching at %X locking bios.\n", bytes + i );␊ |
87 | ␊ |
88 | ␉␉␉relock_vbios(map);␊ |
89 | ␊ |
90 | ␉␉␉close_vbios(map);␊ |
91 | ␉␉}␊ |
92 | ␉}␊ |
93 | }␊ |
94 | ␊ |
95 | ␊ |
96 | /* Copied from 915 resolution created by steve tomljenovic␊ |
97 | *␊ |
98 | * This code is based on the techniques used in :␊ |
99 | *␊ |
100 | * - 855patch. Many thanks to Christian Zietz (czietz gmx net)␊ |
101 | * for demonstrating how to shadow the VBIOS into system RAM␊ |
102 | * and then modify it.␊ |
103 | *␊ |
104 | * - 1280patch by Andrew Tipton (andrewtipton null li).␊ |
105 | *␊ |
106 | * - 855resolution by Alain Poirier␊ |
107 | *␊ |
108 | * This source code is into the public domain.␊ |
109 | */␊ |
110 | ␊ |
111 | /**␊ |
112 | **␊ |
113 | **/␊ |
114 | ␊ |
115 | #define CONFIG_MECH_ONE_ADDR␉0xCF8␊ |
116 | #define CONFIG_MECH_ONE_DATA␉0xCFC␊ |
117 | ␊ |
118 | int freqs[] = { 60, 75, 85 };␊ |
119 | ␊ |
120 | UInt8␉memDevBus = 0;␊ |
121 | ␊ |
122 | UInt32 get_chipset_id(void)␊ |
123 | {␊ |
124 | ␉outl(CONFIG_MECH_ONE_ADDR, 0x80000000);␊ |
125 | ␉return inl(CONFIG_MECH_ONE_DATA);␊ |
126 | }␊ |
127 | ␊ |
128 | chipset_type get_chipset(UInt32 id)␊ |
129 | {␊ |
130 | ␉chipset_type type;␊ |
131 | ␉␉␊ |
132 | ␉switch (id) {␊ |
133 | ␉␉case 0x35758086:␊ |
134 | ␉␉␉type = CT_830;␊ |
135 | ␉␉␉break;␊ |
136 | ␉␉␉␊ |
137 | ␉␉case 0x25608086:␊ |
138 | ␉␉␉type = CT_845G;␊ |
139 | ␉␉␉break;␊ |
140 | ␉␉␉␊ |
141 | ␉␉case 0x35808086:␊ |
142 | ␉␉␉type = CT_855GM;␊ |
143 | ␉␉␉break;␊ |
144 | ␉␉␉␊ |
145 | ␉␉case 0x25708086:␊ |
146 | ␉␉␉type = CT_865G;␊ |
147 | ␉␉␉break;␊ |
148 | ␉␉␉␊ |
149 | ␉␉case 0x25808086:␊ |
150 | ␉␉␉type = CT_915G;␊ |
151 | ␉␉␉break;␊ |
152 | ␉␉␉␊ |
153 | ␉␉case 0x25908086:␊ |
154 | ␉␉␉type = CT_915GM;␊ |
155 | ␉␉␉break;␊ |
156 | ␉␉␉␊ |
157 | ␉␉case 0x27708086:␊ |
158 | ␉␉␉type = CT_945G;␊ |
159 | ␉␉␉break;␊ |
160 | ␉␉␉␊ |
161 | ␉␉case 0x27a08086:␊ |
162 | ␉␉␉type = CT_945GM;␊ |
163 | ␉␉␉break;␊ |
164 | ␉␉␉␊ |
165 | ␉␉case 0x27ac8086:␊ |
166 | ␉␉␉type = CT_945GME;␊ |
167 | ␉␉␉break;␊ |
168 | ␉␉␉␊ |
169 | ␉␉case 0x29708086:␊ |
170 | ␉␉␉type = CT_946GZ;␊ |
171 | ␉␉␉break;␊ |
172 | ␉␉␉␊ |
173 | ␉␉case 0x27748086:␊ |
174 | ␉␉␉type = CT_955X;␊ |
175 | ␉␉␉break;␊ |
176 | ␉␉␉␊ |
177 | ␉␉case 0x277c8086:␊ |
178 | ␉␉␉type = CT_975X;␊ |
179 | ␉␉␉break;␊ |
180 | ␊ |
181 | ␉␉case 0x29a08086:␊ |
182 | ␉␉␉type = CT_G965;␊ |
183 | ␉␉␉break;␊ |
184 | ␉␉␉␊ |
185 | ␉␉case 0x29908086:␊ |
186 | ␉␉␉type = CT_Q965;␊ |
187 | ␉␉␉break;␊ |
188 | ␉␉␉␊ |
189 | ␉␉case 0x81008086:␊ |
190 | ␉␉␉type = CT_500;␊ |
191 | ␉␉␉break;␊ |
192 | ␉␉␉␊ |
193 | ␉␉case 0x2e108086:␊ |
194 | ␉␉case 0X2e908086:␊ |
195 | ␉␉␉type = CT_B43;␊ |
196 | ␉␉␉break;␊ |
197 | ␊ |
198 | ␉␉case 0x2e208086:␊ |
199 | ␉␉␉type = CT_P45;␊ |
200 | ␉␉␉break;␊ |
201 | ␊ |
202 | ␉␉case 0x2e308086:␊ |
203 | ␉␉␉type = CT_G41;␊ |
204 | ␉␉␉break;␊ |
205 | ␉␉␉␉␉␊ |
206 | ␉␉case 0x29c08086:␊ |
207 | ␉␉␉type = CT_G31;␊ |
208 | ␉␉␉break;␊ |
209 | ␉␉␉␊ |
210 | ␉␉case 0x29208086:␊ |
211 | ␉␉␉type = CT_G45;␊ |
212 | ␉␉␉break;␊ |
213 | ␉␉␉␊ |
214 | ␉␉case 0xA0108086:␉// mobile␊ |
215 | ␉␉case 0xA0008086:␉// desktop␊ |
216 | ␉␉␉type = CT_3150;␊ |
217 | ␉␉␉break;␊ |
218 | ␉␉␉␊ |
219 | ␉␉case 0x2a008086:␊ |
220 | ␉␉␉type = CT_965GM;␊ |
221 | ␉␉␉break;␊ |
222 | ␉␉␉␊ |
223 | ␉␉case 0x29e08086:␊ |
224 | ␉␉␉type = CT_X48;␊ |
225 | ␉␉␉break;␉␉␉␊ |
226 | ␉␉␉␉␊ |
227 | ␉␉case 0x2a408086:␊ |
228 | ␉␉␉type = CT_GM45;␊ |
229 | ␉␉␉break;␊ |
230 | ␉␉␉␊ |
231 | ␉␉␉//␊ |
232 | ␉␉␉// Core processors␊ |
233 | ␉␉␉// http://pci-ids.ucw.cz/read/PC/8086␊ |
234 | ␉␉␉//␊ |
235 | /*␉␉case 0x00408086: // Core Processor DRAM Controller␊ |
236 | ␉␉case 0x00448086: // Core Processor DRAM Controller␊ |
237 | ␉␉case 0x00488086: // Core Processor DRAM Controller␊ |
238 | ␉␉case 0x00698086: // Core Processor DRAM Controller␊ |
239 | ␉␉␉verbose(" core proc 1st gen identified\n");␊ |
240 | ␉␉␉type = CT_CORE_PROC_1;␊ |
241 | ␉␉␉break;␊ |
242 | */␉␉␉␊ |
243 | ␉␉case 0x01008086: // 2nd Generation Core Processor Family DRAM Controller␊ |
244 | ␉␉case 0x01048086: // 2nd Generation Core Processor Family DRAM Controller␊ |
245 | ␉␉case 0x01088086: // Xeon E3-1200 2nd Generation Core Processor Family DRAM Controller␊ |
246 | ␉␉case 0x010c8086: // Xeon E3-1200 2nd Generation Core Processor Family DRAM Controller␊ |
247 | ␊ |
248 | ␉␉case 0x01508086: // 3rd Generation Core Processor Family DRAM Controller␊ |
249 | ␉␉case 0x01548086: // 3rd Generation Core Processor Family DRAM Controller␊ |
250 | ␉␉case 0x01588086: // 3rd Generation Core Processor Family DRAM Controller␊ |
251 | ␉␉case 0x015c8086: // 3rd Generation Core Processor Family DRAM Controller␊ |
252 | ␉␉␉verbose(" core proc identified\n");␊ |
253 | ␉␉␉type = CT_CORE_PROC_2_3;␊ |
254 | ␉␉␉break;␊ |
255 | ␉␉␉␊ |
256 | ␉␉default:␊ |
257 | ␉␉␉if((id & 0x0000FFFF) == 0x00008086) // Intel chipset␊ |
258 | ␉␉␉{␊ |
259 | ␉␉␉␉//␊ |
260 | ␉␉␉␉// http://www.intel.com/content/www/us/en/processors/core/CoreTechnicalResources.html␊ |
261 | ␉␉␉␉// Core procs 1st gen: Bus (ff or 7f or 3f), Device 0, Func 1 contains␊ |
262 | ␉␉␉␉// System address decoder (SAD) with devId:␊ |
263 | ␉␉␉␉// 2c01 - Core i7-900 and Extreme Edition, Desktop␊ |
264 | ␉␉␉␉// 2c81 - CoreTM i7-800 and i5-700 Desktop␊ |
265 | ␉␉␉␉// 2c81 - CoreTM i7-900 Mobile Processor Extreme Edition Series, Intel Core i7-800 and i7-700 Mobile␊ |
266 | ␉␉␉␉// 2d01 - Core-i5-600, i3-500 desktop, Pentium 6000, Desktop␊ |
267 | ␉␉␉␉// 2d81 - Core i7-900 and Extreme Edition, Desktop, 32 nm␊ |
268 | ␉␉␉␉// 2cc1 - Xeon Processor C5500/C3500 Series␊ |
269 | ␉␉␉␉// SAD regs 40h-46h are PAM regs␊ |
270 | ␉␉␉␉//␊ |
271 | ␉␉␉␉UInt8 buses[] = {0xff, 0x7f, 0x3f};␊ |
272 | ␉␉␉␉UInt8 bus;␊ |
273 | ␉␉␉␉UInt32 i;␊ |
274 | ␉␉␉␉UInt16 devId;␊ |
275 | ␊ |
276 | ␉␉␉␉for (i = 0; i < sizeof(buses)/sizeof(buses[0]); i++)␊ |
277 | ␉␉␉␉{␊ |
278 | ␉␉␉␉␉// 1 << 31 | bus << 16 | device << 11 | function << 8 | offset␊ |
279 | ␉␉␉␉␉//verbose(" reading %x", (1 << 31 | buses[i] << 16 | 0 << 11 | 1 << 8 | 0));␊ |
280 | ␉␉␉␉␉outl(CONFIG_MECH_ONE_ADDR, (1 << 31 | buses[i] << 16 | 0 << 11 | 1 << 8 | 0));␊ |
281 | ␉␉␉␉␉devId = inw(CONFIG_MECH_ONE_DATA + 2);␊ |
282 | ␉␉␉␉␉//verbose(" = %x\n", devId);␊ |
283 | ␉␉␉␉␉if (devId == 0x2c01 || devId == 0x2c81 ||␊ |
284 | ␉␉␉␉␉␉devId == 0x2d01 || devId == 0x2d81 || devId == 0x2cc1)␊ |
285 | ␉␉␉␉␉{␊ |
286 | ␉␉␉␉␉␉verbose(" core proc identified\n");␊ |
287 | ␉␉␉␉␉␉memDevBus = buses[i];␊ |
288 | ␉␉␉␉␉␉type = CT_CORE_PROC_1;␊ |
289 | ␉␉␉␉␉␉break; // from for␊ |
290 | ␉␉␉␉␉}␊ |
291 | ␉␉␉␉}␊ |
292 | ␉␉␉␉if (type != CT_UNKNOWN) {␊ |
293 | ␉␉␉␉␉break; // from switch␊ |
294 | ␉␉␉␉}␊ |
295 | ␊ |
296 | ␉␉␉␉//␊ |
297 | ␉␉␉␉// Core i7 Processor Family for the LGA-2011␊ |
298 | ␉␉␉␉// http://www.intel.com/content/www/us/en/processors/core/core-i7-lga-2011-datasheet-vol-2.html␊ |
299 | ␉␉␉␉// Bus 0, Dev 5, Func 0, DevId=3c28 contains reg CPUBUSNO at 108h, bits 15:8 = Uncore bus␊ |
300 | ␉␉␉␉// Bus "Uncore bus", Dev 12, Func 6, DevId=3CF4 is System Address Decoder and PAM regs are at 40h-46h␊ |
301 | ␉␉␉␉//␊ |
302 | ␉␉␉␉outl(CONFIG_MECH_ONE_ADDR, (1 << 31 | 0 << 16 | 5 << 11 | 0 << 8 | 0));␊ |
303 | ␉␉␉␉devId = inw(CONFIG_MECH_ONE_DATA + 2);␊ |
304 | ␉␉␉␉if (devId == 0x3c28)␊ |
305 | ␉␉␉␉{␊ |
306 | ␉␉␉␉␉outl(CONFIG_MECH_ONE_ADDR, (1 << 31 | 0 << 16 | 5 << 11 | 0 << 8 | 0x108));␊ |
307 | ␉␉␉␉␉bus = inb(CONFIG_MECH_ONE_DATA + 1); // "Uncore bus"␊ |
308 | ␊ |
309 | ␉␉␉␉␉outl(CONFIG_MECH_ONE_ADDR, (1 << 31 | bus << 16 | 12 << 11 | 6 << 8 | 0));␊ |
310 | ␉␉␉␉␉devId = inw(CONFIG_MECH_ONE_DATA + 2);␊ |
311 | ␉␉␉␉␉if (devId == 0x3cf4) {␊ |
312 | ␉␉␉␉␉␉verbose(" core proc for the LGA-2011 identified\n");␊ |
313 | ␉␉␉␉␉␉memDevBus = bus;␊ |
314 | ␉␉␉␉␉␉type = CT_CORE_PROC_2011;␊ |
315 | ␉␉␉␉␉␉break; // from switch␊ |
316 | ␉␉␉␉␉}␊ |
317 | ␉␉␉␉}␊ |
318 | ␊ |
319 | ␉␉␉␉verbose(" unknown Intel chipset/proc\n");␊ |
320 | ␉␉␉␉//printf("Unknown chipset 0x%llX, please email id to meklort@gmail.com", id);␊ |
321 | ␉␉␉␉//getc();␊ |
322 | ␉␉␉␉//type = CT_UNKNOWN_INTEL;␊ |
323 | ␉␉␉␉type = CT_UNKNOWN;␊ |
324 | ␊ |
325 | ␉␉␉}␊ |
326 | ␉␉␉else␊ |
327 | ␉␉␉{␊ |
328 | ␉␉␉␉type = CT_UNKNOWN;␊ |
329 | ␉␉␉}␊ |
330 | ␉␉␉break;␊ |
331 | ␉}␊ |
332 | ␊ |
333 | ␉return type;␊ |
334 | }␊ |
335 | ␊ |
336 | vbios_resolution_type1 * map_type1_resolution(vbios_map * map, UInt16 res)␊ |
337 | {␊ |
338 | ␉vbios_resolution_type1 * ptr = ((vbios_resolution_type1*)(map->bios_ptr + res)); ␊ |
339 | ␉return ptr;␊ |
340 | }␊ |
341 | ␊ |
342 | vbios_resolution_type2 * map_type2_resolution(vbios_map * map, UInt16 res)␊ |
343 | {␊ |
344 | ␉vbios_resolution_type2 * ptr = ((vbios_resolution_type2*)(map->bios_ptr + res)); ␊ |
345 | ␉return ptr;␊ |
346 | }␊ |
347 | ␊ |
348 | vbios_resolution_type3 * map_type3_resolution(vbios_map * map, UInt16 res)␊ |
349 | {␊ |
350 | ␉vbios_resolution_type3 * ptr = ((vbios_resolution_type3*)(map->bios_ptr + res)); ␊ |
351 | ␉return ptr;␊ |
352 | }␊ |
353 | ␊ |
354 | char detect_bios_type(vbios_map * map, char modeline, int entry_size);␊ |
355 | char detect_bios_type(vbios_map * map, char modeline, int entry_size)␊ |
356 | {␊ |
357 | ␉UInt32 i;␊ |
358 | ␉UInt16 r1, r2;␊ |
359 | ␉␊ |
360 | ␉r1 = r2 = 32000;␊ |
361 | ␉␊ |
362 | ␉for (i=0; i < map->mode_table_size; i++)␊ |
363 | ␉{␊ |
364 | //␉␉msglog(" 0x%X", map->mode_table[i].resolution );␊ |
365 | ␊ |
366 | ␉␉if (map->mode_table[i].resolution <= r1)␊ |
367 | ␉␉{␊ |
368 | ␉␉␉r1 = map->mode_table[i].resolution;␊ |
369 | ␉␉}␊ |
370 | ␉␉else␊ |
371 | ␉␉{␊ |
372 | ␉␉␉if (map->mode_table[i].resolution <= r2)␊ |
373 | ␉␉␉{␊ |
374 | ␉␉␉␉r2 = map->mode_table[i].resolution;␊ |
375 | ␉␉␉}␊ |
376 | ␉␉}␊ |
377 | ␊ |
378 | ␉␉//printf("r1 = %d r2 = %d\n", r1, r2);␊ |
379 | ␉}␊ |
380 | ␉␊ |
381 | ␉return (r2-r1-6) % entry_size == 0;␊ |
382 | }␊ |
383 | ␊ |
384 | void close_vbios(vbios_map * map);␊ |
385 | ␊ |
386 | char detect_ati_bios_type(vbios_map * map)␊ |
387 | {␉␊ |
388 | ␉return map->mode_table_size % sizeof(ATOM_MODE_TIMING) == 0;␊ |
389 | }␊ |
390 | ␊ |
391 | ␊ |
392 | vbios_map * open_vbios(chipset_type forced_chipset)␊ |
393 | {␊ |
394 | ␉UInt32 z;␊ |
395 | ␉vbios_map * map = malloc(sizeof(vbios_map));␊ |
396 | ␉if (!map)␊ |
397 | ␉{␊ |
398 | ␉␉return 0;␊ |
399 | ␉}␊ |
400 | ␉for(z=0; z<sizeof(vbios_map); z++) ((char*)map)[z]=0;␊ |
401 | ␉/*␊ |
402 | ␉ * Determine chipset␊ |
403 | ␉ */␊ |
404 | ␉␊ |
405 | ␉if (forced_chipset == CT_UNKNOWN)␊ |
406 | ␉{␊ |
407 | ␉␉map->chipset_id = get_chipset_id();␊ |
408 | ␉␉map->chipset = get_chipset(map->chipset_id);␊ |
409 | ␉}␊ |
410 | ␉else if (forced_chipset != CT_UNKNOWN)␊ |
411 | ␉{␊ |
412 | ␉␉map->chipset = forced_chipset;␊ |
413 | ␉}␊ |
414 | ␉␊ |
415 | ␉␊ |
416 | ␉if (map->chipset == CT_UNKNOWN)␊ |
417 | ␉{␊ |
418 | ␉␉verbose(" Unknown chipset type: %08x.\n", map->chipset_id);␊ |
419 | ␉␉//verbose("915resolution only works with Intel 800/900 series graphic chipsets.\n");␊ |
420 | ␉␉//verbose("Chipset Id: %x\n", map->chipset_id);␊ |
421 | ␉␉close_vbios(map);␊ |
422 | ␉␉return 0;␊ |
423 | ␉}␊ |
424 | ␉else␊ |
425 | ␉{␊ |
426 | ␉␉verbose(" Detected chipset/proc id (DRAM controller): %08x\n", map->chipset_id);␊ |
427 | ␉}␊ |
428 | ␉␊ |
429 | ␉␊ |
430 | ␉verbose(" VBios: ");␊ |
431 | ␉/*␊ |
432 | ␉ * Map the video bios to memory␊ |
433 | ␉ */␊ |
434 | ␉map->bios_ptr=(char*)VBIOS_START;␊ |
435 | ␉␊ |
436 | ␉/*␊ |
437 | ␉ * check if we have ATI Radeon␊ |
438 | ␉ */␊ |
439 | ␉map->ati_tables.base = map->bios_ptr;␊ |
440 | ␉map->ati_tables.AtomRomHeader = (ATOM_ROM_HEADER *) (map->bios_ptr + *(unsigned short *) (map->bios_ptr + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)); ␊ |
441 | ␉if (strcmp ((char *) map->ati_tables.AtomRomHeader->uaFirmWareSignature, "ATOM") == 0)␊ |
442 | ␉{␊ |
443 | ␉␉verbose("ATI");␊ |
444 | ␉␉// ATI Radeon Card␊ |
445 | ␉␉map->bios = BT_ATI_1;␊ |
446 | ␉␉␊ |
447 | ␉␉map->ati_tables.MasterDataTables = (unsigned short *) &((ATOM_MASTER_DATA_TABLE *) (map->bios_ptr + map->ati_tables.AtomRomHeader->usMasterDataTableOffset))->ListOfDataTables;␊ |
448 | ␉␉unsigned short std_vesa_offset = (unsigned short) ((ATOM_MASTER_LIST_OF_DATA_TABLES *)map->ati_tables.MasterDataTables)->StandardVESA_Timing;␊ |
449 | ␉␉ATOM_STANDARD_VESA_TIMING * std_vesa = (ATOM_STANDARD_VESA_TIMING *) (map->bios_ptr + std_vesa_offset);␊ |
450 | ␉␉␊ |
451 | ␉␉map->ati_mode_table = (char *) &std_vesa->aModeTimings;␊ |
452 | ␉␉if (map->ati_mode_table == 0)␊ |
453 | ␉␉{␊ |
454 | ␉␉␉printf("Unable to locate the mode table.\n");␊ |
455 | ␉␉␉printf("Please run the program 'dump_bios' as root and\n");␊ |
456 | ␉␉␉printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n");␊ |
457 | ␉␉␉printf("Chipset: %d\n", map->chipset);␊ |
458 | ␉␉␉close_vbios(map);␊ |
459 | ␉␉␉return 0;␊ |
460 | ␉␉}␊ |
461 | ␉␉map->mode_table_size = std_vesa->sHeader.usStructureSize - sizeof(ATOM_COMMON_TABLE_HEADER);␊ |
462 | ␉␉␊ |
463 | ␉␉if (!detect_ati_bios_type(map))␊ |
464 | ␉␉{␊ |
465 | ␉␉␉map->bios = BT_ATI_2;␊ |
466 | ␉␉}␊ |
467 | ␊ |
468 | ␉␉if (map->bios == BT_ATI_1)␊ |
469 | ␉␉{␊ |
470 | ␉␉␉verbose(", BT_ATI_1\n");␊ |
471 | ␉␉}␊ |
472 | ␉␉else␊ |
473 | ␉␉{␊ |
474 | ␉␉␉verbose(", BT_ATI_2\n");␊ |
475 | ␉␉}␊ |
476 | ␉}␊ |
477 | ␉else␊ |
478 | ␉{␊ |
479 | ␉␉␊ |
480 | ␉␉/*␊ |
481 | ␉␉ * check if we have NVIDIA␊ |
482 | ␉␉ */␊ |
483 | ␊ |
484 | ␉␉int i = 0;␊ |
485 | ␉␉while (i < 512)␊ |
486 | ␉␉{ // we don't need to look through the whole bios, just the first 512 bytes␊ |
487 | ␉␉␉if ((␉map->bios_ptr[i] == 'N') ␊ |
488 | ␉␉␉␉&& (map->bios_ptr[i+1] == 'V') ␊ |
489 | ␉␉␉␉&& (map->bios_ptr[i+2] == 'I') ␊ |
490 | ␉␉␉␉&& (map->bios_ptr[i+3] == 'D')) ␊ |
491 | ␉␉␉{␊ |
492 | ␉␉␉␉verbose("nVidia\n");␊ |
493 | ␉␉␉␉map->bios = BT_NVDA;␊ |
494 | ␉␉␉␉unsigned short nv_data_table_offset = 0;␊ |
495 | ␉␉␉␉unsigned short * nv_data_table;␊ |
496 | ␉␉␉␉NV_VESA_TABLE * std_vesa;␊ |
497 | ␉␉␉␉␊ |
498 | ␉␉␉␉int i = 0;␊ |
499 | ␊ |
500 | ␉␉␉␉while (i < 0x300)␊ |
501 | ␉␉␉␉{ //We don't need to look for the table in the whole bios, the 768 first bytes only␊ |
502 | ␉␉␉␉␉if ((␉map->bios_ptr[i] == 0x44) ␊ |
503 | ␉␉␉␉␉␉&& (map->bios_ptr[i+1] == 0x01) ␊ |
504 | ␉␉␉␉␉␉&& (map->bios_ptr[i+2] == 0x04) ␊ |
505 | ␉␉␉␉␉␉&& (map->bios_ptr[i+3] == 0x00))␊ |
506 | ␉␉␉␉␉{␊ |
507 | ␉␉␉␉␉␉nv_data_table_offset = (unsigned short) (map->bios_ptr[i+4] | (map->bios_ptr[i+5] << 8));␊ |
508 | ␉␉␉␉␉␉break;␊ |
509 | ␉␉␉␉␉}␊ |
510 | ␉␉␉␉␉i++;␊ |
511 | ␉␉␉␉}␊ |
512 | ␉␉␉␉␊ |
513 | ␉␉␉␉nv_data_table = (unsigned short *) (map->bios_ptr + (nv_data_table_offset + OFFSET_TO_VESA_TABLE_INDEX));␊ |
514 | ␉␉␉␉std_vesa = (NV_VESA_TABLE *) (map->bios_ptr + *nv_data_table);␊ |
515 | ␉␉␉␉␊ |
516 | ␉␉␉␉map->nv_mode_table = (char *) std_vesa->sModelines;␊ |
517 | ␉␉␉␉if (map->nv_mode_table == 0)␊ |
518 | ␉␉␉␉{␊ |
519 | ␉␉␉␉␉printf("Unable to locate the mode table.\n");␊ |
520 | ␉␉␉␉␉printf("Please run the program 'dump_bios' as root and\n");␊ |
521 | ␉␉␉␉␉printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n");␊ |
522 | ␉␉␉␉␉printf("Chipset: %s\n", map->chipset);␊ |
523 | ␉␉␉␉␉close_vbios(map);␊ |
524 | ␉␉␉␉␉return 0;␊ |
525 | ␉␉␉␉}␊ |
526 | ␉␉␉␉map->mode_table_size = std_vesa->sHeader.usTable_Size;␊ |
527 | ␉␉␉␉␊ |
528 | ␉␉␉␉break;␊ |
529 | ␉␉␉}␊ |
530 | ␉␉␉i++;␊ |
531 | ␉␉}␊ |
532 | ␉}␊ |
533 | ␉␊ |
534 | ␊ |
535 | ␉/*␊ |
536 | ␉ * check if we have Intel␊ |
537 | ␉ */␊ |
538 | ␊ |
539 | ␉/*if (map->chipset == CT_UNKNOWN && memmem(map->bios_ptr, VBIOS_SIZE, INTEL_SIGNATURE, strlen(INTEL_SIGNATURE))) {␊ |
540 | ␉ printf( "Intel chipset detected. However, 915resolution was unable to determine the chipset type.\n");␊ |
541 | ␊ |
542 | ␉ printf("Chipset Id: %x\n", map->chipset_id);␊ |
543 | ␊ |
544 | ␉ printf("Please report this problem to stomljen@yahoo.com\n");␊ |
545 | ␊ |
546 | ␉ close_vbios(map);␊ |
547 | ␉ return 0;␊ |
548 | ␉ }*/␊ |
549 | ␊ |
550 | ␉/*␊ |
551 | ␉ * check for others␊ |
552 | ␉ */␊ |
553 | ␉␊ |
554 | ␉/*␊ |
555 | ␉ * Figure out where the mode table is ␊ |
556 | ␉ */␊ |
557 | ␉if ((map->bios != BT_ATI_1) && (map->bios != BT_ATI_2) && (map->bios != BT_NVDA)) ␊ |
558 | ␉{␊ |
559 | ␉␉char* p = map->bios_ptr + 16;␊ |
560 | ␉␉char* limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode));␊ |
561 | ␉␉␊ |
562 | ␉␉verbose("Other");␊ |
563 | ␉␉msglog("Started mode table scan at: 0x%X\n", p );␊ |
564 | ␉␉while (p < limit && map->mode_table == 0)␊ |
565 | ␉␉{␊ |
566 | ␉␉␉vbios_mode * mode_ptr = (vbios_mode *) p;␊ |
567 | ␉␉␉␊ |
568 | ␉␉␉if (((mode_ptr[0].mode & 0xf0) == 0x30) && ((mode_ptr[1].mode & 0xf0) == 0x30) &&␊ |
569 | ␉␉␉␉((mode_ptr[2].mode & 0xf0) == 0x30) && ((mode_ptr[3].mode & 0xf0) == 0x30))␊ |
570 | ␉␉␉{␊ |
571 | ␉␉␉␉map->mode_table = mode_ptr;␊ |
572 | ␉␉␉}␊ |
573 | ␉␉␉␊ |
574 | ␉␉␉p++;␊ |
575 | ␉␉}␊ |
576 | ␉␉msglog("Ended mode table scan at: 0x%X\n", p );␊ |
577 | ␉␉if (map->mode_table == 0)␊ |
578 | ␉␉{␊ |
579 | ␉␉␉close_vbios(map);␊ |
580 | ␉␉␉return 0;␊ |
581 | ␉␉}␊ |
582 | ␉}␊ |
583 | ␉␊ |
584 | ␉␊ |
585 | ␉/*␊ |
586 | ␉ * Determine size of mode table␊ |
587 | ␉ */␊ |
588 | ␉if ((map->bios != BT_ATI_1) && (map->bios != BT_ATI_2) && (map->bios != BT_NVDA))␊ |
589 | ␉{␊ |
590 | ␉␉vbios_mode * mode_ptr = map->mode_table;␊ |
591 | ␉␉␊ |
592 | ␉␉while (mode_ptr->mode != 0xff)␊ |
593 | ␉␉{␊ |
594 | ␉␉␉map->mode_table_size++;␊ |
595 | ␉␉␉mode_ptr++;␊ |
596 | ␉␉}␊ |
597 | ␉␉msglog("Table size: 0x%X\n", map->mode_table_size );␊ |
598 | ␉}␊ |
599 | ␉␊ |
600 | ␉/*␊ |
601 | ␉ * Figure out what type of bios we have␊ |
602 | ␉ * order of detection is important␊ |
603 | ␉ */␊ |
604 | ␉if ((map->bios != BT_ATI_1) && (map->bios != BT_ATI_2) && (map->bios != BT_NVDA))␊ |
605 | ␉{␊ |
606 | ␉␉if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type3)))␊ |
607 | ␉␉{␊ |
608 | ␉␉␉map->bios = BT_3;␊ |
609 | ␉␉␉verbose(", BT_3\n");␊ |
610 | ␉␉}␊ |
611 | ␉␉else if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type2)))␊ |
612 | ␉␉{␊ |
613 | ␉␉␉map->bios = BT_2;␊ |
614 | ␉␉␉verbose(", BT_2\n");␊ |
615 | ␉␉}␊ |
616 | ␉␉else if (detect_bios_type(map, FALSE, sizeof(vbios_resolution_type1)))␊ |
617 | ␉␉{␊ |
618 | ␉␉␉map->bios = BT_1;␊ |
619 | ␉␉␉verbose(", BT_1\n");␊ |
620 | ␉␉}␊ |
621 | ␉␉else {␊ |
622 | ␉␉␉verbose(" - unknown\n");␊ |
623 | ␉␉␉//return 0;␊ |
624 | ␉␉}␊ |
625 | ␉}␊ |
626 | ␉␊ |
627 | ␉return map;␊ |
628 | }␊ |
629 | ␊ |
630 | void close_vbios(vbios_map * map)␊ |
631 | {␊ |
632 | ␉free(map);␊ |
633 | }␊ |
634 | ␊ |
635 | void unlock_vbios(vbios_map * map)␊ |
636 | {␊ |
637 | ␉map->unlocked = TRUE;␊ |
638 | ␊ |
639 | ␉switch (map->chipset) {␊ |
640 | ␉␉case CT_UNKNOWN:␊ |
641 | ␉␉␉break;␊ |
642 | ␉␉case CT_830:␊ |
643 | ␉␉case CT_855GM:␊ |
644 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, 0x8000005a);␊ |
645 | ␉␉␉map->b1 = inb(CONFIG_MECH_ONE_DATA + 2);␊ |
646 | ␉␉␉␊ |
647 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, 0x8000005a);␊ |
648 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 2, 0x33);␊ |
649 | ␉␉␉break;␊ |
650 | ␉␉case CT_845G:␊ |
651 | ␉␉case CT_865G:␊ |
652 | ␉␉case CT_915G:␊ |
653 | ␉␉case CT_915GM:␊ |
654 | ␉␉case CT_945G:␊ |
655 | ␉␉case CT_945GM:␊ |
656 | ␉␉case CT_945GME:␊ |
657 | ␉␉case CT_946GZ:␊ |
658 | ␉␉case CT_G965:␊ |
659 | ␉␉case CT_Q965:␊ |
660 | ␉␉case CT_965GM:␊ |
661 | ␉␉case CT_975X:␊ |
662 | ␉␉case CT_P35:␊ |
663 | ␉␉case CT_955X:␊ |
664 | ␉␉case CT_X48:␊ |
665 | ␉␉case CT_B43:␊ |
666 | ␉␉case CT_Q45:␊ |
667 | ␉␉case CT_P45:␊ |
668 | ␉␉case CT_GM45:␊ |
669 | ␉␉case CT_G45:␊ |
670 | ␉␉case CT_G41:␊ |
671 | ␉␉case CT_G31:␊ |
672 | ␉␉case CT_500:␊ |
673 | ␉␉case CT_3150:␊ |
674 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, 0x80000090);␊ |
675 | ␉␉␉map->b1 = inb(CONFIG_MECH_ONE_DATA + 1);␊ |
676 | ␉␉␉map->b2 = inb(CONFIG_MECH_ONE_DATA + 2);␊ |
677 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, 0x80000090);␊ |
678 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 1, 0x33);␊ |
679 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 2, 0x33);␊ |
680 | ␉␉␉break;␊ |
681 | ␉␉case CT_CORE_PROC_1:␉ // Core procs - PAM regs are Bus=memDevBus, Dev=0, Func=1, 40h - 46h␊ |
682 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, (1 << 31 | memDevBus << 16 | 0 << 11 | 1 << 8 | 0x40));␊ |
683 | ␉␉␉map->b1 = inb(CONFIG_MECH_ONE_DATA + 1);␊ |
684 | ␉␉␉map->b2 = inb(CONFIG_MECH_ONE_DATA + 2);␊ |
685 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, (1 << 31 | memDevBus << 16 | 0 << 11 | 1 << 8 | 0x40));␊ |
686 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 1, 0x33);␊ |
687 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 2, 0x33);␊ |
688 | ␉␉␉break;␊ |
689 | ␉␉case CT_CORE_PROC_2011:␉ // Core procs LGA-2011 - PAM regs are Bus=memDevBus, Dev=12, Func=6, 40h - 46h␊ |
690 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, (1 << 31 | memDevBus << 16 | 12 << 11 | 6 << 8 | 0x40));␊ |
691 | ␉␉␉map->b1 = inb(CONFIG_MECH_ONE_DATA + 1);␊ |
692 | ␉␉␉map->b2 = inb(CONFIG_MECH_ONE_DATA + 2);␊ |
693 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, (1 << 31 | memDevBus << 16 | 12 << 11 | 6 << 8 | 0x40));␊ |
694 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 1, 0x33);␊ |
695 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 2, 0x33);␊ |
696 | ␉␉␉break;␊ |
697 | ␉␉case CT_CORE_PROC_2_3:␉ // Core procs - PAM regs are 80h - 86h␊ |
698 | ␉␉//case CT_UNKNOWN_INTEL:␉// Assume newer intel chipset is the same as before␊ |
699 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, 0x80000080);␊ |
700 | ␉␉␉map->b1 = inb(CONFIG_MECH_ONE_DATA + 1);␊ |
701 | ␉␉␉map->b2 = inb(CONFIG_MECH_ONE_DATA + 2);␊ |
702 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, 0x80000080);␊ |
703 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 1, 0x33);␊ |
704 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 2, 0x33);␊ |
705 | ␉␉␉break;␊ |
706 | ␉␉default:␊ |
707 | ␉␉␉break;␊ |
708 | ␉}␊ |
709 | ␉␊ |
710 | ␉// test if vbios is unlocked␊ |
711 | ␉UInt8 *ptr8 = (UInt8*)(VBIOS_START + 0xa123);␊ |
712 | ␉UInt8 val8 = *ptr8;␊ |
713 | ␉*ptr8 = *ptr8 + 1;␊ |
714 | ␉if (val8 != *ptr8) {␊ |
715 | ␉␉*ptr8 = val8;␊ |
716 | ␉␉map->unlocked = TRUE;␊ |
717 | ␉␉verbose(" vbios unlocked\n");␊ |
718 | ␉}␊ |
719 | #if DEBUG␊ |
720 | ␉{␊ |
721 | ␉␉UInt32 t = inl(CONFIG_MECH_ONE_DATA);␊ |
722 | ␉␉verbose("unlock PAM: (0x%08x)\n", t);␊ |
723 | ␉}␊ |
724 | #endif␊ |
725 | }␊ |
726 | ␊ |
727 | void relock_vbios(vbios_map * map)␊ |
728 | {␊ |
729 | ␉␊ |
730 | ␉map->unlocked = FALSE;␊ |
731 | ␉␊ |
732 | ␉switch (map->chipset)␊ |
733 | ␉{␊ |
734 | ␉␉case CT_UNKNOWN:␊ |
735 | ␉␉␉break;␊ |
736 | ␉␉case CT_830:␊ |
737 | ␉␉case CT_855GM:␊ |
738 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, 0x8000005a);␊ |
739 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 2, map->b1);␊ |
740 | ␉␉␉break;␊ |
741 | ␉␉case CT_845G:␊ |
742 | ␉␉case CT_865G:␊ |
743 | ␉␉case CT_915G:␊ |
744 | ␉␉case CT_915GM:␊ |
745 | ␉␉case CT_945G:␊ |
746 | ␉␉case CT_945GM:␊ |
747 | ␉␉case CT_945GME:␊ |
748 | ␉␉case CT_946GZ:␊ |
749 | ␉␉case CT_G965:␊ |
750 | ␉␉case CT_955X:␊ |
751 | ␉␉case CT_G45:␊ |
752 | ␉␉case CT_Q965:␊ |
753 | ␉␉case CT_965GM:␊ |
754 | ␉␉case CT_975X:␊ |
755 | ␉␉case CT_P35:␊ |
756 | ␉␉case CT_X48:␊ |
757 | ␉␉case CT_B43:␊ |
758 | ␉␉case CT_Q45:␊ |
759 | ␉␉case CT_P45:␊ |
760 | ␉␉case CT_GM45:␊ |
761 | ␉␉case CT_G41:␊ |
762 | ␉␉case CT_G31:␊ |
763 | ␉␉case CT_500:␊ |
764 | ␉␉case CT_3150:␊ |
765 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, 0x80000090);␊ |
766 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 1, map->b1);␊ |
767 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 2, map->b2);␊ |
768 | ␉␉␉break;␊ |
769 | ␉␉case CT_CORE_PROC_1:␊ |
770 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, (1 << 31 | memDevBus << 16 | 0 << 11 | 1 << 8 | 0x40));␊ |
771 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 1, map->b1);␊ |
772 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 2, map->b2);␊ |
773 | ␉␉␉break;␊ |
774 | ␉␉case CT_CORE_PROC_2011:␊ |
775 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, (1 << 31 | memDevBus << 16 | 12 << 11 | 6 << 8 | 0x40));␊ |
776 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 1, map->b1);␊ |
777 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 2, map->b2);␊ |
778 | ␉␉␉break;␊ |
779 | ␉␉case CT_CORE_PROC_2_3:␊ |
780 | ␉␉//case CT_UNKNOWN_INTEL:␊ |
781 | ␉␉␉outl(CONFIG_MECH_ONE_ADDR, 0x80000080);␊ |
782 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 1, map->b1);␊ |
783 | ␉␉␉outb(CONFIG_MECH_ONE_DATA + 2, map->b2);␊ |
784 | ␉␉default:␊ |
785 | ␉␉␉break;␊ |
786 | ␉}␊ |
787 | ␉␊ |
788 | #if DEBUG␊ |
789 | ␉{␊ |
790 | UInt32 t = inl(CONFIG_MECH_ONE_DATA);␊ |
791 | ␉␉verbose("relock PAM: (0x%08x)\n", t);␊ |
792 | ␉}␊ |
793 | #endif␊ |
794 | }␊ |
795 | ␊ |
796 | ␊ |
797 | int getMode(edid_mode *mode)␊ |
798 | {␊ |
799 | ␉char* edidInfo = readEDID();␊ |
800 | ␉␉␉␊ |
801 | ␉if(!edidInfo) return 1;␊ |
802 | //Slice␊ |
803 | ␉if(!fb_parse_edid((struct EDID *)edidInfo, mode)) ␊ |
804 | ␉{␊ |
805 | ␉␉//free( edidInfo );␊ |
806 | ␉␉return 1;␊ |
807 | ␉}␊ |
808 | /*␉mode->pixel_clock = (edidInfo[55] << 8) | edidInfo[54];␊ |
809 | ␉mode->h_active = edidInfo[56] | ((edidInfo[58] & 0xF0) << 4);␊ |
810 | ␉mode->h_blanking = ((edidInfo[58] & 0x0F) << 8) | edidInfo[57];␊ |
811 | ␉mode->v_active = edidInfo[59] | ((edidInfo[61] & 0xF0) << 4);␊ |
812 | ␉mode->v_blanking = ((edidInfo[61] & 0x0F) << 8) | edidInfo[60];␊ |
813 | ␉mode->h_sync_offset = ((edidInfo[65] & 0xC0) >> 2) | edidInfo[62];␊ |
814 | ␉mode->h_sync_width = (edidInfo[65] & 0x30) | edidInfo[63];␊ |
815 | ␉mode->v_sync_offset = (edidInfo[65] & 0x0C) | ((edidInfo[64] & 0x0C) >> 2);␊ |
816 | ␉mode->v_sync_width = ((edidInfo[65] & 0x3) << 2) | (edidInfo[64] & 0x03);␊ |
817 | */␉␉␊ |
818 | ␉if(!mode->h_active) return 1;␊ |
819 | ␉//free( edidInfo );␊ |
820 | ␉␉␊ |
821 | ␉return 0;␊ |
822 | ␉␉␊ |
823 | }␊ |
824 | ␊ |
825 | ␊ |
826 | static void gtf_timings(UInt32 x, UInt32 y, UInt32 freq,␊ |
827 | ␉␉␉␉␉␉unsigned long *clock,␊ |
828 | ␉␉␉␉␉␉UInt16 *hsyncstart, UInt16 *hsyncend, UInt16 *hblank,␊ |
829 | ␉␉␉␉␉␉UInt16 *vsyncstart, UInt16 *vsyncend, UInt16 *vblank)␊ |
830 | {␊ |
831 | ␉UInt32 hbl, vbl, vfreq;␊ |
832 | ␉␊ |
833 | ␉vbl = y + (y+1)/(20000.0/(11*freq) - 1) + 1.5;␊ |
834 | ␉vfreq = vbl * freq;␊ |
835 | ␉hbl = 16 * (int)(x * (30.0 - 300000.0 / vfreq) /␊ |
836 | ␉␉␉␉␉ + (70.0 + 300000.0 / vfreq) / 16.0 + 0.5);␊ |
837 | ␊ |
838 | ␉*vsyncstart = y;␊ |
839 | ␉*vsyncend = y + 3;␊ |
840 | ␉*vblank = vbl - 1;␊ |
841 | ␉*hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1;␊ |
842 | ␉*hsyncend = x + hbl / 2 - 1;␊ |
843 | ␉*hblank = x + hbl - 1;␊ |
844 | ␉*clock = (x + hbl) * vfreq / 1000;␊ |
845 | }␊ |
846 | ␊ |
847 | void set_mode(vbios_map * map, /*UInt32 mode,*/ UInt32 x, UInt32 y, UInt32 bp, UInt32 htotal, UInt32 vtotal) {␊ |
848 | ␉UInt32 xprev, yprev;␊ |
849 | ␉UInt32 i = 0, j;␊ |
850 | ␉// patch first available mode␊ |
851 | ␉␊ |
852 | ␉//␉for (i=0; i < map->mode_table_size; i++) {␊ |
853 | ␉//␉␉if (map->mode_table[0].mode == mode) {␊ |
854 | ␉verbose(" Patching: ");␊ |
855 | ␉switch(map->bios) {␊ |
856 | ␉␉case BT_INTEL:␊ |
857 | ␉␉␉verbose("BT_INTEL - not supported\n");␊ |
858 | ␉␉␉return;␊ |
859 | ␊ |
860 | ␉␉case BT_1:␊ |
861 | ␉␉{␊ |
862 | ␉␉␉verbose("BT_1 patched.\n");␊ |
863 | ␉␉␉vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);␊ |
864 | ␉␉␉␊ |
865 | ␉␉␉if (bp)␊ |
866 | ␉␉␉{␊ |
867 | ␉␉␉␉map->mode_table[i].bits_per_pixel = (uint8_t)bp;␊ |
868 | ␉␉␉}␊ |
869 | ␉␉␉␊ |
870 | ␉␉␉res->x2 = (htotal?(((htotal-x) >> 8) & 0x0f) : (res->x2 & 0x0f)) | ((x >> 4) & 0xf0);␊ |
871 | ␉␉␉res->x1 = (x & 0xff);␊ |
872 | ␉␉␉␊ |
873 | ␉␉␉res->y2 = (vtotal?(((vtotal-y) >> 8) & 0x0f) : (res->y2 & 0x0f)) | ((y >> 4) & 0xf0);␊ |
874 | ␉␉␉res->y1 = (y & 0xff);␊ |
875 | ␉␉␉if (htotal)␊ |
876 | ␉␉␉{␊ |
877 | ␉␉␉␉res->x_total = ((htotal-x) & 0xff);␊ |
878 | ␉␉␉}␊ |
879 | ␉␉␉if (vtotal)␊ |
880 | ␉␉␉{␊ |
881 | ␉␉␉␉res->y_total = ((vtotal-y) & 0xff);␊ |
882 | ␉␉␉}␊ |
883 | ␉␉␉break;␊ |
884 | ␉␉}␊ |
885 | ␉␉case BT_2:␊ |
886 | ␉␉{␊ |
887 | ␉␉␉vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);␊ |
888 | ␉␉␉␊ |
889 | ␉␉␉res->xchars = (uint8_t)(x / 8);␊ |
890 | ␉␉␉res->ychars = (uint8_t)(y / 16 - 1);␊ |
891 | ␉␉␉xprev = res->modelines[0].x1;␊ |
892 | ␉␉␉yprev = res->modelines[0].y1;␊ |
893 | ␉␉␉␊ |
894 | ␉␉␉for(j=0; j < 3; j++) {␊ |
895 | ␉␉␉␉vbios_modeline_type2 * modeline = &res->modelines[j];␊ |
896 | ␉␉␉␉␊ |
897 | ␉␉␉␉if (modeline->x1 == xprev && modeline->y1 == yprev) {␊ |
898 | ␉␉␉␉␉modeline->x1 = modeline->x2 = (uint16_t)(x-1);␊ |
899 | ␉␉␉␉␉modeline->y1 = modeline->y2 = (uint16_t)(y-1);␊ |
900 | ␉␉␉␉␉␊ |
901 | ␉␉␉␉␉gtf_timings(x, y, freqs[j], &modeline->clock,␊ |
902 | ␉␉␉␉␉␉␉␉&modeline->hsyncstart, &modeline->hsyncend,␊ |
903 | ␉␉␉␉␉␉␉␉&modeline->hblank, &modeline->vsyncstart,␊ |
904 | ␉␉␉␉␉␉␉␉&modeline->vsyncend, &modeline->vblank);␊ |
905 | ␉␉␉␉␉␊ |
906 | ␉␉␉␉␉if (htotal)␊ |
907 | ␉␉␉␉␉{␊ |
908 | ␉␉␉␉␉␉modeline->htotal = (uint16_t)htotal;␊ |
909 | ␉␉␉␉␉}␊ |
910 | ␉␉␉␉␉else␊ |
911 | ␉␉␉␉␉{␊ |
912 | ␉␉␉␉␉␉modeline->htotal = modeline->hblank;␊ |
913 | ␉␉␉␉␉}␊ |
914 | ␉␉␉␉␉if (vtotal)␊ |
915 | ␉␉␉␉␉{␊ |
916 | ␉␉␉␉␉␉modeline->vtotal = (uint16_t)vtotal;␊ |
917 | ␉␉␉␉␉}␊ |
918 | ␉␉␉␉␉else␊ |
919 | ␉␉␉␉␉{␊ |
920 | ␉␉␉␉␉␉modeline->vtotal = modeline->vblank;␊ |
921 | ␉␉␉␉␉}␊ |
922 | ␉␉␉␉}␊ |
923 | ␉␉␉}␊ |
924 | ␉␉␉verbose("BT_1 patched.\n");␊ |
925 | ␉␉␉break;␊ |
926 | ␉␉}␊ |
927 | ␉␉case BT_3:␊ |
928 | ␉␉{␊ |
929 | ␉␉␉vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);␊ |
930 | ␉␉␉␊ |
931 | ␉␉␉xprev = res->modelines[0].x1;␊ |
932 | ␉␉␉yprev = res->modelines[0].y1;␊ |
933 | ␉␉␉␊ |
934 | ␉␉␉for (j=0; j < 3; j++) {␊ |
935 | ␉␉␉␉vbios_modeline_type3 * modeline = &res->modelines[j];␊ |
936 | ␉␉␉␉␊ |
937 | ␉␉␉␉if (modeline->x1 == xprev && modeline->y1 == yprev) {␊ |
938 | ␉␉␉␉␉modeline->x1 = modeline->x2 = (uint16_t)(x-1);␊ |
939 | ␉␉␉␉␉modeline->y1 = modeline->y2 = (uint16_t)(y-1);␊ |
940 | ␉␉␉␉␉␊ |
941 | ␉␉␉␉␉gtf_timings(x, y, freqs[j], &modeline->clock,␊ |
942 | ␉␉␉␉␉␉␉␉&modeline->hsyncstart, &modeline->hsyncend,␊ |
943 | ␉␉␉␉␉␉␉␉&modeline->hblank, &modeline->vsyncstart,␊ |
944 | ␉␉␉␉␉␉␉␉&modeline->vsyncend, &modeline->vblank);␊ |
945 | ␉␉␉␉␉if (htotal)␊ |
946 | ␉␉␉␉␉{␊ |
947 | ␉␉␉␉␉␉modeline->htotal = (uint16_t)htotal;␊ |
948 | ␉␉␉␉␉}␊ |
949 | ␉␉␉␉␉else␊ |
950 | ␉␉␉␉␉{␊ |
951 | ␉␉␉␉␉␉modeline->htotal = modeline->hblank;␊ |
952 | ␉␉␉␉␉}␊ |
953 | ␉␉␉␉␉if (vtotal)␊ |
954 | ␉␉␉␉␉{␊ |
955 | ␉␉␉␉␉␉modeline->vtotal = (uint16_t)vtotal;␊ |
956 | ␉␉␉␉␉}␊ |
957 | ␉␉␉␉␉else␊ |
958 | ␉␉␉␉␉{␊ |
959 | ␉␉␉␉␉␉modeline->vtotal = modeline->vblank;␊ |
960 | ␉␉␉␉␉}␊ |
961 | ␉␉␉␉␉modeline->timing_h = (uint16_t)(y-1);␊ |
962 | ␉␉␉␉␉modeline->timing_v = (uint16_t)(x-1);␊ |
963 | ␉␉␉␉}␊ |
964 | ␉␉␉}␊ |
965 | ␉␉␉verbose("BT_3 patched.\n");␊ |
966 | ␉␉␉break;␊ |
967 | ␉␉}␊ |
968 | ␉␉case BT_ATI_1:␊ |
969 | ␉␉{␊ |
970 | ␉␉␉verbose("BT_ATI_1");␊ |
971 | ␉␉␉edid_mode mode;␊ |
972 | ␉␉␉␉␊ |
973 | ␉␉␉ATOM_MODE_TIMING *mode_timing = (ATOM_MODE_TIMING *) map->ati_mode_table;␊ |
974 | ␊ |
975 | ␉␉␉//if (mode.pixel_clock && (mode.h_active == x) && (mode.v_active == y) && !force){␊ |
976 | ␉␉␉if (!getMode(&mode))␊ |
977 | ␉␉␉{␊ |
978 | ␉␉␉␉verbose("\n Edid detailed timing descriptor found: %dx%d\n vbios mode 0 patched!\n", mode.h_active, mode.v_active);␊ |
979 | ␉␉␉␉mode_timing->usCRTC_H_Total = mode.h_active + mode.h_blanking;␊ |
980 | ␉␉␉␉mode_timing->usCRTC_H_Disp = mode.h_active;␊ |
981 | ␉␉␉␉mode_timing->usCRTC_H_SyncStart = mode.h_active + mode.h_sync_offset;␊ |
982 | ␉␉␉␉mode_timing->usCRTC_H_SyncWidth = mode.h_sync_width;␊ |
983 | ␉␉␉␉␉␊ |
984 | ␉␉␉␉mode_timing->usCRTC_V_Total = mode.v_active + mode.v_blanking;␊ |
985 | ␉␉␉␉mode_timing->usCRTC_V_Disp = mode.v_active;␊ |
986 | ␉␉␉␉mode_timing->usCRTC_V_SyncStart = mode.v_active + mode.v_sync_offset;␊ |
987 | ␉␉␉␉mode_timing->usCRTC_V_SyncWidth = mode.v_sync_width;␊ |
988 | ␊ |
989 | ␉␉␉␉mode_timing->usPixelClock = mode.pixel_clock;␊ |
990 | ␉␉␉}␊ |
991 | ␉␉␉else␊ |
992 | ␉␉␉{␊ |
993 | ␉␉␉␉verbose(" Edid not found or invalid - vbios not patched!\n");␊ |
994 | ␉␉␉}␊ |
995 | ␉␉␉/*else␊ |
996 | ␉␉␉{␊ |
997 | ␉␉␉␉vbios_modeline_type2 modeline;␊ |
998 | ␊ |
999 | ␉␉␉␉cvt_timings(x, y, freqs[0], &modeline.clock,␊ |
1000 | ␉␉␉␉␉␉␉&modeline.hsyncstart, &modeline.hsyncend,␊ |
1001 | ␉␉␉␉␉␉␉&modeline.hblank, &modeline.vsyncstart,␊ |
1002 | ␉␉␉␉␉␉␉&modeline.vsyncend, &modeline.vblank, 0);␊ |
1003 | ␊ |
1004 | ␉␉␉␉mode_timing->usCRTC_H_Total = x + modeline.hblank;␊ |
1005 | ␉␉␉␉mode_timing->usCRTC_H_Disp = x;␊ |
1006 | ␉␉␉␉mode_timing->usCRTC_H_SyncStart = modeline.hsyncstart;␊ |
1007 | ␉␉␉␉mode_timing->usCRTC_H_SyncWidth = modeline.hsyncend - modeline.hsyncstart;␊ |
1008 | ␊ |
1009 | ␉␉␉␉mode_timing->usCRTC_V_Total = y + modeline.vblank;␊ |
1010 | ␉␉␉␉mode_timing->usCRTC_V_Disp = y;␊ |
1011 | ␉␉␉␉mode_timing->usCRTC_V_SyncStart = modeline.vsyncstart;␊ |
1012 | ␉␉␉␉mode_timing->usCRTC_V_SyncWidth = modeline.vsyncend - modeline.vsyncstart;␊ |
1013 | ␉␉␉␉␉␉␉␉␉␉␉␉␊ |
1014 | ␉␉␉␉mode_timing->usPixelClock = modeline.clock;␊ |
1015 | ␉␉␉ }*/␊ |
1016 | ␊ |
1017 | ␉␉␉break;␊ |
1018 | ␉␉}␊ |
1019 | ␉␉case BT_ATI_2:␊ |
1020 | ␉␉{␊ |
1021 | ␉␉␉verbose("BT_ATI_2");␊ |
1022 | ␉␉␉edid_mode mode;␊ |
1023 | ␉␉␉␉␉␉␊ |
1024 | ␉␉␉ATOM_DTD_FORMAT *mode_timing = (ATOM_DTD_FORMAT *) map->ati_mode_table;␊ |
1025 | ␉␉␉␊ |
1026 | ␉␉␉/*if (mode.pixel_clock && (mode.h_active == x) && (mode.v_active == y) && !force) {*/␊ |
1027 | ␉␉␉if (!getMode(&mode)) {␊ |
1028 | ␉␉␉␉verbose("\n Edid detailed timing descriptor found: %dx%d\n vbios mode 0 patched!\n", mode.h_active, mode.v_active);␊ |
1029 | ␉␉␉␉mode_timing->usHBlanking_Time = mode.h_blanking;␊ |
1030 | ␉␉␉␉mode_timing->usHActive = mode.h_active;␊ |
1031 | ␉␉␉␉mode_timing->usHSyncOffset = mode.h_sync_offset;␊ |
1032 | ␉␉␉␉mode_timing->usHSyncWidth = mode.h_sync_width;␊ |
1033 | ␉␉␉␉␉␉␉␉␉␉␊ |
1034 | ␉␉␉␉mode_timing->usVBlanking_Time = mode.v_blanking;␊ |
1035 | ␉␉␉␉mode_timing->usVActive = mode.v_active;␊ |
1036 | ␉␉␉␉mode_timing->usVSyncOffset = mode.v_sync_offset;␊ |
1037 | ␉␉␉␉mode_timing->usVSyncWidth = mode.v_sync_width;␊ |
1038 | ␉␉␉␉␉␉␉␉␉␉␊ |
1039 | ␉␉␉␉mode_timing->usPixClk = mode.pixel_clock;␊ |
1040 | ␉␉␉}␊ |
1041 | ␉␉␉else␊ |
1042 | ␉␉␉{␊ |
1043 | ␉␉␉␉verbose(" Edid not found or invalid - vbios not patched!\n");␊ |
1044 | ␉␉␉}␊ |
1045 | ␉␉␉/*else␊ |
1046 | ␉␉␉{␊ |
1047 | ␉␉␉␉vbios_modeline_type2 modeline;␊ |
1048 | ␉␉␉␊ |
1049 | ␉␉␉␉cvt_timings(x, y, freqs[0], &modeline.clock,␊ |
1050 | ␉␉␉␉␉␉␉&modeline.hsyncstart, &modeline.hsyncend,␊ |
1051 | ␉␉␉␉␉␉␉&modeline.hblank, &modeline.vsyncstart,␊ |
1052 | ␉␉␉␉␉␉␉&modeline.vsyncend, &modeline.vblank, 0);␊ |
1053 | ␉␉␉␉␉␉␉␉␉␉␉␊ |
1054 | ␉␉␉␉mode_timing->usHBlanking_Time = modeline.hblank;␊ |
1055 | ␉␉␉␉␉␉␉␉␉␉␉mode_timing->usHActive = x;␊ |
1056 | ␉␉␉␉␉␉␉␉␉␉␉mode_timing->usHSyncOffset = modeline.hsyncstart - x;␊ |
1057 | ␉␉␉␉␉␉␉␉␉␉␉mode_timing->usHSyncWidth = modeline.hsyncend - modeline.hsyncstart;␊ |
1058 | ␉␉␉␉␉␉␉␉␉␉␉␊ |
1059 | ␉␉␉␉␉␉␉␉␉␉␉mode_timing->usVBlanking_Time = modeline.vblank;␊ |
1060 | ␉␉␉␉␉␉␉␉␉␉␉mode_timing->usVActive = y;␊ |
1061 | ␉␉␉␉␉␉␉␉␉␉␉mode_timing->usVSyncOffset = modeline.vsyncstart - y;␊ |
1062 | ␉␉␉␉␉␉␉␉␉␉␉mode_timing->usVSyncWidth = modeline.hsyncend - modeline.hsyncstart;␊ |
1063 | ␉␉␉␉␉␉␉␉␉␉␉␊ |
1064 | ␉␉␉␉␉␉␉␉␉␉␉mode_timing->usPixClk = modeline.clock;␊ |
1065 | ␉␉␉␉␉␉␉␉␉␉}*/␊ |
1066 | ␊ |
1067 | ␉␉␉break;␊ |
1068 | ␉␉}␊ |
1069 | ␉␉case BT_NVDA:␊ |
1070 | ␉␉{␊ |
1071 | ␉␉␉verbose("BT_NVDA");␊ |
1072 | ␉␉␉edid_mode mode;␊ |
1073 | ␉␉␉NV_MODELINE *mode_timing = (NV_MODELINE *) map->nv_mode_table;␊ |
1074 | ␉␉␉␊ |
1075 | ␉␉␉/*if (mode.pixel_clock && (mode.h_active == x) && (mode.v_active == y) && !force) {*/␊ |
1076 | ␉␉␉if (!getMode(&mode))␊ |
1077 | ␉␉␉{␊ |
1078 | ␉␉␉␉verbose("\n Edid detailed timing descriptor found: %dx%d\n vbios mode %d patched!\n", mode.h_active, mode.v_active, i);␊ |
1079 | ␉␉␉␉mode_timing[i].usH_Total = mode.h_active + mode.h_blanking;␊ |
1080 | ␉␉␉␉mode_timing[i].usH_Active = mode.h_active;␊ |
1081 | ␉␉␉␉mode_timing[i].usH_SyncStart = mode.h_active + mode.h_sync_offset;␊ |
1082 | ␉␉␉␉mode_timing[i].usH_SyncEnd = mode.h_active + mode.h_sync_offset + mode.h_sync_width;␊ |
1083 | ␉␉␉␉␊ |
1084 | ␉␉␉␉mode_timing[i].usV_Total = mode.v_active + mode.v_blanking;␊ |
1085 | ␉␉␉␉mode_timing[i].usV_Active = mode.v_active;␊ |
1086 | ␉␉␉␉mode_timing[i].usV_SyncStart = mode.v_active + mode.v_sync_offset;␊ |
1087 | ␉␉␉␉mode_timing[i].usV_SyncEnd = mode.v_active + mode.v_sync_offset + mode.v_sync_width;␊ |
1088 | ␉␉␉␉␊ |
1089 | ␉␉␉␉mode_timing[i].usPixel_Clock = mode.pixel_clock;␊ |
1090 | ␉␉␉}␊ |
1091 | ␉␉␉ else␊ |
1092 | ␉␉␉{␊ |
1093 | ␉␉␉␉verbose(" Edid not found or invalid - vbios not patched!\n");␊ |
1094 | ␉␉␉}␊ |
1095 | ␉␉␉/*else␊ |
1096 | ␉␉␉ {␊ |
1097 | ␉␉␉ vbios_modeline_type2 modeline;␊ |
1098 | ␉␉␉ cvt_timings(x, y, freqs[0], &modeline.clock,␊ |
1099 | ␉␉␉ &modeline.hsyncstart, &modeline.hsyncend,␊ |
1100 | ␉␉␉ &modeline.hblank, &modeline.vsyncstart,␊ |
1101 | ␉␉␉ &modeline.vsyncend, &modeline.vblank, 0);␊ |
1102 | ␊ |
1103 | ␉␉␉ mode_timing[i].usH_Total = x + modeline.hblank - 1;␊ |
1104 | ␉␉␉ mode_timing[i].usH_Active = x;␊ |
1105 | ␉␉␉ mode_timing[i].usH_SyncStart = modeline.hsyncstart - 1;␊ |
1106 | ␉␉␉ mode_timing[i].usH_SyncEnd = modeline.hsyncend - 1;␊ |
1107 | ␊ |
1108 | ␉␉␉ mode_timing[i].usV_Total = y + modeline.vblank - 1;␊ |
1109 | ␉␉␉ mode_timing[i].usV_Active = y;␊ |
1110 | ␉␉␉ mode_timing[i].usV_SyncStart = modeline.vsyncstart - 1;␊ |
1111 | ␉␉␉ mode_timing[i].usV_SyncEnd = modeline.vsyncend - 1;␊ |
1112 | ␊ |
1113 | ␉␉␉ mode_timing[i].usPixel_Clock = modeline.clock;␊ |
1114 | ␉␉␉ }*/␊ |
1115 | ␉␉␉break;␊ |
1116 | ␉␉}␊ |
1117 | ␉␉case BT_UNKNOWN:␊ |
1118 | ␉␉{␊ |
1119 | ␉␉␉verbose(" Unknown - vbios not patched\n");␊ |
1120 | ␉␉␉break;␊ |
1121 | ␉␉}␊ |
1122 | ␉␉default:␊ |
1123 | ␉␉␉break;␊ |
1124 | ␉}␊ |
1125 | ␉//␉␉}␊ |
1126 | ␉//␉}␊ |
1127 | }␊ |
1128 | ␊ |
1129 | #endif // _RESOLUTION_H_␊ |
1130 | |