make.tmpl: add missing compiler attribute to build_progs
[AROS.git] / arch / ppc-chrp / hidd.radeon / radeon_bios.c
blob8c1d3b575ac35c371daf08be39970525e1ce9543
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>
22 #include <proto/openfirmware.h>
24 //#include <asm/io.h>
26 #include "ati.h"
27 #include "radeon.h"
28 #include "radeon_reg.h"
29 #include "radeon_macros.h"
30 #include "radeon_bios.h"
32 #define DEBUG 1
33 #include <aros/debug.h>
35 #undef HiddPCIDeviceAttrBase
36 #undef HiddGfxAttrBase
37 #undef HiddPixFmtAttrBase
38 #undef HiddSyncAttrBase
39 #undef HiddBitMapAttrBase
40 #define HiddPCIDeviceAttrBase (sd->pciAttrBase)
41 #define HiddATIBitMapAttrBase (sd->atiBitMapAttrBase)
42 #define HiddBitMapAttrBase (sd->bitMapAttrBase)
43 #define HiddPixFmtAttrBase (sd->pixFmtAttrBase)
44 #define HiddGfxAttrBase (sd->gfxAttrBase)
45 #define HiddSyncAttrBase (sd->syncAttrBase)
47 #ifndef MAX
48 #define MAX(a,b) ((a)>(b)?(a):(b))
49 #endif
50 #ifndef MIN
51 #define MIN(a,b) ((a)>(b)?(b):(a))
52 #endif
55 /* Read the Video BIOS block and the FP registers (if applicable). */
56 BOOL RADEONGetBIOSInfo(struct ati_staticdata *sd)
58 int tmp;
60 if (sd->Card.VBIOS[0] != 0x55 || sd->Card.VBIOS[1] != 0xaa) {
61 D(bug("[ATI] Video BIOS not detected in PCI space!\n"));
62 D(bug("[ATI] Attempting to read Video BIOS using openfirmware\n"));
63 sd->Card.VBIOS = NULL;
65 void *OpenFirmwareBase = OpenResource("openfirmware.resource");
66 void *key = OF_OpenKey("/pci/display");
68 if (key)
70 void *rom_prop = OF_FindProperty(key, "rom");
71 if (rom_prop)
72 sd->Card.VBIOS = OF_GetPropValue(rom_prop);
74 D(bug("[ATI] OF reported BIOS at %08x\n", sd->Card.VBIOS));
77 if (sd->Card.VBIOS[0] != 0x55 || sd->Card.VBIOS[1] != 0xaa) {
78 D(bug("[ATI] Unrecognized BIOS signature, BIOS data will not be used\n"));
79 sd->Card.VBIOS = NULL;
80 return FALSE;
83 if (sd->Card.VBIOS) sd->Card.ROMHeaderStart = RADEON_BIOS16(0x48);
85 if(!sd->Card.ROMHeaderStart) {
86 D(bug("[ATI] Invalid ROM pointer, BIOS data will not be used\n"));
87 if (sd->Card.VBIOS != sd->Card.vbios_org)
88 FreePooled(sd->memPool, sd->Card.VBIOS, 65536);
89 sd->Card.VBIOS = NULL;
90 return FALSE;
93 tmp = sd->Card.ROMHeaderStart + 4;
94 if ((RADEON_BIOS8(tmp) == 'A' &&
95 RADEON_BIOS8(tmp+1) == 'T' &&
96 RADEON_BIOS8(tmp+2) == 'O' &&
97 RADEON_BIOS8(tmp+3) == 'M') ||
98 (RADEON_BIOS8(tmp) == 'M' &&
99 RADEON_BIOS8(tmp+1) == 'O' &&
100 RADEON_BIOS8(tmp+2) == 'T' &&
101 RADEON_BIOS8(tmp+3) == 'A'))
102 sd->Card.IsAtomBios = TRUE;
103 else
104 sd->Card.IsAtomBios = FALSE;
106 if (sd->Card.IsAtomBios)
107 sd->Card.MasterDataStart = RADEON_BIOS16 (sd->Card.ROMHeaderStart + 32);
109 D(bug("[ATI] %s BIOS detected\n", sd->Card.IsAtomBios ? "ATOM":"Legacy"));
111 return TRUE;
114 BOOL RADEONGetConnectorInfoFromBIOS(struct ati_staticdata *sd)
116 int i = 0, j, tmp, tmp0=0, tmp1=0;
118 if(!sd->Card.VBIOS) return FALSE;
120 if (sd->Card.IsAtomBios) {
121 if((tmp = RADEON_BIOS16 (sd->Card.MasterDataStart + 22))) {
122 int crtc = 0, id[2];
123 tmp1 = RADEON_BIOS16 (tmp + 4);
124 for (i=0; i<8; i++) {
125 if(tmp1 & (1<<i)) {
126 UWORD portinfo = RADEON_BIOS16(tmp+6+i*2);
127 if (crtc < 2) {
128 if ((i==2) || (i==6)) continue; /* ignore TV here */
130 if (crtc == 1) {
131 /* sharing same port with id[0] */
132 if (((portinfo>>8) & 0xf) == id[0]) {
133 if (i == 3)
134 sd->Card.PortInfo[0].TMDSType = TMDS_INT;
135 else if (i == 7)
136 sd->Card.PortInfo[0].TMDSType = TMDS_EXT;
138 if (sd->Card.PortInfo[0].DACType == DAC_UNKNOWN)
139 sd->Card.PortInfo[0].DACType = (portinfo & 0xf) - 1;
140 continue;
143 id[crtc] = (portinfo>>8) & 0xf;
144 sd->Card.PortInfo[crtc].DACType = (portinfo & 0xf) - 1;
145 sd->Card.PortInfo[crtc].ConnectorType = (portinfo>>4) & 0xf;
146 if (i == 3)
147 sd->Card.PortInfo[crtc].TMDSType = TMDS_INT;
148 else if (i == 7)
149 sd->Card.PortInfo[crtc].TMDSType = TMDS_EXT;
151 if((tmp0 = RADEON_BIOS16 (sd->Card.MasterDataStart + 24)) && id[crtc]) {
152 switch (RADEON_BIOS16 (tmp0 + 4 + 27 * id[crtc]) * 4)
154 case RADEON_GPIO_MONID:
155 sd->Card.PortInfo[crtc].DDCType = DDC_MONID;
156 break;
157 case RADEON_GPIO_DVI_DDC:
158 sd->Card.PortInfo[crtc].DDCType = DDC_DVI;
159 break;
160 case RADEON_GPIO_VGA_DDC:
161 sd->Card.PortInfo[crtc].DDCType = DDC_VGA;
162 break;
163 case RADEON_GPIO_CRT2_DDC:
164 sd->Card.PortInfo[crtc].DDCType = DDC_CRT2;
165 break;
166 default:
167 sd->Card.PortInfo[crtc].DDCType = DDC_NONE;
168 break;
171 } else {
172 sd->Card.PortInfo[crtc].DDCType = DDC_NONE;
174 crtc++;
175 } else {
176 /* we have already had two CRTCs assigned. the rest may share the same
177 * port with the existing connector, fill in them accordingly.
179 for (j=0; j<2; j++) {
180 if (((portinfo>>8) & 0xf) == id[j]) {
181 if (i == 3)
182 sd->Card.PortInfo[j].TMDSType = TMDS_INT;
183 else if (i == 7)
184 sd->Card.PortInfo[j].TMDSType = TMDS_EXT;
186 if (sd->Card.PortInfo[j].DACType == DAC_UNKNOWN)
187 sd->Card.PortInfo[j].DACType = (portinfo & 0xf) - 1;
194 for (i=0; i<2; i++) {
195 D(bug("[ATI] Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
196 i, sd->Card.PortInfo[i].DDCType, sd->Card.PortInfo[i].DACType,
197 sd->Card.PortInfo[i].TMDSType, sd->Card.PortInfo[i].ConnectorType));
199 } else {
200 D(bug("[ATI] No Device Info Table found!\n"));
201 return FALSE;
203 } else {
204 /* Some laptops only have one connector (VGA) listed in the connector table,
205 * we need to add LVDS in as a non-DDC display.
206 * Note, we can't assume the listed VGA will be filled in PortInfo[0],
207 * when walking through connector table. connector_found has following meaning:
208 * 0 -- nothing found,
209 * 1 -- only PortInfo[0] filled,
210 * 2 -- only PortInfo[1] filled,
211 * 3 -- both are filled.
213 int connector_found = 0;
215 if ((tmp = RADEON_BIOS16(sd->Card.ROMHeaderStart + 0x50))) {
216 for (i = 1; i < 4; i++) {
218 if (!RADEON_BIOS8(tmp + i*2) && i > 1) break; /* end of table */
220 tmp0 = RADEON_BIOS16(tmp + i*2);
221 if (((tmp0 >> 12) & 0x0f) == 0) continue; /* no connector */
222 if (connector_found > 0) {
223 if (sd->Card.PortInfo[tmp1].DDCType == ((tmp0 >> 8) & 0x0f))
224 continue; /* same connector */
227 /* internal DDC_DVI port will get assigned to PortInfo[0], or if there is no DDC_DVI (like in some IGPs). */
228 tmp1 = ((((tmp0 >> 8) & 0xf) == DDC_DVI) || (tmp1 == 1)) ? 0 : 1; /* determine port info index */
230 sd->Card.PortInfo[tmp1].DDCType = (tmp0 >> 8) & 0x0f;
231 if (sd->Card.PortInfo[tmp1].DDCType > DDC_CRT2) sd->Card.PortInfo[tmp1].DDCType = DDC_NONE_DETECTED;
232 sd->Card.PortInfo[tmp1].DACType = (tmp0 & 0x01) ? DAC_TVDAC : DAC_PRIMARY;
233 sd->Card.PortInfo[tmp1].ConnectorType = (tmp0 >> 12) & 0x0f;
234 if (sd->Card.PortInfo[tmp1].ConnectorType > CONNECTOR_UNSUPPORTED) sd->Card.PortInfo[tmp1].ConnectorType = CONNECTOR_UNSUPPORTED;
235 sd->Card.PortInfo[tmp1].TMDSType = ((tmp0 >> 4) & 0x01) ? TMDS_EXT : TMDS_INT;
237 /* some sanity checks */
238 if (((sd->Card.PortInfo[tmp1].ConnectorType != CONNECTOR_DVI_D) &&
239 (sd->Card.PortInfo[tmp1].ConnectorType != CONNECTOR_DVI_I)) &&
240 sd->Card.PortInfo[tmp1].TMDSType == TMDS_INT)
241 sd->Card.PortInfo[tmp1].TMDSType = TMDS_UNKNOWN;
243 connector_found += (tmp1 + 1);
245 } else {
246 D(bug("[ATI] No Connector Info Table found!\n"));
247 return FALSE;
249 if (sd->Card.IsMobility) {
250 /* For the cases where only one VGA connector is found,
251 we assume LVDS is not listed in the connector table,
252 add it in here as the first port.
254 if ((connector_found < 3) && (sd->Card.PortInfo[tmp1].ConnectorType == CONNECTOR_CRT)) {
255 if (connector_found == 1) {
256 memcpy (&sd->Card.PortInfo[1], &sd->Card.PortInfo[0],
257 sizeof (sd->Card.PortInfo[0]));
259 sd->Card.PortInfo[0].DACType = DAC_TVDAC;
260 sd->Card.PortInfo[0].TMDSType = TMDS_UNKNOWN;
261 sd->Card.PortInfo[0].DDCType = DDC_NONE_DETECTED;
262 sd->Card.PortInfo[0].ConnectorType = CONNECTOR_PROPRIETARY;
264 D(bug("[ATI] LVDS port is not in connector table, added in.\n"));
265 if (connector_found == 0) connector_found = 1;
266 else connector_found = 3;
269 if ((tmp = RADEON_BIOS16(sd->Card.ROMHeaderStart + 0x42))) {
270 if ((tmp0 = RADEON_BIOS16(tmp + 0x15))) {
271 if ((tmp1 = RADEON_BIOS8(tmp0+2) & 0x07)) {
272 sd->Card.PortInfo[0].DDCType = tmp1;
273 D(bug("[ATI] LCD DDC Info Table found!\n"));
277 } else if (connector_found == 2) {
278 memcpy (&sd->Card.PortInfo[0], &sd->Card.PortInfo[1],
279 sizeof (sd->Card.PortInfo[0]));
280 sd->Card.PortInfo[1].DACType = DAC_UNKNOWN;
281 sd->Card.PortInfo[1].TMDSType = TMDS_UNKNOWN;
282 sd->Card.PortInfo[1].DDCType = DDC_NONE_DETECTED;
283 sd->Card.PortInfo[1].ConnectorType = CONNECTOR_NONE;
284 connector_found = 1;
287 if (connector_found == 0) {
288 D(bug("[ATI] No connector found in Connector Info Table.\n"));
289 } else {
290 D(bug("[ATI] Connector0: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
291 sd->Card.PortInfo[0].DDCType, sd->Card.PortInfo[0].DACType,
292 sd->Card.PortInfo[0].TMDSType, sd->Card.PortInfo[0].ConnectorType));
294 if (connector_found == 3) {
295 D(bug("[ATI] Connector1: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
296 sd->Card.PortInfo[1].DDCType, sd->Card.PortInfo[1].DACType,
297 sd->Card.PortInfo[1].TMDSType, sd->Card.PortInfo[1].ConnectorType));
300 return TRUE;
303 /* Read PLL parameters from BIOS block. Default to typical values if there
304 is no BIOS. */
305 BOOL RADEONGetClockInfoFromBIOS(struct ati_staticdata *sd)
307 RADEONPLLRec *pll = &sd->Card.pll;
308 UWORD pll_info_block;
310 if (!sd->Card.VBIOS) {
311 return FALSE;
312 } else {
313 if (sd->Card.IsAtomBios) {
314 pll_info_block = RADEON_BIOS16 (sd->Card.MasterDataStart + 12);
316 pll->reference_freq = RADEON_BIOS16 (pll_info_block + 82);
317 pll->reference_div = 0; /* Need to derive from existing setting
318 or use a new algorithm to calculate
319 from min_input and max_input
321 pll->min_pll_freq = RADEON_BIOS16 (pll_info_block + 78);
322 pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 32);
323 pll->xclk = RADEON_BIOS16 (pll_info_block + 72);
325 sd->Card.sclk = RADEON_BIOS32(pll_info_block + 8) / 100.0;
326 sd->Card.mclk = RADEON_BIOS32(pll_info_block + 12) / 100.0;
327 if (sd->Card.sclk == 0) sd->Card.sclk = 200;
328 if (sd->Card.mclk == 0) sd->Card.mclk = 200;
330 D(bug("[ATI] ref_freq: %d, min_pll: %ld, max_pll: %ld, xclk: %d, sclk: %f, mclk: %f\n",
331 pll->reference_freq, pll->min_pll_freq, pll->max_pll_freq, pll->xclk, sd->Card.sclk, sd->Card.mclk));
333 } else {
334 pll_info_block = RADEON_BIOS16 (sd->Card.ROMHeaderStart + 0x30);
336 pll->reference_freq = RADEON_BIOS16 (pll_info_block + 0x0e);
337 pll->reference_div = RADEON_BIOS16 (pll_info_block + 0x10);
338 pll->min_pll_freq = RADEON_BIOS32 (pll_info_block + 0x12);
339 pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 0x16);
340 pll->xclk = RADEON_BIOS16 (pll_info_block + 0x08);
342 sd->Card.sclk = RADEON_BIOS16(pll_info_block + 8) / 100.0;
343 sd->Card.mclk = RADEON_BIOS16(pll_info_block + 10) / 100.0;
347 return TRUE;