2 Copyright © 2004-2017, 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>
19 #include <proto/exec.h>
20 #include <proto/oop.h>
21 #include <proto/utility.h>
25 #include "radeon_reg.h"
26 #include "radeon_macros.h"
27 #include "radeon_bios.h"
28 #include "radeon_bios_rom.h"
31 #include <aros/debug.h>
33 #undef HiddPCIDeviceAttrBase
34 #undef HiddGfxAttrBase
35 #undef HiddPixFmtAttrBase
36 #undef HiddSyncAttrBase
37 #undef HiddBitMapAttrBase
38 #define HiddPCIDeviceAttrBase (sd->pciAttrBase)
39 #define HiddATIBitMapAttrBase (sd->atiBitMapAttrBase)
40 #define HiddBitMapAttrBase (sd->bitMapAttrBase)
41 #define HiddPixFmtAttrBase (sd->pixFmtAttrBase)
42 #define HiddGfxAttrBase (sd->gfxAttrBase)
43 #define HiddSyncAttrBase (sd->syncAttrBase)
46 #define MAX(a,b) ((a)>(b)?(a):(b))
49 #define MIN(a,b) ((a)>(b)?(b):(a))
53 /* Read the Video BIOS block and the FP registers (if applicable). */
54 BOOL
RADEONGetBIOSInfo(struct ati_staticdata
*sd
)
58 sd
->Card
.VBIOS
= radeon_bios
;
60 if (sd
->Card
.VBIOS
[0] != 0x55 || sd
->Card
.VBIOS
[1] != 0xaa) {
61 D(bug("[ATI] Unrecognized BIOS signature, BIOS data will not be used\n"));
62 sd
->Card
.VBIOS
= NULL
;
66 if (sd
->Card
.VBIOS
) sd
->Card
.ROMHeaderStart
= RADEON_BIOS16(0x48);
68 if(!sd
->Card
.ROMHeaderStart
) {
69 D(bug("[ATI] Invalid ROM pointer, BIOS data will not be used\n"));
70 sd
->Card
.VBIOS
= NULL
;
74 tmp
= sd
->Card
.ROMHeaderStart
+ 4;
75 if ((RADEON_BIOS8(tmp
) == 'A' &&
76 RADEON_BIOS8(tmp
+1) == 'T' &&
77 RADEON_BIOS8(tmp
+2) == 'O' &&
78 RADEON_BIOS8(tmp
+3) == 'M') ||
79 (RADEON_BIOS8(tmp
) == 'M' &&
80 RADEON_BIOS8(tmp
+1) == 'O' &&
81 RADEON_BIOS8(tmp
+2) == 'T' &&
82 RADEON_BIOS8(tmp
+3) == 'A'))
83 sd
->Card
.IsAtomBios
= TRUE
;
85 sd
->Card
.IsAtomBios
= FALSE
;
87 if (sd
->Card
.IsAtomBios
)
88 sd
->Card
.MasterDataStart
= RADEON_BIOS16 (sd
->Card
.ROMHeaderStart
+ 32);
90 D(bug("[ATI] %s BIOS detected\n", sd
->Card
.IsAtomBios
? "ATOM":"Legacy"));
95 BOOL
RADEONGetConnectorInfoFromBIOS(struct ati_staticdata
*sd
)
97 int i
= 0, j
, tmp
, tmp0
=0, tmp1
=0;
99 if(!sd
->Card
.VBIOS
) return FALSE
;
101 if (sd
->Card
.IsAtomBios
) {
102 if((tmp
= RADEON_BIOS16 (sd
->Card
.MasterDataStart
+ 22))) {
104 tmp1
= RADEON_BIOS16 (tmp
+ 4);
105 for (i
=0; i
<8; i
++) {
107 UWORD portinfo
= RADEON_BIOS16(tmp
+6+i
*2);
109 if ((i
==2) || (i
==6)) continue; /* ignore TV here */
112 /* sharing same port with id[0] */
113 if (((portinfo
>>8) & 0xf) == id
[0]) {
115 sd
->Card
.PortInfo
[0].TMDSType
= TMDS_INT
;
117 sd
->Card
.PortInfo
[0].TMDSType
= TMDS_EXT
;
119 if (sd
->Card
.PortInfo
[0].DACType
== DAC_UNKNOWN
)
120 sd
->Card
.PortInfo
[0].DACType
= (portinfo
& 0xf) - 1;
124 id
[crtc
] = (portinfo
>>8) & 0xf;
125 sd
->Card
.PortInfo
[crtc
].DACType
= (portinfo
& 0xf) - 1;
126 sd
->Card
.PortInfo
[crtc
].ConnectorType
= (portinfo
>>4) & 0xf;
128 sd
->Card
.PortInfo
[crtc
].TMDSType
= TMDS_INT
;
130 sd
->Card
.PortInfo
[crtc
].TMDSType
= TMDS_EXT
;
132 if((tmp0
= RADEON_BIOS16 (sd
->Card
.MasterDataStart
+ 24)) && id
[crtc
]) {
133 switch (RADEON_BIOS16 (tmp0
+ 4 + 27 * id
[crtc
]) * 4)
135 case RADEON_GPIO_MONID
:
136 sd
->Card
.PortInfo
[crtc
].DDCType
= DDC_MONID
;
138 case RADEON_GPIO_DVI_DDC
:
139 sd
->Card
.PortInfo
[crtc
].DDCType
= DDC_DVI
;
141 case RADEON_GPIO_VGA_DDC
:
142 sd
->Card
.PortInfo
[crtc
].DDCType
= DDC_VGA
;
144 case RADEON_GPIO_CRT2_DDC
:
145 sd
->Card
.PortInfo
[crtc
].DDCType
= DDC_CRT2
;
148 sd
->Card
.PortInfo
[crtc
].DDCType
= DDC_NONE
;
153 sd
->Card
.PortInfo
[crtc
].DDCType
= DDC_NONE
;
157 /* we have already had two CRTCs assigned. the rest may share the same
158 * port with the existing connector, fill in them accordingly.
160 for (j
=0; j
<2; j
++) {
161 if (((portinfo
>>8) & 0xf) == id
[j
]) {
163 sd
->Card
.PortInfo
[j
].TMDSType
= TMDS_INT
;
165 sd
->Card
.PortInfo
[j
].TMDSType
= TMDS_EXT
;
167 if (sd
->Card
.PortInfo
[j
].DACType
== DAC_UNKNOWN
)
168 sd
->Card
.PortInfo
[j
].DACType
= (portinfo
& 0xf) - 1;
175 for (i
=0; i
<2; i
++) {
176 D(bug("[ATI] Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
177 i
, sd
->Card
.PortInfo
[i
].DDCType
, sd
->Card
.PortInfo
[i
].DACType
,
178 sd
->Card
.PortInfo
[i
].TMDSType
, sd
->Card
.PortInfo
[i
].ConnectorType
));
181 D(bug("[ATI] No Device Info Table found!\n"));
185 /* Some laptops only have one connector (VGA) listed in the connector table,
186 * we need to add LVDS in as a non-DDC display.
187 * Note, we can't assume the listed VGA will be filled in PortInfo[0],
188 * when walking through connector table. connector_found has following meaning:
189 * 0 -- nothing found,
190 * 1 -- only PortInfo[0] filled,
191 * 2 -- only PortInfo[1] filled,
192 * 3 -- both are filled.
194 int connector_found
= 0;
196 if ((tmp
= RADEON_BIOS16(sd
->Card
.ROMHeaderStart
+ 0x50))) {
197 for (i
= 1; i
< 4; i
++) {
199 if (!RADEON_BIOS8(tmp
+ i
*2) && i
> 1) break; /* end of table */
201 tmp0
= RADEON_BIOS16(tmp
+ i
*2);
202 if (((tmp0
>> 12) & 0x0f) == 0) continue; /* no connector */
203 if (connector_found
> 0) {
204 if (sd
->Card
.PortInfo
[tmp1
].DDCType
== ((tmp0
>> 8) & 0x0f))
205 continue; /* same connector */
208 /* internal DDC_DVI port will get assigned to PortInfo[0], or if there is no DDC_DVI (like in some IGPs). */
209 tmp1
= ((((tmp0
>> 8) & 0xf) == DDC_DVI
) || (tmp1
== 1)) ? 0 : 1; /* determine port info index */
211 sd
->Card
.PortInfo
[tmp1
].DDCType
= (tmp0
>> 8) & 0x0f;
212 if (sd
->Card
.PortInfo
[tmp1
].DDCType
> DDC_CRT2
) sd
->Card
.PortInfo
[tmp1
].DDCType
= DDC_NONE_DETECTED
;
213 sd
->Card
.PortInfo
[tmp1
].DACType
= (tmp0
& 0x01) ? DAC_TVDAC
: DAC_PRIMARY
;
214 sd
->Card
.PortInfo
[tmp1
].ConnectorType
= (tmp0
>> 12) & 0x0f;
215 if (sd
->Card
.PortInfo
[tmp1
].ConnectorType
> CONNECTOR_UNSUPPORTED
) sd
->Card
.PortInfo
[tmp1
].ConnectorType
= CONNECTOR_UNSUPPORTED
;
216 sd
->Card
.PortInfo
[tmp1
].TMDSType
= ((tmp0
>> 4) & 0x01) ? TMDS_EXT
: TMDS_INT
;
218 /* some sanity checks */
219 if (((sd
->Card
.PortInfo
[tmp1
].ConnectorType
!= CONNECTOR_DVI_D
) &&
220 (sd
->Card
.PortInfo
[tmp1
].ConnectorType
!= CONNECTOR_DVI_I
)) &&
221 sd
->Card
.PortInfo
[tmp1
].TMDSType
== TMDS_INT
)
222 sd
->Card
.PortInfo
[tmp1
].TMDSType
= TMDS_UNKNOWN
;
224 connector_found
+= (tmp1
+ 1);
227 D(bug("[ATI] No Connector Info Table found!\n"));
230 if (sd
->Card
.IsMobility
) {
231 /* For the cases where only one VGA connector is found,
232 we assume LVDS is not listed in the connector table,
233 add it in here as the first port.
235 if ((connector_found
< 3) && (sd
->Card
.PortInfo
[tmp1
].ConnectorType
== CONNECTOR_CRT
)) {
236 if (connector_found
== 1) {
237 memcpy (&sd
->Card
.PortInfo
[1], &sd
->Card
.PortInfo
[0],
238 sizeof (sd
->Card
.PortInfo
[0]));
240 sd
->Card
.PortInfo
[0].DACType
= DAC_TVDAC
;
241 sd
->Card
.PortInfo
[0].TMDSType
= TMDS_UNKNOWN
;
242 sd
->Card
.PortInfo
[0].DDCType
= DDC_NONE_DETECTED
;
243 sd
->Card
.PortInfo
[0].ConnectorType
= CONNECTOR_PROPRIETARY
;
245 D(bug("[ATI] LVDS port is not in connector table, added in.\n"));
246 if (connector_found
== 0) connector_found
= 1;
247 else connector_found
= 3;
250 if ((tmp
= RADEON_BIOS16(sd
->Card
.ROMHeaderStart
+ 0x42))) {
251 if ((tmp0
= RADEON_BIOS16(tmp
+ 0x15))) {
252 if ((tmp1
= RADEON_BIOS8(tmp0
+2) & 0x07)) {
253 sd
->Card
.PortInfo
[0].DDCType
= tmp1
;
254 D(bug("[ATI] LCD DDC Info Table found!\n"));
258 } else if (connector_found
== 2) {
259 memcpy (&sd
->Card
.PortInfo
[0], &sd
->Card
.PortInfo
[1],
260 sizeof (sd
->Card
.PortInfo
[0]));
261 sd
->Card
.PortInfo
[1].DACType
= DAC_UNKNOWN
;
262 sd
->Card
.PortInfo
[1].TMDSType
= TMDS_UNKNOWN
;
263 sd
->Card
.PortInfo
[1].DDCType
= DDC_NONE_DETECTED
;
264 sd
->Card
.PortInfo
[1].ConnectorType
= CONNECTOR_NONE
;
268 if (connector_found
== 0) {
269 D(bug("[ATI] No connector found in Connector Info Table.\n"));
271 D(bug("[ATI] Connector0: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
272 sd
->Card
.PortInfo
[0].DDCType
, sd
->Card
.PortInfo
[0].DACType
,
273 sd
->Card
.PortInfo
[0].TMDSType
, sd
->Card
.PortInfo
[0].ConnectorType
));
275 if (connector_found
== 3) {
276 D(bug("[ATI] Connector1: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
277 sd
->Card
.PortInfo
[1].DDCType
, sd
->Card
.PortInfo
[1].DACType
,
278 sd
->Card
.PortInfo
[1].TMDSType
, sd
->Card
.PortInfo
[1].ConnectorType
));
284 /* Read PLL parameters from BIOS block. Default to typical values if there
286 BOOL
RADEONGetClockInfoFromBIOS(struct ati_staticdata
*sd
)
288 RADEONPLLRec
*pll
= &sd
->Card
.pll
;
289 UWORD pll_info_block
;
291 if (!sd
->Card
.VBIOS
) {
294 if (sd
->Card
.IsAtomBios
) {
295 pll_info_block
= RADEON_BIOS16 (sd
->Card
.MasterDataStart
+ 12);
297 pll
->reference_freq
= RADEON_BIOS16 (pll_info_block
+ 82);
298 pll
->reference_div
= 0; /* Need to derive from existing setting
299 or use a new algorithm to calculate
300 from min_input and max_input
302 pll
->min_pll_freq
= RADEON_BIOS16 (pll_info_block
+ 78);
303 pll
->max_pll_freq
= RADEON_BIOS32 (pll_info_block
+ 32);
304 pll
->xclk
= RADEON_BIOS16 (pll_info_block
+ 72);
306 sd
->Card
.sclk
= RADEON_BIOS32(pll_info_block
+ 8) / 100.0;
307 sd
->Card
.mclk
= RADEON_BIOS32(pll_info_block
+ 12) / 100.0;
308 if (sd
->Card
.sclk
== 0) sd
->Card
.sclk
= 200;
309 if (sd
->Card
.mclk
== 0) sd
->Card
.mclk
= 200;
311 D(bug("[ATI] ref_freq: %d, min_pll: %ld, max_pll: %ld, xclk: %d, sclk: %f, mclk: %f\n",
312 pll
->reference_freq
, pll
->min_pll_freq
, pll
->max_pll_freq
, pll
->xclk
, sd
->Card
.sclk
, sd
->Card
.mclk
));
315 pll_info_block
= RADEON_BIOS16 (sd
->Card
.ROMHeaderStart
+ 0x30);
317 pll
->reference_freq
= RADEON_BIOS16 (pll_info_block
+ 0x0e);
318 pll
->reference_div
= RADEON_BIOS16 (pll_info_block
+ 0x10);
319 pll
->min_pll_freq
= RADEON_BIOS32 (pll_info_block
+ 0x12);
320 pll
->max_pll_freq
= RADEON_BIOS32 (pll_info_block
+ 0x16);
321 pll
->xclk
= RADEON_BIOS16 (pll_info_block
+ 0x08);
323 sd
->Card
.sclk
= RADEON_BIOS16(pll_info_block
+ 8) / 100.0;
324 sd
->Card
.mclk
= RADEON_BIOS16(pll_info_block
+ 10) / 100.0;