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 "bootstruct.h"␊ |
15 | //#include "graphics.h"␊ |
16 | ␊ |
17 | //static biosBuf_t bb;␊ |
18 | ␊ |
19 | UInt32 xResolution = 0;␊ |
20 | UInt32 yResolution = 0;␊ |
21 | UInt32 bpResolution = 0;␊ |
22 | ␊ |
23 | ␊ |
24 | void getResolution(UInt32* x, UInt32* y, UInt32* bp)␊ |
25 | {␊ |
26 | ␉unsigned char* edidInfo = readEDID();␊ |
27 | ␉␊ |
28 | ␉if(!edidInfo) {␊ |
29 | ␉␉xResolution = 1024;␊ |
30 | ␉␉yResolution = 768;␊ |
31 | ␉␉bpResolution = 32;␊ |
32 | ␉␉␊ |
33 | ␉␉free( edidInfo );␊ |
34 | ␉} else {␊ |
35 | ␉␉// TODO: check *all* resolutions reported and eithe ruse the highest, or the native resolution (if there is a flag for that)␊ |
36 | ␉␉xResolution = edidInfo[56] | ((edidInfo[58] & 0xF0) << 4);␊ |
37 | ␉␉yResolution = edidInfo[59] | ((edidInfo[61] & 0xF0) << 4);␊ |
38 | ␉␉␊ |
39 | ␉␉bpResolution = 32;␉// assume 32bits␊ |
40 | ␉␉␊ |
41 | ␉␉free( edidInfo );␊ |
42 | ␉}␊ |
43 | ␉␊ |
44 | ␉if (!xResolution) xResolution = 1024;␊ |
45 | ␉if (!yResolution) yResolution = 768;␊ |
46 | ␉␊ |
47 | ␉*x = xResolution;␊ |
48 | ␉*y = yResolution;␊ |
49 | ␉*bp = bpResolution;␊ |
50 | ␊ |
51 | }␊ |
52 | ␊ |
53 | int getMode(edid_mode *mode)␊ |
54 | {␊ |
55 | ␉unsigned char* edidInfo = readEDID();␊ |
56 | ␉␉␊ |
57 | ␉if(!edidInfo) return 1;␊ |
58 | ␉␊ |
59 | ␉mode->pixel_clock = (edidInfo[55] << 8) | edidInfo[54];␊ |
60 | ␉mode->h_active = edidInfo[56] | ((edidInfo[58] & 0xF0) << 4);␊ |
61 | ␉mode->h_blanking = ((edidInfo[58] & 0x0F) << 8) | edidInfo[57];␊ |
62 | ␉mode->v_active = edidInfo[59] | ((edidInfo[61] & 0xF0) << 4);␊ |
63 | ␉mode->v_blanking = ((edidInfo[61] & 0x0F) << 8) | edidInfo[60];␊ |
64 | ␉mode->h_sync_offset = ((edidInfo[65] & 0xC0) >> 2) | edidInfo[62];␊ |
65 | ␉mode->h_sync_width = (edidInfo[65] & 0x30) | edidInfo[63];␊ |
66 | ␉mode->v_sync_offset = (edidInfo[65] & 0x0C) | ((edidInfo[64] & 0x0C) >> 2);␊ |
67 | ␉mode->v_sync_width = ((edidInfo[65] & 0x3) << 2) | (edidInfo[64] & 0x03);␊ |
68 | ␉␊ |
69 | ␉␊ |
70 | ␉free( edidInfo );␊ |
71 | ␉␊ |
72 | ␉if(!mode->h_active) return 1;␊ |
73 | ␉␊ |
74 | ␉return 0;␊ |
75 | ␉␊ |
76 | }␊ |
77 | ␊ |
78 | unsigned char* readEDID()␊ |
79 | {␊ |
80 | ␉SInt16 last_reported = -1;␊ |
81 | ␉UInt8 edidInfo[EDID_BLOCK_SIZE];␊ |
82 | ␊ |
83 | ␉//UInt8 pointer;␊ |
84 | ␊ |
85 | ␉UInt8 header1[] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};␊ |
86 | ␉UInt8 header2[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};␊ |
87 | ␉␊ |
88 | ␉int status;␊ |
89 | ␉unsigned int blocks_left = 1;␊ |
90 | ␉␊ |
91 | ␉do␊ |
92 | ␉{␊ |
93 | ␉␉// TODO: This currently only retrieves the *last* block, make the block buffer expand as needed / calculated from the first block␊ |
94 | ␊ |
95 | ␉␉bzero( edidInfo, EDID_BLOCK_SIZE);␊ |
96 | ␊ |
97 | ␉␉status = getEDID(edidInfo, blocks_left);␊ |
98 | ␉␉␊ |
99 | ␉␉␉␉//printf("Buffer location: 0x%X\n", SEG(buffer) << 16 | OFF(buffer));␊ |
100 | ␊ |
101 | ␉␉/*␊ |
102 | ␉␉int j, i;␊ |
103 | ␉␉for (j = 0; j < 8; j++) {␊ |
104 | ␉␉␉for(i = 0; i < 16; i++) printf("0x%X ", ebiosInfo[((i+1) * (j + 1)) - 1]);␊ |
105 | ␊ |
106 | ␉␉}␊ |
107 | ␉␉printf("\n");␊ |
108 | ␉␉*/␊ |
109 | ␉␉␊ |
110 | ␉␉if(status == 0)␊ |
111 | ␉␉{␊ |
112 | ␉␉␉//if( edidInfo[0] == 0x00 || edidInfo[0] == 0xFF)␊ |
113 | ␉␉␉if((memcmp(edidInfo, header1, sizeof(header1)) != 0) ||␊ |
114 | ␉␉␉ (memcmp(edidInfo, header2, sizeof(header2)) != 0) )␊ |
115 | ␉␉␉{␊ |
116 | ␉␉␉␉blocks_left--;␊ |
117 | ␉␉␉␉int reported = edidInfo[ EDID_V1_BLOCKS_TO_GO_OFFSET ];␊ |
118 | ␉␉␉␉␊ |
119 | ␉␉␉␉if ( reported > blocks_left )␊ |
120 | ␉␉␉␉{␊ |
121 | ␉␉␉␉␉␊ |
122 | ␉␉␉␉␉printf("EDID claims %d more blocks left\n", reported);␊ |
123 | ␉␉␉␉}␊ |
124 | ␉␉␉␉␊ |
125 | ␉␉␉␉if ( (last_reported <= reported && last_reported != -1)␊ |
126 | ␉␉␉␉␉|| reported == 0xff␊ |
127 | ␉␉␉␉␉/* 0xff frequently comes up in corrupt edids */␊ |
128 | ␉␉␉␉␉//|| reported == MAGIC␊ |
129 | ␉␉␉␉␉)␊ |
130 | ␉␉␉␉{␊ |
131 | ␉␉␉␉␉printf("Last reported %d\n", last_reported);␊ |
132 | ␉␉␉␉␉printf( "EDID blocks left is wrong.\n"␊ |
133 | ␉␉␉␉␉␉ "Your EDID is probably invalid.\n");␊ |
134 | ␉␉␉␉␉return 0;␊ |
135 | ␉␉␉␉}␊ |
136 | ␉␉␉␉else␊ |
137 | ␉␉␉␉{␊ |
138 | ␉␉␉␉␉//printf("Reading EDID block\n");␊ |
139 | ␉␉␉␉␉//printf("H Active = %d", ebiosInfo[56] | ((ebiosInfo[58] & 0xF0) << 4) );␊ |
140 | ␉␉␉␉␉//printf("V Active = %d", ebiosInfo[59] | ((ebiosInfo[61] & 0xF0) << 4) );␊ |
141 | ␊ |
142 | ␉␉␉␉␉last_reported = reported;␊ |
143 | ␉␉␉␉␉blocks_left = reported;␊ |
144 | ␉␉␉␉}␊ |
145 | ␉␉␉} ␊ |
146 | ␉␉␉else␊ |
147 | ␉␉␉{␊ |
148 | ␉␉␉␉printf("Invalid block %d\n", blocks_left);␊ |
149 | ␉␉␉␉printf("Header1 = %d", memcmp(edidInfo, header1, sizeof(header1)) );␊ |
150 | ␉␉␉␉printf("Header2 = %d", memcmp(edidInfo, header2, sizeof(header2)) );␊ |
151 | ␉␉␉␉return 0;␊ |
152 | ␉␉␉}␊ |
153 | ␉␉} else return 0;␊ |
154 | ␉␉␊ |
155 | ␉␉blocks_left = 0;␉␊ |
156 | ␉} while(blocks_left);␊ |
157 | ␊ |
158 | ␉UInt8* ret = malloc(sizeof(edidInfo));␊ |
159 | ␉memcpy(ret, edidInfo, sizeof(edidInfo));␊ |
160 | ␉return (ret);␊ |
161 | }␊ |
162 | |