Added a test for MUIA_Listview_SelectChange.
[AROS.git] / arch / ppc-sam440 / hidd.radeon / radeon_bios.c
blob2c246bf668101c897d82adba4301d81c3e580074
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 "ati.h"
24 #include "radeon.h"
25 #include "radeon_reg.h"
26 #include "radeon_macros.h"
27 #include "radeon_bios.h"
28 #include "radeon_bios_rom.h"
30 #define DEBUG 1
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)
45 #ifndef MAX
46 #define MAX(a,b) ((a)>(b)?(a):(b))
47 #endif
48 #ifndef MIN
49 #define MIN(a,b) ((a)>(b)?(b):(a))
50 #endif
53 /* Read the Video BIOS block and the FP registers (if applicable). */
54 BOOL RADEONGetBIOSInfo(struct ati_staticdata *sd)
56 int tmp;
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;
63 return FALSE;
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;
71 return FALSE;
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;
84 else
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"));
92 return TRUE;
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))) {
103 int crtc = 0, id[2];
104 tmp1 = RADEON_BIOS16 (tmp + 4);
105 for (i=0; i<8; i++) {
106 if(tmp1 & (1<<i)) {
107 UWORD portinfo = RADEON_BIOS16(tmp+6+i*2);
108 if (crtc < 2) {
109 if ((i==2) || (i==6)) continue; /* ignore TV here */
111 if (crtc == 1) {
112 /* sharing same port with id[0] */
113 if (((portinfo>>8) & 0xf) == id[0]) {
114 if (i == 3)
115 sd->Card.PortInfo[0].TMDSType = TMDS_INT;
116 else if (i == 7)
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;
121 continue;
124 id[crtc] = (portinfo>>8) & 0xf;
125 sd->Card.PortInfo[crtc].DACType = (portinfo & 0xf) - 1;
126 sd->Card.PortInfo[crtc].ConnectorType = (portinfo>>4) & 0xf;
127 if (i == 3)
128 sd->Card.PortInfo[crtc].TMDSType = TMDS_INT;
129 else if (i == 7)
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;
137 break;
138 case RADEON_GPIO_DVI_DDC:
139 sd->Card.PortInfo[crtc].DDCType = DDC_DVI;
140 break;
141 case RADEON_GPIO_VGA_DDC:
142 sd->Card.PortInfo[crtc].DDCType = DDC_VGA;
143 break;
144 case RADEON_GPIO_CRT2_DDC:
145 sd->Card.PortInfo[crtc].DDCType = DDC_CRT2;
146 break;
147 default:
148 sd->Card.PortInfo[crtc].DDCType = DDC_NONE;
149 break;
152 } else {
153 sd->Card.PortInfo[crtc].DDCType = DDC_NONE;
155 crtc++;
156 } else {
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]) {
162 if (i == 3)
163 sd->Card.PortInfo[j].TMDSType = TMDS_INT;
164 else if (i == 7)
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));
180 } else {
181 D(bug("[ATI] No Device Info Table found!\n"));
182 return FALSE;
184 } else {
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);
226 } else {
227 D(bug("[ATI] No Connector Info Table found!\n"));
228 return FALSE;
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;
265 connector_found = 1;
268 if (connector_found == 0) {
269 D(bug("[ATI] No connector found in Connector Info Table.\n"));
270 } else {
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));
281 return TRUE;
284 /* Read PLL parameters from BIOS block. Default to typical values if there
285 is no BIOS. */
286 BOOL RADEONGetClockInfoFromBIOS(struct ati_staticdata *sd)
288 RADEONPLLRec *pll = &sd->Card.pll;
289 UWORD pll_info_block;
291 if (!sd->Card.VBIOS) {
292 return FALSE;
293 } else {
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));
314 } else {
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;
328 return TRUE;