2 Copyright � 2004-2007, The AROS Development Team. All rights reserved.
5 Desc: ATI radeon driver. BIOS part.
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>
28 #include "radeon_reg.h"
29 #include "radeon_macros.h"
30 #include "radeon_bios.h"
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)
48 #define MAX(a,b) ((a)>(b)?(a):(b))
51 #define MIN(a,b) ((a)>(b)?(b):(a))
55 /* Read the Video BIOS block and the FP registers (if applicable). */
56 BOOL
RADEONGetBIOSInfo(struct ati_staticdata
*sd
)
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");
70 void *rom_prop
= OF_FindProperty(key
, "rom");
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
;
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
;
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
;
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"));
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))) {
123 tmp1
= RADEON_BIOS16 (tmp
+ 4);
124 for (i
=0; i
<8; i
++) {
126 UWORD portinfo
= RADEON_BIOS16(tmp
+6+i
*2);
128 if ((i
==2) || (i
==6)) continue; /* ignore TV here */
131 /* sharing same port with id[0] */
132 if (((portinfo
>>8) & 0xf) == id
[0]) {
134 sd
->Card
.PortInfo
[0].TMDSType
= TMDS_INT
;
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;
143 id
[crtc
] = (portinfo
>>8) & 0xf;
144 sd
->Card
.PortInfo
[crtc
].DACType
= (portinfo
& 0xf) - 1;
145 sd
->Card
.PortInfo
[crtc
].ConnectorType
= (portinfo
>>4) & 0xf;
147 sd
->Card
.PortInfo
[crtc
].TMDSType
= TMDS_INT
;
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
;
157 case RADEON_GPIO_DVI_DDC
:
158 sd
->Card
.PortInfo
[crtc
].DDCType
= DDC_DVI
;
160 case RADEON_GPIO_VGA_DDC
:
161 sd
->Card
.PortInfo
[crtc
].DDCType
= DDC_VGA
;
163 case RADEON_GPIO_CRT2_DDC
:
164 sd
->Card
.PortInfo
[crtc
].DDCType
= DDC_CRT2
;
167 sd
->Card
.PortInfo
[crtc
].DDCType
= DDC_NONE
;
172 sd
->Card
.PortInfo
[crtc
].DDCType
= DDC_NONE
;
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
]) {
182 sd
->Card
.PortInfo
[j
].TMDSType
= TMDS_INT
;
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
));
200 D(bug("[ATI] No Device Info Table found!\n"));
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);
246 D(bug("[ATI] No Connector Info Table found!\n"));
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
;
287 if (connector_found
== 0) {
288 D(bug("[ATI] No connector found in Connector Info Table.\n"));
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
));
303 /* Read PLL parameters from BIOS block. Default to typical values if there
305 BOOL
RADEONGetClockInfoFromBIOS(struct ati_staticdata
*sd
)
307 RADEONPLLRec
*pll
= &sd
->Card
.pll
;
308 UWORD pll_info_block
;
310 if (!sd
->Card
.VBIOS
) {
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
));
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;