Chameleon

Chameleon Svn Source Tree

Root/branches/slice/i386/modules/Resolution/edid.c

1/*
2 * edid.c
3 *
4 *
5 * Created by Evan Lojewski on 12/1/09.
6 * Copyright 2009. All rights reserved.
7 *
8 *Slice 2010
9 */
10
11
12//#include "libsaio.h"
13#include "edid.h"
14#include "vbe.h"
15#include "graphics.h"
16#include "boot.h"
17//----------------------------------------------------------------------------------
18
19#define FBMON_FIX_HEADER 1
20#define FBMON_FIX_INPUT 2
21#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
22
23//----------------------------------------------------------------------------------
24/*
25struct broken_edid {
26const char manufacturer[4];
27UInt32 model;
28UInt32 fix;
29};
30
31//----------------------------------------------------------------------------------
32
33broken_edid brokendb[] = {
34// DEC FR-PCXAV-YZ *
35{ "DEC", 0x073a, FBMON_FIX_HEADER,},
36// ViewSonic PF775a *
37{ "VSC", 0x5a44, FBMON_FIX_INPUT,}
38};
39//----------------------------------------------------------------------------------
40*/
41const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
42
43//----------------------------------------------------------------------------------
44int edid_compare(unsigned char *edid1, unsigned char *edid2)
45{
46int result = 0;
47unsigned char *block = edid1 + ID_MANUFACTURER_NAME, manufacturer1[4], manufacturer2[4];;
48manufacturer1[0] = ((block[0] & 0x7c) >> 2) + '@';
49manufacturer1[1] = ((block[0] & 0x03) << 3) + ((block[1] & 0xe0) >> 5) + '@';
50manufacturer1[2] = (block[1] & 0x1f) + '@';
51manufacturer1[3] = 0;
52
53block = edid2 + ID_MANUFACTURER_NAME;
54manufacturer2[0] = ((block[0] & 0x7c) >> 2) + '@';
55manufacturer2[1] = ((block[0] & 0x03) << 3) + ((block[1] & 0xe0) >> 5) + '@';
56manufacturer2[2] = (block[1] & 0x1f) + '@';
57manufacturer2[3] = 0;
58int x;
59for(x = 0; x < 4; x++)
60{
61if(manufacturer1[x] == manufacturer2[x])
62result++;
63}
64
65return result;
66}
67
68int check_edid(unsigned char *edid)
69{
70unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
71//unsigned char *b;
72UInt32 model;
73//int i, fix = 0, ret = 0;
74
75manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
76manufacturer[1] = ((block[0] & 0x03) << 3) +
77((block[1] & 0xe0) >> 5) + '@';
78manufacturer[2] = (block[1] & 0x1f) + '@';
79manufacturer[3] = 0;
80model = block[2] + (block[3] << 8);
81/*
82for (i = 0; i < (int)ARRAY_SIZE(brokendb); i++) {
83if (!strncmp((const char *)manufacturer, brokendb[i].manufacturer, 4) &&
84brokendb[i].model == model) {
85DEBG("ATIFB: The EDID Block of "
86 "Manufacturer: %s Model: 0x%08lx is known to "
87 "be broken,\n", manufacturer, model);
88fix = brokendb[i].fix;
89break;
90}
91}
92
93switch (fix) {
94case FBMON_FIX_HEADER:
95for (i = 0; i < 8; i++) {
96if (edid[i] != edid_v1_header[i])
97ret = fix;
98}
99break;
100case FBMON_FIX_INPUT:
101b = edid + EDID_STRUCT_DISPLAY;
102/// Only if display is GTF capable will
103 //the input type be reset to analog *
104if (b[4] & 0x01 && b[0] & 0x80)
105ret = fix;
106break;
107}
108*/
109return 0; //ret;
110}
111
112//----------------------------------------------------------------------------------
113
114static void fix_edid(unsigned char *edid, int fix)
115{
116unsigned char *b;
117
118switch (fix) {
119case FBMON_FIX_HEADER:
120msglog("EDID: trying a header reconstruct\n");
121memcpy(edid, edid_v1_header, 8);
122break;
123case FBMON_FIX_INPUT:
124msglog("EDID: trying to fix input type\n");
125b = edid + EDID_STRUCT_DISPLAY;
126b[0] &= ~0x80;
127edid[127] += 0x80;
128}
129}
130
131//----------------------------------------------------------------------------------
132
133int edid_checksum(unsigned char *edid)
134{
135unsigned char i, csum = 0, all_null = 0;
136int err = 0, fix = check_edid(edid);
137
138if (fix)
139fix_edid(edid, fix);
140
141for (i = 0; i < EDID_LENGTH; i++) {
142csum += edid[i];
143all_null |= edid[i];
144}
145
146if (csum == 0x00 && all_null) {
147/* checksum passed, everything's good */
148err = 1;
149}
150
151return err;
152}
153
154//----------------------------------------------------------------------------------
155
156static int edid_check_header(unsigned char *edid)
157{
158int i, err = 1, fix = check_edid(edid);
159
160if (fix)
161fix_edid(edid, fix);
162
163for (i = 0; i < 8; i++) {
164if (edid[i] != edid_v1_header[i])
165err = 0;
166}
167
168return err;
169}
170//------------------------------------------------------------------------
171bool verifyEDID(unsigned char *edid)
172{
173if (edid == NULL || !edid_checksum(edid) ||!edid_check_header(edid))
174{
175return false;
176}
177return true;
178}
179
180int edid_is_timing_block(unsigned char *block)
181{
182if ((block[0] != 0x00) || (block[1] != 0x00) ||
183(block[2] != 0x00) || (block[4] != 0x00))
184return 1;
185else
186return 0;
187}
188//----------------------------------------------------------------------------------
189
190int fb_parse_edid(struct EDID *edid, UInt32* x, UInt32* y)
191{
192int i;
193unsigned char *block;
194
195if(!verifyEDID((unsigned char *)edid)) return 1;
196
197block = (unsigned char *)edid + DETAILED_TIMING_DESCRIPTIONS_START; //54
198
199for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
200if (edid_is_timing_block(block)) {
201*x = H_ACTIVE;
202*y = V_ACTIVE;
203/*
204var->xres = var->xres_virtual = H_ACTIVE;
205var->yres = var->yres_virtual = V_ACTIVE;
206var->height = var->width = -1;
207var->right_margin = H_SYNC_OFFSET;
208var->left_margin = (H_ACTIVE + H_BLANKING) -
209(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
210var->upper_margin = V_BLANKING - V_SYNC_OFFSET -
211V_SYNC_WIDTH;
212var->lower_margin = V_SYNC_OFFSET;
213var->hsync_len = H_SYNC_WIDTH;
214var->vsync_len = V_SYNC_WIDTH;
215var->pixclock = PIXEL_CLOCK;
216var->pixclock /= 1000;
217var->pixclock = KHZ2PICOS(var->pixclock);
218
219if (HSYNC_POSITIVE)
220var->sync |= FB_SYNC_HOR_HIGH_ACT;
221if (VSYNC_POSITIVE)
222var->sync |= FB_SYNC_VERT_HIGH_ACT;
223 */
224return 0;
225}
226}
227return 1;
228}
229
230void getResolution(UInt32* x, UInt32* y, UInt32* bp)
231{
232int val;
233static UInt32 xResolution, yResolution, bpResolution;
234
235if(getIntForKey(kScreenWidth, &val, &bootInfo->bootConfig))
236{
237xResolution = val;
238}
239
240if(getIntForKey(kScreenHeight, &val, &bootInfo->bootConfig))
241{
242yResolution = val;
243}
244
245bpResolution = 32;// assume 32bits
246
247
248if(!xResolution || !yResolution || !bpResolution)
249{
250
251char* edidInfo = readEDID();
252
253if(!edidInfo) return;
254
255// TODO: check *all* resolutions reported and either use the highest, or the native resolution (if there is a flag for that)
256//xResolution = edidInfo[56] | ((edidInfo[58] & 0xF0) << 4);
257//yResolution = edidInfo[59] | ((edidInfo[61] & 0xF0) << 4);
258if(fb_parse_edid(edidInfo, &xResolution, &yResolution))
259{
260xResolution = DEFAULT_SCREEN_WIDTH;
261yResolution = DEFAULT_SCREEN_HEIGHT;
262}
263/*
264 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0x32 0x0C
265 0x00 0xDF 0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0x00
266 0x0C 0xDF 0x00 0x00 0x12 0x03 0x21 0x78 0xE9 0x99
267 0x53 0x28 0xFF 0xFF 0x32 0xDF 0x00 0x12 0x80 0x78
268 0xD5 0x53 0x26 0x00 0x01 0x01 0x01 0x01 0xFF 0x00
269 0xDF 0x00 0x03 0x78 0x99 0x28 0x00 0x01 0x01 0x01
270 0x01 0x21 0x84 0x20 0xFF 0x0C 0x00 0x03 0x0A 0x53
271 0x54 0x01 0x01 0x01 0xDE 0x84 0x56 0x00 0xA0 0x30
272 0xFF 0xDF 0x12 0x78 0x53 0x00 0x01 0x01 0x01 0x84
273 0x00 0x18 0x84 0x00 0x00 0x57 0xFF 0x00 0x80 0x99
274 0x54 0x01 0x01 0x21 0x20 0x00 0x50 0x00 0x00 0x35
275 0x57 0xFE 0x00 0x00 0x78 0x28 0x01 0x01 0x21 0x20
276 0x18 0x30 0x00 0x57 0x34 0xFE 0xAA 0x9A
277
278 */
279
280//msglog("H Active = %d ", edidInfo[56] | ((edidInfo[58] & 0xF0) << 4) );
281//msglog("V Active = %d \n", edidInfo[59] | ((edidInfo[61] & 0xF0) << 4) );
282
283free( edidInfo );
284
285//if(!xResolution) xResolution = DEFAULT_SCREEN_WIDTH;
286//if(!yResolution) yResolution = DEFAULT_SCREEN_HEIGHT;
287
288}
289
290*x = xResolution;
291*y = yResolution;
292*bp = bpResolution;
293
294}
295
296char* readEDID()
297{
298SInt16 last_reported = -1;
299UInt8 edidInfo[EDID_BLOCK_SIZE];
300
301UInt8 header1[] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
302UInt8 header2[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
303
304SInt16 status;
305UInt16 blocks_left = 1;
306msglog("readEDID\n");
307do
308{
309// TODO: This currently only retrieves the *last* block, make the block buffer expand as needed / calculated from the first block
310
311bzero( edidInfo, EDID_BLOCK_SIZE);
312
313status = getEDID(edidInfo, blocks_left);
314
315
316msglog("Buffer location: 0x%X status: %d\n", SEG(edidInfo) << 16 | OFF(edidInfo), status);
317
318int j, i;
319for (j = 0; j < 8; j++) {
320for(i = 0; i < 16; i++) msglog("0x%02X ", edidInfo[((i+1) * (j + 1)) - 1]);
321msglog("\n");
322}
323
324
325
326if(status == 0)
327{
328//if( edidInfo[0] == 0x00 || edidInfo[0] == 0xFF)
329if((memcmp(edidInfo, header1, sizeof(header1)) != 0) ||
330 (memcmp(edidInfo, header2, sizeof(header2)) != 0) )
331{
332blocks_left--;
333int reported = edidInfo[ EDID_V1_BLOCKS_TO_GO_OFFSET ];
334
335if ( reported > blocks_left )
336{
337
338msglog("EDID claims %d more blocks left\n", reported);
339}
340
341if ( (last_reported <= reported && last_reported != -1)
342|| reported == 0xff
343/* 0xff frequently comes up in corrupt edids */
344//|| reported == MAGIC
345)
346{
347msglog("Last reported %d\n", last_reported);
348msglog( "EDID blocks left is wrong.\n"
349 "Your EDID is probably invalid.\n");
350return 0;
351}
352else
353{
354//printf("Reading EDID block\n");
355//printf("H Active = %d", ebiosInfo[56] | ((ebiosInfo[58] & 0xF0) << 4) );
356//printf("V Active = %d", ebiosInfo[59] | ((ebiosInfo[61] & 0xF0) << 4) );
357
358last_reported = reported;
359blocks_left = reported;
360}
361}
362else
363{
364msglog("Invalid block %d\n", blocks_left);
365msglog("Header1 = %d", memcmp(edidInfo, header1, sizeof(header1)) );
366msglog("Header2 = %d", memcmp(edidInfo, header2, sizeof(header2)) );
367return 0;
368}
369}
370blocks_left = 0;
371} while(blocks_left);
372
373char* ret = malloc(sizeof(edidInfo));
374memcpy(ret, edidInfo, sizeof(edidInfo));
375return ret;
376}
377

Archive Download this file

Revision: 691