Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/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 */
9
10
11#include "libsaio.h"
12#include "edid.h"
13#include "vbe.h"
14#include "graphics.h"
15#include "boot.h"
16
17void getResolutionHook(void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)
18{
19getResolution(arg1, arg2, arg3);
20}
21
22void getResolution(UInt32* x, UInt32* y, UInt32* bp)
23{
24int val;
25static UInt32 xResolution, yResolution, bpResolution;
26
27if(getIntForKey(kScreenWidth, &val, &bootInfo->bootConfig))
28{
29xResolution = val;
30}
31
32if(getIntForKey(kScreenHeight, &val, &bootInfo->bootConfig))
33{
34yResolution = val;
35}
36
37bpResolution = 32;// assume 32bits
38
39
40if(!xResolution || !yResolution || !bpResolution)
41{
42
43char* edidInfo = readEDID();
44
45if(!edidInfo) return;
46
47// TODO: check *all* resolutions reported and either use the highest, or the native resolution (if there is a flag for that)
48xResolution = edidInfo[56] | ((edidInfo[58] & 0xF0) << 4);
49yResolution = edidInfo[59] | ((edidInfo[61] & 0xF0) << 4);
50
51//printf("H Active = %d", edidInfo[56] | ((edidInfo[58] & 0xF0) << 4) );
52//printf("V Active = %d", edidInfo[59] | ((edidInfo[61] & 0xF0) << 4) );
53
54free( edidInfo );
55
56if(!xResolution) xResolution = DEFAULT_SCREEN_WIDTH;
57if(!yResolution) yResolution = DEFAULT_SCREEN_HEIGHT;
58
59}
60
61*x = xResolution;
62*y = yResolution;
63*bp = bpResolution;
64
65}
66
67char* readEDID()
68{
69SInt16 last_reported = -1;
70UInt8 edidInfo[EDID_BLOCK_SIZE];
71
72UInt8 header1[] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
73UInt8 header2[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
74
75SInt16 status;
76UInt16 blocks_left = 1;
77
78do
79{
80// TODO: This currently only retrieves the *last* block, make the block buffer expand as needed / calculated from the first block
81
82bzero( edidInfo, EDID_BLOCK_SIZE);
83
84status = getEDID(edidInfo, blocks_left);
85
86
87//printf("Buffer location: 0x%X\n", SEG(buffer) << 16 | OFF(buffer));
88/*
89int j, i;
90for (j = 0; j < 8; j++) {
91for(i = 0; i < 16; i++) printf("0x%X ", ebiosInfo[((i+1) * (j + 1)) - 1]);
92
93}
94printf("\n");
95*/
96
97if(status == 0)
98{
99//if( edidInfo[0] == 0x00 || edidInfo[0] == 0xFF)
100if((memcmp(edidInfo, header1, sizeof(header1)) != 0) ||
101 (memcmp(edidInfo, header2, sizeof(header2)) != 0) )
102{
103blocks_left--;
104int reported = edidInfo[ EDID_V1_BLOCKS_TO_GO_OFFSET ];
105
106if ( reported > blocks_left )
107{
108
109printf("EDID claims %d more blocks left\n", reported);
110}
111
112if ( (last_reported <= reported && last_reported != -1)
113|| reported == 0xff
114/* 0xff frequently comes up in corrupt edids */
115//|| reported == MAGIC
116)
117{
118printf("Last reported %d\n", last_reported);
119printf( "EDID blocks left is wrong.\n"
120 "Your EDID is probably invalid.\n");
121return 0;
122}
123else
124{
125//printf("Reading EDID block\n");
126//printf("H Active = %d", ebiosInfo[56] | ((ebiosInfo[58] & 0xF0) << 4) );
127//printf("V Active = %d", ebiosInfo[59] | ((ebiosInfo[61] & 0xF0) << 4) );
128
129last_reported = reported;
130blocks_left = reported;
131}
132}
133else
134{
135printf("Invalid block %d\n", blocks_left);
136printf("Header1 = %d", memcmp(edidInfo, header1, sizeof(header1)) );
137printf("Header2 = %d", memcmp(edidInfo, header2, sizeof(header2)) );
138return 0;
139}
140}
141blocks_left = 0;
142} while(blocks_left);
143
144char* ret = malloc(sizeof(edidInfo));
145memcpy(ret, edidInfo, sizeof(edidInfo));
146return ret;
147}
148

Archive Download this file

Revision: 789