Hint added.
[AROS.git] / workbench / hidds / radeon / radeon_bios.c
blobe805e8443e6998b7baef3256b3673c2456a060cb
1 /*
2 Copyright © 2004-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: ATI radeon driver. BIOS part.
6 Lang: English
7 */
9 /*
10 * This file is a derived version of the XFree86 ATI driver (radeon_bios.c file)
13 #include <exec/types.h>
14 #include <exec/memory.h>
16 #include <hidd/hidd.h>
17 #include <hidd/graphics.h>
19 #include <proto/exec.h>
20 #include <proto/oop.h>
21 #include <proto/utility.h>
23 //#include <asm/io.h>
25 #include "ati.h"
26 #include "radeon.h"
27 #include "radeon_reg.h"
28 #include "radeon_macros.h"
29 #include "radeon_bios.h"
31 #define DEBUG 1
32 #include <aros/debug.h>
34 #undef HiddPCIDeviceAttrBase
35 #undef HiddGfxAttrBase
36 #undef HiddPixFmtAttrBase
37 #undef HiddSyncAttrBase
38 #undef HiddBitMapAttrBase
39 #define HiddPCIDeviceAttrBase (sd->pciAttrBase)
40 #define HiddATIBitMapAttrBase (sd->atiBitMapAttrBase)
41 #define HiddBitMapAttrBase (sd->bitMapAttrBase)
42 #define HiddPixFmtAttrBase (sd->pixFmtAttrBase)
43 #define HiddGfxAttrBase (sd->gfxAttrBase)
44 #define HiddSyncAttrBase (sd->syncAttrBase)
46 #ifndef MAX
47 #define MAX(a,b) ((a)>(b)?(a):(b))
48 #endif
49 #ifndef MIN
50 #define MIN(a,b) ((a)>(b)?(b):(a))
51 #endif
54 /* Read the Video BIOS block and the FP registers (if applicable). */
55 BOOL RADEONGetBIOSInfo(struct ati_staticdata *sd)
57 int tmp;
59 if (sd->Card.VBIOS[0] != 0x55 || sd->Card.VBIOS[1] != 0xaa) {
60 D(bug("[ATI] Video BIOS not detected in PCI space!\n"));
61 D(bug("[ATI] Attempting to read Video BIOS from legacy ISA space!\n"));
62 sd->Card.VBIOS = AllocPooled(sd->memPool, 65536);
63 CopyMemQuick((APTR)0x000c0000, sd->Card.VBIOS, 65536);
66 if (sd->Card.VBIOS[0] != 0x55 || sd->Card.VBIOS[1] != 0xaa) {
67 D(bug("[ATI] Unrecognized BIOS signature, BIOS data will not be used\n"));
68 if (sd->Card.VBIOS != sd->Card.vbios_org)
69 FreePooled(sd->memPool, sd->Card.VBIOS, 65536);
70 sd->Card.VBIOS = NULL;
71 return FALSE;
74 if (sd->Card.VBIOS) sd->Card.ROMHeaderStart = RADEON_BIOS16(0x48);
76 if(!sd->Card.ROMHeaderStart) {
77 D(bug("[ATI] Invalid ROM pointer, BIOS data will not be used\n"));
78 if (sd->Card.VBIOS != sd->Card.vbios_org)
79 FreePooled(sd->memPool, sd->Card.VBIOS, 65536);
80 sd->Card.VBIOS = NULL;
81 return FALSE;
84 tmp = sd->Card.ROMHeaderStart + 4;
85 if ((RADEON_BIOS8(tmp) == 'A' &&
86 RADEON_BIOS8(tmp+1) == 'T' &&
87 RADEON_BIOS8(tmp+2) == 'O' &&
88 RADEON_BIOS8(tmp+3) == 'M') ||
89 (RADEON_BIOS8(tmp) == 'M' &&
90 RADEON_BIOS8(tmp+1) == 'O' &&
91 RADEON_BIOS8(tmp+2) == 'T' &&
92 RADEON_BIOS8(tmp+3) == 'A'))
93 sd->Card.IsAtomBios = TRUE;
94 else
95 sd->Card.IsAtomBios = FALSE;
97 if (sd->Card.IsAtomBios)
98 sd->Card.MasterDataStart = RADEON_BIOS16 (sd->Card.ROMHeaderStart + 32);
100 D(bug("[ATI] %s BIOS detected\n", sd->Card.IsAtomBios ? "ATOM":"Legacy"));
102 return TRUE;
105 BOOL RADEONGetConnectorInfoFromBIOS(struct ati_staticdata *sd)
107 int i = 0, j, tmp, tmp0=0, tmp1=0;
109 if(!sd->Card.VBIOS) return FALSE;
111 if (sd->Card.IsAtomBios) {
112 if((tmp = RADEON_BIOS16 (sd->Card.MasterDataStart + 22))) {
113 int crtc = 0, id[2];
114 tmp1 = RADEON_BIOS16 (tmp + 4);
115 for (i=0; i<8; i++) {
116 if(tmp1 & (1<<i)) {
117 UWORD portinfo = RADEON_BIOS16(tmp+6+i*2);
118 if (crtc < 2) {
119 if ((i==2) || (i==6)) continue; /* ignore TV here */
121 if (crtc == 1) {
122 /* sharing same port with id[0] */
123 if (((portinfo>>8) & 0xf) == id[0]) {
124 if (i == 3)
125 sd->Card.PortInfo[0].TMDSType = TMDS_INT;
126 else if (i == 7)
127 sd->Card.PortInfo[0].TMDSType = TMDS_EXT;
129 if (sd->Card.PortInfo[0].DACType == DAC_UNKNOWN)
130 sd->Card.PortInfo[0].DACType = (portinfo & 0xf) - 1;
131 continue;
134 id[crtc] = (portinfo>>8) & 0xf;
135 sd->Card.PortInfo[crtc].DACType = (portinfo & 0xf) - 1;
136 sd->Card.PortInfo[crtc].ConnectorType = (portinfo>>4) & 0xf;
137 if (i == 3)
138 sd->Card.PortInfo[crtc].TMDSType = TMDS_INT;
139 else if (i == 7)
140 sd->Card.PortInfo[crtc].TMDSType = TMDS_EXT;
142 if((tmp0 = RADEON_BIOS16 (sd->Card.MasterDataStart + 24)) && id[crtc]) {
143 switch (RADEON_BIOS16 (tmp0 + 4 + 27 * id[crtc]) * 4)
145 case RADEON_GPIO_MONID:
146 sd->Card.PortInfo[crtc].DDCType = DDC_MONID;
147 break;
148 case RADEON_GPIO_DVI_DDC:
149 sd->Card.PortInfo[crtc].DDCType = DDC_DVI;
150 break;
151 case RADEON_GPIO_VGA_DDC:
152 sd->Card.PortInfo[crtc].DDCType = DDC_VGA;
153 break;
154 case RADEON_GPIO_CRT2_DDC:
155 sd->Card.PortInfo[crtc].DDCType = DDC_CRT2;
156 break;
157 default:
158 sd->Card.PortInfo[crtc].DDCType = DDC_NONE;
159 break;
162 } else {
163 sd->Card.PortInfo[crtc].DDCType = DDC_NONE;
165 crtc++;
166 } else {
167 /* we have already had two CRTCs assigned. the rest may share the same
168 * port with the existing connector, fill in them accordingly.
170 for (j=0; j<2; j++) {
171 if (((portinfo>>8) & 0xf) == id[j]) {
172 if (i == 3)
173 sd->Card.PortInfo[j].TMDSType = TMDS_INT;
174 else if (i == 7)
175 sd->Card.PortInfo[j].TMDSType = TMDS_EXT;
177 if (sd->Card.PortInfo[j].DACType == DAC_UNKNOWN)
178 sd->Card.PortInfo[j].DACType = (portinfo & 0xf) - 1;
185 for (i=0; i<2; i++) {
186 D(bug("[ATI] Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
187 i, sd->Card.PortInfo[i].DDCType, sd->Card.PortInfo[i].DACType,
188 sd->Card.PortInfo[i].TMDSType, sd->Card.PortInfo[i].ConnectorType));
190 } else {
191 D(bug("[ATI] No Device Info Table found!\n"));
192 return FALSE;
194 } else {
195 /* Some laptops only have one connector (VGA) listed in the connector table,
196 * we need to add LVDS in as a non-DDC display.
197 * Note, we can't assume the listed VGA will be filled in PortInfo[0],
198 * when walking through connector table. connector_found has following meaning:
199 * 0 -- nothing found,
200 * 1 -- only PortInfo[0] filled,
201 * 2 -- only PortInfo[1] filled,
202 * 3 -- both are filled.
204 int connector_found = 0;
206 if ((tmp = RADEON_BIOS16(sd->Card.ROMHeaderStart + 0x50))) {
207 for (i = 1; i < 4; i++) {
209 if (!RADEON_BIOS8(tmp + i*2) && i > 1) break; /* end of table */
211 tmp0 = RADEON_BIOS16(tmp + i*2);
212 if (((tmp0 >> 12) & 0x0f) == 0) continue; /* no connector */
213 if (connector_found > 0) {
214 if (sd->Card.PortInfo[tmp1].DDCType == ((tmp0 >> 8) & 0x0f))
215 continue; /* same connector */
218 /* internal DDC_DVI port will get assigned to PortInfo[0], or if there is no DDC_DVI (like in some IGPs). */
219 tmp1 = ((((tmp0 >> 8) & 0xf) == DDC_DVI) || (tmp1 == 1)) ? 0 : 1; /* determine port info index */
221 sd->Card.PortInfo[tmp1].DDCType = (tmp0 >> 8) & 0x0f;
222 if (sd->Card.PortInfo[tmp1].DDCType > DDC_CRT2) sd->Card.PortInfo[tmp1].DDCType = DDC_NONE_DETECTED;
223 sd->Card.PortInfo[tmp1].DACType = (tmp0 & 0x01) ? DAC_TVDAC : DAC_PRIMARY;
224 sd->Card.PortInfo[tmp1].ConnectorType = (tmp0 >> 12) & 0x0f;
225 if (sd->Card.PortInfo[tmp1].ConnectorType > CONNECTOR_UNSUPPORTED) sd->Card.PortInfo[tmp1].ConnectorType = CONNECTOR_UNSUPPORTED;
226 sd->Card.PortInfo[tmp1].TMDSType = ((tmp0 >> 4) & 0x01) ? TMDS_EXT : TMDS_INT;
228 /* some sanity checks */
229 if (((sd->Card.PortInfo[tmp1].ConnectorType != CONNECTOR_DVI_D) &&
230 (sd->Card.PortInfo[tmp1].ConnectorType != CONNECTOR_DVI_I)) &&
231 sd->Card.PortInfo[tmp1].TMDSType == TMDS_INT)
232 sd->Card.PortInfo[tmp1].TMDSType = TMDS_UNKNOWN;
234 connector_found += (tmp1 + 1);
236 } else {
237 D(bug("[ATI] No Connector Info Table found!\n"));
238 return FALSE;
240 if (sd->Card.IsMobility) {
241 /* For the cases where only one VGA connector is found,
242 we assume LVDS is not listed in the connector table,
243 add it in here as the first port.
245 if ((connector_found < 3) && (sd->Card.PortInfo[tmp1].ConnectorType == CONNECTOR_CRT)) {
246 if (connector_found == 1) {
247 memcpy (&sd->Card.PortInfo[1], &sd->Card.PortInfo[0],
248 sizeof (sd->Card.PortInfo[0]));
250 sd->Card.PortInfo[0].DACType = DAC_TVDAC;
251 sd->Card.PortInfo[0].TMDSType = TMDS_UNKNOWN;
252 sd->Card.PortInfo[0].DDCType = DDC_NONE_DETECTED;
253 sd->Card.PortInfo[0].ConnectorType = CONNECTOR_PROPRIETARY;
255 D(bug("[ATI] LVDS port is not in connector table, added in.\n"));
256 if (connector_found == 0) connector_found = 1;
257 else connector_found = 3;
260 if ((tmp = RADEON_BIOS16(sd->Card.ROMHeaderStart + 0x42))) {
261 if ((tmp0 = RADEON_BIOS16(tmp + 0x15))) {
262 if ((tmp1 = RADEON_BIOS8(tmp0+2) & 0x07)) {
263 sd->Card.PortInfo[0].DDCType = tmp1;
264 D(bug("[ATI] LCD DDC Info Table found!\n"));
268 } else if (connector_found == 2) {
269 memcpy (&sd->Card.PortInfo[0], &sd->Card.PortInfo[1],
270 sizeof (sd->Card.PortInfo[0]));
271 sd->Card.PortInfo[1].DACType = DAC_UNKNOWN;
272 sd->Card.PortInfo[1].TMDSType = TMDS_UNKNOWN;
273 sd->Card.PortInfo[1].DDCType = DDC_NONE_DETECTED;
274 sd->Card.PortInfo[1].ConnectorType = CONNECTOR_NONE;
275 connector_found = 1;
278 if (connector_found == 0) {
279 D(bug("[ATI] No connector found in Connector Info Table.\n"));
280 } else {
281 D(bug("[ATI] Connector0: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
282 sd->Card.PortInfo[0].DDCType, sd->Card.PortInfo[0].DACType,
283 sd->Card.PortInfo[0].TMDSType, sd->Card.PortInfo[0].ConnectorType));
285 if (connector_found == 3) {
286 D(bug("[ATI] Connector1: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
287 sd->Card.PortInfo[1].DDCType, sd->Card.PortInfo[1].DACType,
288 sd->Card.PortInfo[1].TMDSType, sd->Card.PortInfo[1].ConnectorType));
291 return TRUE;
294 /* Read PLL parameters from BIOS block. Default to typical values if there
295 is no BIOS. */
296 BOOL RADEONGetClockInfoFromBIOS(struct ati_staticdata *sd)
298 RADEONPLLRec *pll = &sd->Card.pll;
299 UWORD pll_info_block;
301 if (!sd->Card.VBIOS) {
302 return FALSE;
303 } else {
304 if (sd->Card.IsAtomBios) {
305 pll_info_block = RADEON_BIOS16 (sd->Card.MasterDataStart + 12);
307 pll->reference_freq = RADEON_BIOS16 (pll_info_block + 82);
308 pll->reference_div = 0; /* Need to derive from existing setting
309 or use a new algorithm to calculate
310 from min_input and max_input
312 pll->min_pll_freq = RADEON_BIOS16 (pll_info_block + 78);
313 pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 32);
314 pll->xclk = RADEON_BIOS16 (pll_info_block + 72);
316 sd->Card.sclk = RADEON_BIOS32(pll_info_block + 8) / 100.0;
317 sd->Card.mclk = RADEON_BIOS32(pll_info_block + 12) / 100.0;
318 if (sd->Card.sclk == 0) sd->Card.sclk = 200;
319 if (sd->Card.mclk == 0) sd->Card.mclk = 200;
321 D(bug("[ATI] ref_freq: %d, min_pll: %ld, max_pll: %ld, xclk: %d, sclk: %f, mclk: %f\n",
322 pll->reference_freq, pll->min_pll_freq, pll->max_pll_freq, pll->xclk, sd->Card.sclk, sd->Card.mclk));
324 } else {
325 pll_info_block = RADEON_BIOS16 (sd->Card.ROMHeaderStart + 0x30);
327 pll->reference_freq = RADEON_BIOS16 (pll_info_block + 0x0e);
328 pll->reference_div = RADEON_BIOS16 (pll_info_block + 0x10);
329 pll->min_pll_freq = RADEON_BIOS32 (pll_info_block + 0x12);
330 pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 0x16);
331 pll->xclk = RADEON_BIOS16 (pll_info_block + 0x08);
333 sd->Card.sclk = RADEON_BIOS16(pll_info_block + 8) / 100.0;
334 sd->Card.mclk = RADEON_BIOS16(pll_info_block + 10) / 100.0;
338 return TRUE;