radeon_bios.c revision c503f109
1209ff23fSmrg/* 2209ff23fSmrg * Copyright 2004 ATI Technologies Inc., Markham, Ontario 3209ff23fSmrg * 4209ff23fSmrg * All Rights Reserved. 5209ff23fSmrg * 6209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining 7209ff23fSmrg * a copy of this software and associated documentation files (the 8209ff23fSmrg * "Software"), to deal in the Software without restriction, including 9209ff23fSmrg * without limitation on the rights to use, copy, modify, merge, 10209ff23fSmrg * publish, distribute, sublicense, and/or sell copies of the Software, 11209ff23fSmrg * and to permit persons to whom the Software is furnished to do so, 12209ff23fSmrg * subject to the following conditions: 13209ff23fSmrg * 14209ff23fSmrg * The above copyright notice and this permission notice (including the 15209ff23fSmrg * next paragraph) shall be included in all copies or substantial 16209ff23fSmrg * portions of the Software. 17209ff23fSmrg * 18209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19209ff23fSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20209ff23fSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21209ff23fSmrg * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR 22209ff23fSmrg * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23209ff23fSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24209ff23fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25209ff23fSmrg * DEALINGS IN THE SOFTWARE. 26209ff23fSmrg */ 27209ff23fSmrg 28209ff23fSmrg#ifdef HAVE_CONFIG_H 29209ff23fSmrg#include "config.h" 30209ff23fSmrg#endif 31209ff23fSmrg 32209ff23fSmrg#include <string.h> 33209ff23fSmrg 34209ff23fSmrg#include "xf86.h" 35209ff23fSmrg#include "xf86_OSproc.h" 36209ff23fSmrg 37209ff23fSmrg#include "xf86PciInfo.h" 38209ff23fSmrg#include "radeon.h" 39209ff23fSmrg#include "radeon_reg.h" 40209ff23fSmrg#include "radeon_macros.h" 41209ff23fSmrg#include "radeon_probe.h" 42209ff23fSmrg#include "radeon_atombios.h" 43209ff23fSmrg#include "vbe.h" 44209ff23fSmrg 45209ff23fSmrgtypedef enum 46209ff23fSmrg{ 47209ff23fSmrg DDC_NONE_DETECTED, 48209ff23fSmrg DDC_MONID, 49209ff23fSmrg DDC_DVI, 50209ff23fSmrg DDC_VGA, 51209ff23fSmrg DDC_CRT2, 52209ff23fSmrg DDC_LCD, 53209ff23fSmrg DDC_GPIO, 54209ff23fSmrg} RADEONLegacyDDCType; 55209ff23fSmrg 56209ff23fSmrgtypedef enum 57209ff23fSmrg{ 58209ff23fSmrg CONNECTOR_NONE_LEGACY, 59209ff23fSmrg CONNECTOR_PROPRIETARY_LEGACY, 60209ff23fSmrg CONNECTOR_CRT_LEGACY, 61209ff23fSmrg CONNECTOR_DVI_I_LEGACY, 62209ff23fSmrg CONNECTOR_DVI_D_LEGACY, 63209ff23fSmrg CONNECTOR_CTV_LEGACY, 64209ff23fSmrg CONNECTOR_STV_LEGACY, 65209ff23fSmrg CONNECTOR_UNSUPPORTED_LEGACY 66209ff23fSmrg} RADEONLegacyConnectorType; 67209ff23fSmrg 68209ff23fSmrgstatic Bool 69209ff23fSmrgradeon_read_bios(ScrnInfoPtr pScrn) 70209ff23fSmrg{ 71209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 72209ff23fSmrg 73209ff23fSmrg#ifdef XSERVER_LIBPCIACCESS 74209ff23fSmrg if (pci_device_read_rom(info->PciInfo, info->VBIOS)) { 75209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 76209ff23fSmrg "Failed to read PCI ROM!\n"); 77209ff23fSmrg return FALSE; 78209ff23fSmrg } 79209ff23fSmrg#else 80209ff23fSmrg xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, RADEON_VBIOS_SIZE); 81209ff23fSmrg if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { 82209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 83209ff23fSmrg "Video BIOS not detected in PCI space!\n"); 84209ff23fSmrg if (xf86IsEntityPrimary(info->pEnt->index)) { 85209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 86209ff23fSmrg "Attempting to read Video BIOS from " 87209ff23fSmrg "legacy ISA space!\n"); 88209ff23fSmrg info->BIOSAddr = 0x000c0000; 89209ff23fSmrg xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, 90209ff23fSmrg RADEON_VBIOS_SIZE, info->VBIOS); 91209ff23fSmrg } 92209ff23fSmrg } 93209ff23fSmrg#endif 94209ff23fSmrg if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) 95209ff23fSmrg return FALSE; 96209ff23fSmrg else 97209ff23fSmrg return TRUE; 98209ff23fSmrg} 99209ff23fSmrg 100209ff23fSmrgstatic Bool 101b7e1c893Smrgradeon_read_disabled_bios(ScrnInfoPtr pScrn) 102209ff23fSmrg{ 103209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 104209ff23fSmrg RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); 105209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 106209ff23fSmrg Bool ret; 107209ff23fSmrg 108209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Attempting to read un-POSTed bios\n"); 109209ff23fSmrg 110209ff23fSmrg if (info->ChipFamily >= CHIP_FAMILY_R600) { 111209ff23fSmrg uint32_t viph_control = INREG(RADEON_VIPH_CONTROL); 112209ff23fSmrg uint32_t bus_cntl = INREG(RADEON_BUS_CNTL); 113209ff23fSmrg uint32_t d1vga_control = INREG(AVIVO_D1VGA_CONTROL); 114209ff23fSmrg uint32_t d2vga_control = INREG(AVIVO_D2VGA_CONTROL); 115209ff23fSmrg uint32_t vga_render_control = INREG(AVIVO_VGA_RENDER_CONTROL); 116209ff23fSmrg uint32_t rom_cntl = INREG(R600_ROM_CNTL); 117209ff23fSmrg uint32_t general_pwrmgt = INREG(R600_GENERAL_PWRMGT); 118209ff23fSmrg uint32_t low_vid_lower_gpio_cntl = INREG(R600_LOW_VID_LOWER_GPIO_CNTL); 119209ff23fSmrg uint32_t medium_vid_lower_gpio_cntl = INREG(R600_MEDIUM_VID_LOWER_GPIO_CNTL); 120209ff23fSmrg uint32_t high_vid_lower_gpio_cntl = INREG(R600_HIGH_VID_LOWER_GPIO_CNTL); 121209ff23fSmrg uint32_t ctxsw_vid_lower_gpio_cntl = INREG(R600_CTXSW_VID_LOWER_GPIO_CNTL); 122209ff23fSmrg uint32_t lower_gpio_enable = INREG(R600_LOWER_GPIO_ENABLE); 123209ff23fSmrg 124209ff23fSmrg /* disable VIP */ 125209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 126209ff23fSmrg 127209ff23fSmrg /* enable the rom */ 128209ff23fSmrg OUTREG(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); 129209ff23fSmrg 130209ff23fSmrg /* Disable VGA mode */ 131209ff23fSmrg OUTREG(AVIVO_D1VGA_CONTROL, (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 132209ff23fSmrg AVIVO_DVGA_CONTROL_TIMING_SELECT))); 133209ff23fSmrg OUTREG(AVIVO_D2VGA_CONTROL, (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 134209ff23fSmrg AVIVO_DVGA_CONTROL_TIMING_SELECT))); 135209ff23fSmrg OUTREG(AVIVO_VGA_RENDER_CONTROL, (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 136209ff23fSmrg 137209ff23fSmrg OUTREG(R600_ROM_CNTL, ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) | 138209ff23fSmrg (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | 139209ff23fSmrg R600_SCK_OVERWRITE)); 140209ff23fSmrg 141209ff23fSmrg OUTREG(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS)); 142209ff23fSmrg 143209ff23fSmrg OUTREG(R600_LOW_VID_LOWER_GPIO_CNTL, (low_vid_lower_gpio_cntl & ~0x400)); 144209ff23fSmrg 145209ff23fSmrg OUTREG(R600_MEDIUM_VID_LOWER_GPIO_CNTL, (medium_vid_lower_gpio_cntl & ~0x400)); 146209ff23fSmrg 147209ff23fSmrg OUTREG(R600_HIGH_VID_LOWER_GPIO_CNTL, (high_vid_lower_gpio_cntl & ~0x400)); 148209ff23fSmrg 149209ff23fSmrg OUTREG(R600_CTXSW_VID_LOWER_GPIO_CNTL, (ctxsw_vid_lower_gpio_cntl & ~0x400)); 150209ff23fSmrg 151209ff23fSmrg OUTREG(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400)); 152209ff23fSmrg 153209ff23fSmrg ret = radeon_read_bios(pScrn); 154209ff23fSmrg 155209ff23fSmrg /* restore regs */ 156209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, viph_control); 157209ff23fSmrg OUTREG(RADEON_BUS_CNTL, bus_cntl); 158209ff23fSmrg OUTREG(AVIVO_D1VGA_CONTROL, d1vga_control); 159209ff23fSmrg OUTREG(AVIVO_D2VGA_CONTROL, d2vga_control); 160209ff23fSmrg OUTREG(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 161209ff23fSmrg OUTREG(R600_ROM_CNTL, rom_cntl); 162209ff23fSmrg OUTREG(R600_GENERAL_PWRMGT, general_pwrmgt); 163209ff23fSmrg OUTREG(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl); 164209ff23fSmrg OUTREG(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl); 165209ff23fSmrg OUTREG(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl); 166209ff23fSmrg OUTREG(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl); 167209ff23fSmrg OUTREG(R600_LOWER_GPIO_ENABLE, lower_gpio_enable); 168209ff23fSmrg 169209ff23fSmrg } else if (info->ChipFamily >= CHIP_FAMILY_RV515) { 170209ff23fSmrg uint32_t seprom_cntl1 = INREG(RADEON_SEPROM_CNTL1); 171209ff23fSmrg uint32_t viph_control = INREG(RADEON_VIPH_CONTROL); 172209ff23fSmrg uint32_t bus_cntl = INREG(RADEON_BUS_CNTL); 173209ff23fSmrg uint32_t d1vga_control = INREG(AVIVO_D1VGA_CONTROL); 174209ff23fSmrg uint32_t d2vga_control = INREG(AVIVO_D2VGA_CONTROL); 175209ff23fSmrg uint32_t vga_render_control = INREG(AVIVO_VGA_RENDER_CONTROL); 176209ff23fSmrg uint32_t gpiopad_a = INREG(RADEON_GPIOPAD_A); 177209ff23fSmrg uint32_t gpiopad_en = INREG(RADEON_GPIOPAD_EN); 178209ff23fSmrg uint32_t gpiopad_mask = INREG(RADEON_GPIOPAD_MASK); 179209ff23fSmrg 180209ff23fSmrg OUTREG(RADEON_SEPROM_CNTL1, ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | 181209ff23fSmrg (0xc << RADEON_SCK_PRESCALE_SHIFT))); 182209ff23fSmrg 183209ff23fSmrg OUTREG(RADEON_GPIOPAD_A, 0); 184209ff23fSmrg OUTREG(RADEON_GPIOPAD_EN, 0); 185209ff23fSmrg OUTREG(RADEON_GPIOPAD_MASK, 0); 186209ff23fSmrg 187209ff23fSmrg /* disable VIP */ 188209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 189209ff23fSmrg 190209ff23fSmrg /* enable the rom */ 191209ff23fSmrg OUTREG(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); 192209ff23fSmrg 193209ff23fSmrg /* Disable VGA mode */ 194209ff23fSmrg OUTREG(AVIVO_D1VGA_CONTROL, (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 195209ff23fSmrg AVIVO_DVGA_CONTROL_TIMING_SELECT))); 196209ff23fSmrg OUTREG(AVIVO_D2VGA_CONTROL, (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 197209ff23fSmrg AVIVO_DVGA_CONTROL_TIMING_SELECT))); 198209ff23fSmrg OUTREG(AVIVO_VGA_RENDER_CONTROL, (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 199209ff23fSmrg 200209ff23fSmrg ret = radeon_read_bios(pScrn); 201209ff23fSmrg 202209ff23fSmrg /* restore regs */ 203209ff23fSmrg OUTREG(RADEON_SEPROM_CNTL1, seprom_cntl1); 204209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, viph_control); 205209ff23fSmrg OUTREG(RADEON_BUS_CNTL, bus_cntl); 206209ff23fSmrg OUTREG(AVIVO_D1VGA_CONTROL, d1vga_control); 207209ff23fSmrg OUTREG(AVIVO_D2VGA_CONTROL, d2vga_control); 208209ff23fSmrg OUTREG(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 209209ff23fSmrg OUTREG(RADEON_GPIOPAD_A, gpiopad_a); 210209ff23fSmrg OUTREG(RADEON_GPIOPAD_EN, gpiopad_en); 211209ff23fSmrg OUTREG(RADEON_GPIOPAD_MASK, gpiopad_mask); 212209ff23fSmrg 213209ff23fSmrg } else { 214209ff23fSmrg uint32_t seprom_cntl1 = INREG(RADEON_SEPROM_CNTL1); 215209ff23fSmrg uint32_t viph_control = INREG(RADEON_VIPH_CONTROL); 216209ff23fSmrg uint32_t bus_cntl = INREG(RADEON_BUS_CNTL); 217209ff23fSmrg uint32_t crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); 218209ff23fSmrg uint32_t crtc2_gen_cntl = 0; 219209ff23fSmrg uint32_t crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); 220209ff23fSmrg uint32_t fp2_gen_cntl = 0; 221209ff23fSmrg 222209ff23fSmrg if (PCI_DEV_DEVICE_ID(info->PciInfo) == PCI_CHIP_RV100_QY) 223209ff23fSmrg fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); 224209ff23fSmrg 225209ff23fSmrg if (pRADEONEnt->HasCRTC2) 226209ff23fSmrg crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); 227209ff23fSmrg 228209ff23fSmrg OUTREG(RADEON_SEPROM_CNTL1, ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | 229209ff23fSmrg (0xc << RADEON_SCK_PRESCALE_SHIFT))); 230209ff23fSmrg 231209ff23fSmrg /* disable VIP */ 232209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 233209ff23fSmrg 234209ff23fSmrg /* enable the rom */ 235209ff23fSmrg OUTREG(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); 236209ff23fSmrg 237209ff23fSmrg /* Turn off mem requests and CRTC for both controllers */ 238209ff23fSmrg OUTREG(RADEON_CRTC_GEN_CNTL, ((crtc_gen_cntl & ~RADEON_CRTC_EN) | 239209ff23fSmrg (RADEON_CRTC_DISP_REQ_EN_B | 240209ff23fSmrg RADEON_CRTC_EXT_DISP_EN))); 241209ff23fSmrg if (pRADEONEnt->HasCRTC2) 242209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) | 243209ff23fSmrg RADEON_CRTC2_DISP_REQ_EN_B)); 244209ff23fSmrg 245209ff23fSmrg /* Turn off CRTC */ 246209ff23fSmrg OUTREG(RADEON_CRTC_EXT_CNTL, ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) | 247209ff23fSmrg (RADEON_CRTC_SYNC_TRISTAT | 248209ff23fSmrg RADEON_CRTC_DISPLAY_DIS))); 249209ff23fSmrg 250209ff23fSmrg if (PCI_DEV_DEVICE_ID(info->PciInfo) == PCI_CHIP_RV100_QY) 251209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON)); 252209ff23fSmrg 253209ff23fSmrg ret = radeon_read_bios(pScrn); 254209ff23fSmrg 255209ff23fSmrg /* restore regs */ 256209ff23fSmrg OUTREG(RADEON_SEPROM_CNTL1, seprom_cntl1); 257209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, viph_control); 258209ff23fSmrg OUTREG(RADEON_BUS_CNTL, bus_cntl); 259209ff23fSmrg OUTREG(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); 260209ff23fSmrg if (pRADEONEnt->HasCRTC2) 261209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 262209ff23fSmrg OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); 263209ff23fSmrg if (PCI_DEV_DEVICE_ID(info->PciInfo) == PCI_CHIP_RV100_QY) 264209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 265209ff23fSmrg } 266209ff23fSmrg return ret; 267209ff23fSmrg} 268209ff23fSmrg 269b7e1c893SmrgBool 270b7e1c893Smrgradeon_card_posted(ScrnInfoPtr pScrn) 271b7e1c893Smrg{ 272b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 273b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 274b7e1c893Smrg uint32_t reg; 275b7e1c893Smrg 276c503f109Smrg /* first check CRTCs */ 277b7e1c893Smrg if (IS_AVIVO_VARIANT) { 278b7e1c893Smrg reg = INREG(AVIVO_D1CRTC_CONTROL) | INREG(AVIVO_D2CRTC_CONTROL); 279b7e1c893Smrg if (reg & AVIVO_CRTC_EN) 280b7e1c893Smrg return TRUE; 281b7e1c893Smrg } else { 282b7e1c893Smrg reg = INREG(RADEON_CRTC_GEN_CNTL) | INREG(RADEON_CRTC2_GEN_CNTL); 283b7e1c893Smrg if (reg & RADEON_CRTC_EN) 284b7e1c893Smrg return TRUE; 285b7e1c893Smrg } 286b7e1c893Smrg 287c503f109Smrg /* then check MEM_SIZE, in case something turned the crtcs off */ 288c503f109Smrg if (info->ChipFamily >= CHIP_FAMILY_R600) 289c503f109Smrg reg = INREG(R600_CONFIG_MEMSIZE); 290c503f109Smrg else 291c503f109Smrg reg = INREG(RADEON_CONFIG_MEMSIZE); 292c503f109Smrg 293c503f109Smrg if (reg) 294c503f109Smrg return TRUE; 295c503f109Smrg 296b7e1c893Smrg return FALSE; 297b7e1c893Smrg} 298b7e1c893Smrg 299209ff23fSmrg/* Read the Video BIOS block and the FP registers (if applicable). */ 300209ff23fSmrgBool 301209ff23fSmrgRADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) 302209ff23fSmrg{ 303209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 304209ff23fSmrg int tmp; 305209ff23fSmrg unsigned short dptr; 306209ff23fSmrg 307209ff23fSmrg#ifdef XSERVER_LIBPCIACCESS 308209ff23fSmrg int size = info->PciInfo->rom_size > RADEON_VBIOS_SIZE ? info->PciInfo->rom_size : RADEON_VBIOS_SIZE; 309209ff23fSmrg info->VBIOS = xalloc(size); 310209ff23fSmrg#else 311209ff23fSmrg info->VBIOS = xalloc(RADEON_VBIOS_SIZE); 312209ff23fSmrg#endif 313209ff23fSmrg if (!info->VBIOS) { 314209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 315209ff23fSmrg "Cannot allocate space for hold Video BIOS!\n"); 316209ff23fSmrg return FALSE; 317209ff23fSmrg } else { 318209ff23fSmrg if (pInt10) { 319209ff23fSmrg info->BIOSAddr = pInt10->BIOSseg << 4; 320209ff23fSmrg (void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr), 321209ff23fSmrg RADEON_VBIOS_SIZE); 322b7e1c893Smrg } else if (!radeon_read_bios(pScrn)) 323b7e1c893Smrg (void)radeon_read_disabled_bios(pScrn); 324209ff23fSmrg } 325209ff23fSmrg 326209ff23fSmrg if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { 327209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 328209ff23fSmrg "Unrecognized BIOS signature, BIOS data will not be used\n"); 329209ff23fSmrg xfree (info->VBIOS); 330209ff23fSmrg info->VBIOS = NULL; 331209ff23fSmrg return FALSE; 332209ff23fSmrg } 333209ff23fSmrg 334209ff23fSmrg /* Verify it's an x86 BIOS not OF firmware, copied from radeonfb */ 335209ff23fSmrg dptr = RADEON_BIOS16(0x18); 336209ff23fSmrg /* If PCI data signature is wrong assume x86 video BIOS anyway */ 337209ff23fSmrg if (RADEON_BIOS32(dptr) != (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) { 338209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 339209ff23fSmrg "ROM PCI data signature incorrect, ignoring\n"); 340209ff23fSmrg } 341209ff23fSmrg else if (info->VBIOS[dptr + 0x14] != 0x0) { 342209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 343209ff23fSmrg "Not an x86 BIOS ROM image, BIOS data will not be used\n"); 344209ff23fSmrg xfree (info->VBIOS); 345209ff23fSmrg info->VBIOS = NULL; 346209ff23fSmrg return FALSE; 347209ff23fSmrg } 348209ff23fSmrg 349209ff23fSmrg if (info->VBIOS) info->ROMHeaderStart = RADEON_BIOS16(0x48); 350209ff23fSmrg 351209ff23fSmrg if(!info->ROMHeaderStart) { 352209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 353209ff23fSmrg "Invalid ROM pointer, BIOS data will not be used\n"); 354209ff23fSmrg xfree (info->VBIOS); 355209ff23fSmrg info->VBIOS = NULL; 356209ff23fSmrg return FALSE; 357209ff23fSmrg } 358b7e1c893Smrg 359209ff23fSmrg tmp = info->ROMHeaderStart + 4; 360209ff23fSmrg if ((RADEON_BIOS8(tmp) == 'A' && 361209ff23fSmrg RADEON_BIOS8(tmp+1) == 'T' && 362209ff23fSmrg RADEON_BIOS8(tmp+2) == 'O' && 363209ff23fSmrg RADEON_BIOS8(tmp+3) == 'M') || 364209ff23fSmrg (RADEON_BIOS8(tmp) == 'M' && 365209ff23fSmrg RADEON_BIOS8(tmp+1) == 'O' && 366209ff23fSmrg RADEON_BIOS8(tmp+2) == 'T' && 367209ff23fSmrg RADEON_BIOS8(tmp+3) == 'A')) 368209ff23fSmrg info->IsAtomBios = TRUE; 369209ff23fSmrg else 370209ff23fSmrg info->IsAtomBios = FALSE; 371209ff23fSmrg 372209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s BIOS detected\n", 373209ff23fSmrg info->IsAtomBios ? "ATOM":"Legacy"); 374209ff23fSmrg 375209ff23fSmrg if (info->IsAtomBios) { 376b7e1c893Smrg AtomBiosArgRec atomBiosArg; 377209ff23fSmrg 378b7e1c893Smrg if (RHDAtomBiosFunc(pScrn->scrnIndex, NULL, ATOMBIOS_INIT, &atomBiosArg) 379b7e1c893Smrg == ATOM_SUCCESS) { 380b7e1c893Smrg info->atomBIOS = atomBiosArg.atomhandle; 381b7e1c893Smrg } 382209ff23fSmrg 383b7e1c893Smrg atomBiosArg.fb.start = info->FbFreeStart; 384b7e1c893Smrg atomBiosArg.fb.size = info->FbFreeSize; 385b7e1c893Smrg if (RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, ATOMBIOS_ALLOCATE_FB_SCRATCH, 386209ff23fSmrg &atomBiosArg) == ATOM_SUCCESS) { 387209ff23fSmrg 388209ff23fSmrg info->FbFreeStart = atomBiosArg.fb.start; 389209ff23fSmrg info->FbFreeSize = atomBiosArg.fb.size; 390b7e1c893Smrg } 391b7e1c893Smrg 392b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, GET_DEFAULT_ENGINE_CLOCK, 393b7e1c893Smrg &atomBiosArg); 394b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, GET_DEFAULT_MEMORY_CLOCK, 395b7e1c893Smrg &atomBiosArg); 396b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 397b7e1c893Smrg GET_MAX_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg); 398b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 399b7e1c893Smrg GET_MIN_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg); 400b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 401b7e1c893Smrg GET_MAX_PIXEL_CLOCK_PLL_INPUT, &atomBiosArg); 402b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 403209ff23fSmrg GET_MIN_PIXEL_CLOCK_PLL_INPUT, &atomBiosArg); 404b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 405209ff23fSmrg GET_MAX_PIXEL_CLK, &atomBiosArg); 406b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 407b7e1c893Smrg GET_REF_CLOCK, &atomBiosArg); 408209ff23fSmrg 409209ff23fSmrg info->MasterDataStart = RADEON_BIOS16 (info->ROMHeaderStart + 32); 410209ff23fSmrg } 411b7e1c893Smrg 412b7e1c893Smrg /* We are a bit too quick at using this "unposted" to re-post the 413b7e1c893Smrg * card. This causes some problems with VT switch on some machines, 414b7e1c893Smrg * so let's work around this for now by only POSTing if none of the 415b7e1c893Smrg * CRTCs are enabled 416b7e1c893Smrg */ 417b7e1c893Smrg if ((!radeon_card_posted(pScrn)) && info->VBIOS) { 418b7e1c893Smrg if (info->IsAtomBios) { 419b7e1c893Smrg if (!rhdAtomASICInit(info->atomBIOS)) 420b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 421b7e1c893Smrg "%s: AsicInit failed.\n",__func__); 422b7e1c893Smrg } else { 423209ff23fSmrg#if 0 424b7e1c893Smrg /* FIX ME */ 425b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Attempting to POST via legacy BIOS tables\n"); 426209ff23fSmrg RADEONGetBIOSInitTableOffsets(pScrn); 427209ff23fSmrg RADEONPostCardFromBIOSTables(pScrn); 428b7e1c893Smrg#endif 429209ff23fSmrg } 430209ff23fSmrg } 431b7e1c893Smrg 432209ff23fSmrg return TRUE; 433209ff23fSmrg} 434209ff23fSmrg 435209ff23fSmrgstatic Bool RADEONGetATOMConnectorInfoFromBIOS (ScrnInfoPtr pScrn) 436209ff23fSmrg{ 437209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 438209ff23fSmrg 439209ff23fSmrg if (!info->VBIOS) return FALSE; 440b7e1c893Smrg 441209ff23fSmrg if (RADEONGetATOMConnectorInfoFromBIOSObject(pScrn)) 442209ff23fSmrg return TRUE; 443209ff23fSmrg 444209ff23fSmrg if (RADEONGetATOMConnectorInfoFromBIOSConnectorTable(pScrn)) 445209ff23fSmrg return TRUE; 446209ff23fSmrg 447209ff23fSmrg return FALSE; 448209ff23fSmrg} 449209ff23fSmrg 450209ff23fSmrgstatic void RADEONApplyLegacyQuirks(ScrnInfoPtr pScrn, int index) 451209ff23fSmrg{ 452209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 453209ff23fSmrg 454b7e1c893Smrg /* XPRESS DDC quirks */ 455209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400 || 456209ff23fSmrg info->ChipFamily == CHIP_FAMILY_RS480) && 457209ff23fSmrg info->BiosConnector[index].ddc_i2c.mask_clk_reg == RADEON_GPIO_CRT2_DDC) { 458209ff23fSmrg info->BiosConnector[index].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); 459b7e1c893Smrg } else if ((info->ChipFamily == CHIP_FAMILY_RS400 || 460b7e1c893Smrg info->ChipFamily == CHIP_FAMILY_RS480) && 461b7e1c893Smrg info->BiosConnector[index].ddc_i2c.mask_clk_reg == RADEON_GPIO_MONID) { 462b7e1c893Smrg info->BiosConnector[index].ddc_i2c.valid = TRUE; 463b7e1c893Smrg info->BiosConnector[index].ddc_i2c.mask_clk_mask = (0x20 << 8); 464b7e1c893Smrg info->BiosConnector[index].ddc_i2c.mask_data_mask = 0x80; 465b7e1c893Smrg info->BiosConnector[index].ddc_i2c.a_clk_mask = (0x20 << 8); 466b7e1c893Smrg info->BiosConnector[index].ddc_i2c.a_data_mask = 0x80; 467b7e1c893Smrg info->BiosConnector[index].ddc_i2c.put_clk_mask = (0x20 << 8); 468b7e1c893Smrg info->BiosConnector[index].ddc_i2c.put_data_mask = 0x80; 469b7e1c893Smrg info->BiosConnector[index].ddc_i2c.get_clk_mask = (0x20 << 8); 470b7e1c893Smrg info->BiosConnector[index].ddc_i2c.get_data_mask = 0x80; 471b7e1c893Smrg info->BiosConnector[index].ddc_i2c.mask_clk_reg = RADEON_GPIOPAD_MASK; 472b7e1c893Smrg info->BiosConnector[index].ddc_i2c.mask_data_reg = RADEON_GPIOPAD_MASK; 473b7e1c893Smrg info->BiosConnector[index].ddc_i2c.a_clk_reg = RADEON_GPIOPAD_A; 474b7e1c893Smrg info->BiosConnector[index].ddc_i2c.a_data_reg = RADEON_GPIOPAD_A; 475b7e1c893Smrg info->BiosConnector[index].ddc_i2c.put_clk_reg = RADEON_GPIOPAD_EN; 476b7e1c893Smrg info->BiosConnector[index].ddc_i2c.put_data_reg = RADEON_GPIOPAD_EN; 477b7e1c893Smrg info->BiosConnector[index].ddc_i2c.get_clk_reg = RADEON_LCD_GPIO_Y_REG; 478b7e1c893Smrg info->BiosConnector[index].ddc_i2c.get_data_reg = RADEON_LCD_GPIO_Y_REG; 479209ff23fSmrg } 480209ff23fSmrg 481209ff23fSmrg /* Certain IBM chipset RN50s have a BIOS reporting two VGAs, 482209ff23fSmrg one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */ 483209ff23fSmrg if (info->Chipset == PCI_CHIP_RN50_515E && 484209ff23fSmrg PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1014) { 485209ff23fSmrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_VGA && 486209ff23fSmrg info->BiosConnector[index].ddc_i2c.mask_clk_reg == RADEON_GPIO_CRT2_DDC) { 487209ff23fSmrg info->BiosConnector[index].valid = FALSE; 488209ff23fSmrg } 489209ff23fSmrg } 490209ff23fSmrg 491209ff23fSmrg /* Some RV100 cards with 2 VGA ports show up with DVI+VGA */ 492209ff23fSmrg if (info->Chipset == PCI_CHIP_RV100_QY && 493209ff23fSmrg PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1002 && 494209ff23fSmrg PCI_SUB_DEVICE_ID(info->PciInfo) == 0x013a) { 495209ff23fSmrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_DVI_I) { 496209ff23fSmrg info->BiosConnector[index].ConnectorType = CONNECTOR_VGA; 497209ff23fSmrg } 498209ff23fSmrg } 499209ff23fSmrg 500b7e1c893Smrg /* X300 card with extra non-existent DVI port */ 501b7e1c893Smrg if (info->Chipset == PCI_CHIP_RV370_5B60 && 502b7e1c893Smrg PCI_SUB_VENDOR_ID(info->PciInfo) == 0x17af && 503b7e1c893Smrg PCI_SUB_DEVICE_ID(info->PciInfo) == 0x201e && 504b7e1c893Smrg index == 2) { 505b7e1c893Smrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_DVI_I) { 506b7e1c893Smrg info->BiosConnector[index].valid = FALSE; 507b7e1c893Smrg } 508b7e1c893Smrg } 509b7e1c893Smrg 510b7e1c893Smrg /* r200 card with primary dac routed to both VGA and DVI - disable load detection 511b7e1c893Smrg * otherwise you end up detecing load if either port is attached 512b7e1c893Smrg */ 513b7e1c893Smrg if (info->Chipset == PCI_CHIP_R200_QL && 514b7e1c893Smrg PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1569 && 515b7e1c893Smrg PCI_SUB_DEVICE_ID(info->PciInfo) == 0x514c && 516b7e1c893Smrg (info->BiosConnector[index].devices & ATOM_DEVICE_CRT1_SUPPORT)) { 517b7e1c893Smrg info->BiosConnector[index].load_detection = FALSE; 518b7e1c893Smrg } 519b7e1c893Smrg 520209ff23fSmrg} 521209ff23fSmrg 522209ff23fSmrgstatic Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) 523209ff23fSmrg{ 524209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 525209ff23fSmrg int offset, i, entry, tmp, tmp0, tmp1; 526209ff23fSmrg RADEONLegacyDDCType DDCType; 527209ff23fSmrg RADEONLegacyConnectorType ConnectorType; 528209ff23fSmrg 529209ff23fSmrg if (!info->VBIOS) return FALSE; 530209ff23fSmrg 531209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x50); 532209ff23fSmrg if (offset) { 533209ff23fSmrg for (i = 0; i < 4; i++) { 534209ff23fSmrg entry = offset + 2 + i*2; 535209ff23fSmrg 536209ff23fSmrg if (!RADEON_BIOS16(entry)) { 537209ff23fSmrg break; 538209ff23fSmrg } 539209ff23fSmrg info->BiosConnector[i].valid = TRUE; 540209ff23fSmrg tmp = RADEON_BIOS16(entry); 541209ff23fSmrg info->BiosConnector[i].ConnectorType = (tmp >> 12) & 0xf; 542209ff23fSmrg ConnectorType = (tmp >> 12) & 0xf; 543209ff23fSmrg switch (ConnectorType) { 544209ff23fSmrg case CONNECTOR_PROPRIETARY_LEGACY: 545b7e1c893Smrg info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_D; 546b7e1c893Smrg if ((tmp >> 4) & 0x1) { 547b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP2_SUPPORT; 548b7e1c893Smrg if (!radeon_add_encoder(pScrn, 549b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 550b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT, 551b7e1c893Smrg 0), 552b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT)) 553b7e1c893Smrg return FALSE; 554b7e1c893Smrg } else { 555b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP1_SUPPORT; 556b7e1c893Smrg if (!radeon_add_encoder(pScrn, 557b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 558b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT, 559b7e1c893Smrg 0), 560b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT)) 561b7e1c893Smrg return FALSE; 562b7e1c893Smrg } 563209ff23fSmrg break; 564209ff23fSmrg case CONNECTOR_CRT_LEGACY: 565209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_VGA; 566b7e1c893Smrg if (tmp & 0x1) { 567b7e1c893Smrg info->BiosConnector[i].load_detection = FALSE; 568b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_CRT2_SUPPORT; 569b7e1c893Smrg if (!radeon_add_encoder(pScrn, 570b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 571b7e1c893Smrg ATOM_DEVICE_CRT2_SUPPORT, 572b7e1c893Smrg 2), 573b7e1c893Smrg ATOM_DEVICE_CRT2_SUPPORT)) 574b7e1c893Smrg return FALSE; 575b7e1c893Smrg } else { 576b7e1c893Smrg info->BiosConnector[i].load_detection = TRUE; 577b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_CRT1_SUPPORT; 578b7e1c893Smrg if (!radeon_add_encoder(pScrn, 579b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 580b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT, 581b7e1c893Smrg 1), 582b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT)) 583b7e1c893Smrg return FALSE; 584b7e1c893Smrg } 585209ff23fSmrg break; 586209ff23fSmrg case CONNECTOR_DVI_I_LEGACY: 587209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_I; 588b7e1c893Smrg if (tmp & 0x1) { 589b7e1c893Smrg info->BiosConnector[i].load_detection = FALSE; 590b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_CRT2_SUPPORT; 591b7e1c893Smrg if (!radeon_add_encoder(pScrn, 592b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 593b7e1c893Smrg ATOM_DEVICE_CRT2_SUPPORT, 594b7e1c893Smrg 2), 595b7e1c893Smrg ATOM_DEVICE_CRT2_SUPPORT)) 596b7e1c893Smrg return FALSE; 597b7e1c893Smrg } else { 598b7e1c893Smrg info->BiosConnector[i].load_detection = TRUE; 599b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_CRT1_SUPPORT; 600b7e1c893Smrg if (!radeon_add_encoder(pScrn, 601b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 602b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT, 603b7e1c893Smrg 1), 604b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT)) 605b7e1c893Smrg return FALSE; 606b7e1c893Smrg } 607b7e1c893Smrg if ((tmp >> 4) & 0x1) { 608b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP2_SUPPORT; 609b7e1c893Smrg if (!radeon_add_encoder(pScrn, 610b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 611b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT, 612b7e1c893Smrg 0), 613b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT)) 614b7e1c893Smrg return FALSE; 615b7e1c893Smrg } else { 616b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP1_SUPPORT; 617b7e1c893Smrg if (!radeon_add_encoder(pScrn, 618b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 619b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT, 620b7e1c893Smrg 0), 621b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT)) 622b7e1c893Smrg return FALSE; 623b7e1c893Smrg } 624209ff23fSmrg break; 625209ff23fSmrg case CONNECTOR_DVI_D_LEGACY: 626209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_D; 627b7e1c893Smrg if ((tmp >> 4) & 0x1) { 628b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP2_SUPPORT; 629b7e1c893Smrg if (!radeon_add_encoder(pScrn, 630b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 631b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT, 632b7e1c893Smrg 0), 633b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT)) 634b7e1c893Smrg return FALSE; 635b7e1c893Smrg } else { 636b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP1_SUPPORT; 637b7e1c893Smrg if (!radeon_add_encoder(pScrn, 638b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 639b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT, 640b7e1c893Smrg 0), 641b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT)) 642b7e1c893Smrg return FALSE; 643b7e1c893Smrg } 644209ff23fSmrg break; 645209ff23fSmrg case CONNECTOR_CTV_LEGACY: 646209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_CTV; 647b7e1c893Smrg info->BiosConnector[i].load_detection = FALSE; 648b7e1c893Smrg info->BiosConnector[i].devices = ATOM_DEVICE_TV1_SUPPORT; 649b7e1c893Smrg if (!radeon_add_encoder(pScrn, 650b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 651b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT, 652b7e1c893Smrg 2), 653b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT)) 654b7e1c893Smrg return FALSE; 655209ff23fSmrg break; 656209ff23fSmrg case CONNECTOR_STV_LEGACY: 657209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_STV; 658b7e1c893Smrg info->BiosConnector[i].load_detection = FALSE; 659b7e1c893Smrg info->BiosConnector[i].devices = ATOM_DEVICE_TV1_SUPPORT; 660b7e1c893Smrg if (!radeon_add_encoder(pScrn, 661b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 662b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT, 663b7e1c893Smrg 2), 664b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT)) 665b7e1c893Smrg return FALSE; 666209ff23fSmrg break; 667209ff23fSmrg default: 668209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown Connector Type: %d\n", ConnectorType); 669209ff23fSmrg info->BiosConnector[i].valid = FALSE; 670209ff23fSmrg break; 671209ff23fSmrg } 672209ff23fSmrg 673209ff23fSmrg info->BiosConnector[i].ddc_i2c.valid = FALSE; 674209ff23fSmrg 675209ff23fSmrg DDCType = (tmp >> 8) & 0xf; 676209ff23fSmrg switch (DDCType) { 677209ff23fSmrg case DDC_MONID: 678209ff23fSmrg info->BiosConnector[i].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); 679209ff23fSmrg break; 680209ff23fSmrg case DDC_DVI: 681209ff23fSmrg info->BiosConnector[i].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC); 682209ff23fSmrg break; 683209ff23fSmrg case DDC_VGA: 684209ff23fSmrg info->BiosConnector[i].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC); 685209ff23fSmrg break; 686209ff23fSmrg case DDC_CRT2: 687209ff23fSmrg info->BiosConnector[i].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); 688209ff23fSmrg break; 689209ff23fSmrg default: 690209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown DDC Type: %d\n", DDCType); 691209ff23fSmrg break; 692209ff23fSmrg } 693209ff23fSmrg 694209ff23fSmrg RADEONApplyLegacyQuirks(pScrn, i); 695209ff23fSmrg 696209ff23fSmrg } 697209ff23fSmrg } else { 698209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n"); 699209ff23fSmrg 700209ff23fSmrg /* old radeons and r128 didn't use connector tables you just check 701209ff23fSmrg * for LVDS, DVI, TV, etc. tables 702209ff23fSmrg */ 703209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x34); 704209ff23fSmrg if (offset) { 705209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 706209ff23fSmrg "Found DFP table, assuming DVI connector\n"); 707209ff23fSmrg info->BiosConnector[0].valid = TRUE; 708209ff23fSmrg info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I; 709b7e1c893Smrg info->BiosConnector[0].load_detection = TRUE; 710209ff23fSmrg info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC); 711b7e1c893Smrg info->BiosConnector[0].devices = ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT; 712b7e1c893Smrg if (!radeon_add_encoder(pScrn, 713b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 714b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT, 715b7e1c893Smrg 0), 716b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT)) 717b7e1c893Smrg return FALSE; 718b7e1c893Smrg if (!radeon_add_encoder(pScrn, 719b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 720b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT, 721b7e1c893Smrg 1), 722b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT)) 723b7e1c893Smrg return FALSE; 724209ff23fSmrg } else 725209ff23fSmrg return FALSE; 726209ff23fSmrg } 727209ff23fSmrg 728209ff23fSmrg /* check LVDS table */ 729b7e1c893Smrg /* IGP can be mobile or desktop so check the connectors */ 730b7e1c893Smrg if (info->IsMobility || info->IsIGP) { 731209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x40); 732209ff23fSmrg if (offset) { 733209ff23fSmrg info->BiosConnector[4].valid = TRUE; 734209ff23fSmrg info->BiosConnector[4].ConnectorType = CONNECTOR_LVDS; 735209ff23fSmrg info->BiosConnector[4].ddc_i2c.valid = FALSE; 736209ff23fSmrg 737b7e1c893Smrg info->BiosConnector[4].devices = ATOM_DEVICE_LCD1_SUPPORT; 738b7e1c893Smrg if (!radeon_add_encoder(pScrn, 739b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 740b7e1c893Smrg ATOM_DEVICE_LCD1_SUPPORT, 741b7e1c893Smrg 0), 742b7e1c893Smrg ATOM_DEVICE_LCD1_SUPPORT)) 743b7e1c893Smrg return FALSE; 744b7e1c893Smrg 745209ff23fSmrg tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42); 746209ff23fSmrg if (tmp) { 747209ff23fSmrg tmp0 = RADEON_BIOS16(tmp + 0x15); 748209ff23fSmrg if (tmp0) { 749209ff23fSmrg tmp1 = RADEON_BIOS8(tmp0+2) & 0x07; 750209ff23fSmrg if (tmp1) { 751209ff23fSmrg DDCType = tmp1; 752209ff23fSmrg switch (DDCType) { 753b7e1c893Smrg case DDC_NONE_DETECTED: 754b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DDC for LCD\n"); 755b7e1c893Smrg break; 756209ff23fSmrg case DDC_MONID: 757209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); 758209ff23fSmrg break; 759209ff23fSmrg case DDC_DVI: 760209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC); 761209ff23fSmrg break; 762209ff23fSmrg case DDC_VGA: 763209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC); 764209ff23fSmrg break; 765209ff23fSmrg case DDC_CRT2: 766209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); 767209ff23fSmrg break; 768209ff23fSmrg case DDC_LCD: 769209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_LCD_GPIO_MASK); 770b7e1c893Smrg info->BiosConnector[4].ddc_i2c.mask_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 771b7e1c893Smrg info->BiosConnector[4].ddc_i2c.mask_data_mask = RADEON_BIOS32(tmp0 + 0x07); 772b7e1c893Smrg info->BiosConnector[4].ddc_i2c.a_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 773b7e1c893Smrg info->BiosConnector[4].ddc_i2c.a_data_mask = RADEON_BIOS32(tmp0 + 0x07); 774209ff23fSmrg info->BiosConnector[4].ddc_i2c.put_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 775209ff23fSmrg info->BiosConnector[4].ddc_i2c.put_data_mask = RADEON_BIOS32(tmp0 + 0x07); 776209ff23fSmrg info->BiosConnector[4].ddc_i2c.get_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 777209ff23fSmrg info->BiosConnector[4].ddc_i2c.get_data_mask = RADEON_BIOS32(tmp0 + 0x07); 778209ff23fSmrg break; 779209ff23fSmrg case DDC_GPIO: 780209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_MDGPIO_EN_REG); 781b7e1c893Smrg info->BiosConnector[4].ddc_i2c.mask_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 782b7e1c893Smrg info->BiosConnector[4].ddc_i2c.mask_data_mask = RADEON_BIOS32(tmp0 + 0x07); 783b7e1c893Smrg info->BiosConnector[4].ddc_i2c.a_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 784b7e1c893Smrg info->BiosConnector[4].ddc_i2c.a_data_mask = RADEON_BIOS32(tmp0 + 0x07); 785209ff23fSmrg info->BiosConnector[4].ddc_i2c.put_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 786209ff23fSmrg info->BiosConnector[4].ddc_i2c.put_data_mask = RADEON_BIOS32(tmp0 + 0x07); 787209ff23fSmrg info->BiosConnector[4].ddc_i2c.get_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 788209ff23fSmrg info->BiosConnector[4].ddc_i2c.get_data_mask = RADEON_BIOS32(tmp0 + 0x07); 789209ff23fSmrg break; 790209ff23fSmrg default: 791209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown DDC Type: %d\n", DDCType); 792209ff23fSmrg break; 793209ff23fSmrg } 794209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); 795209ff23fSmrg } 796209ff23fSmrg } 797b7e1c893Smrg } else 798209ff23fSmrg info->BiosConnector[4].ddc_i2c.valid = FALSE; 799209ff23fSmrg } 800209ff23fSmrg } 801209ff23fSmrg 802209ff23fSmrg /* check TV table */ 803209ff23fSmrg if (info->InternalTVOut) { 804209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); 805209ff23fSmrg if (offset) { 806209ff23fSmrg if (RADEON_BIOS8(offset + 6) == 'T') { 807209ff23fSmrg info->BiosConnector[5].valid = TRUE; 808209ff23fSmrg /* assume s-video for now */ 809209ff23fSmrg info->BiosConnector[5].ConnectorType = CONNECTOR_STV; 810b7e1c893Smrg info->BiosConnector[5].load_detection = FALSE; 811209ff23fSmrg info->BiosConnector[5].ddc_i2c.valid = FALSE; 812b7e1c893Smrg info->BiosConnector[5].devices = ATOM_DEVICE_TV1_SUPPORT; 813b7e1c893Smrg if (!radeon_add_encoder(pScrn, 814b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 815b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT, 816b7e1c893Smrg 2), 817b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT)) 818b7e1c893Smrg return FALSE; 819209ff23fSmrg } 820209ff23fSmrg } 821209ff23fSmrg } 822209ff23fSmrg 823209ff23fSmrg return TRUE; 824209ff23fSmrg} 825209ff23fSmrg 826209ff23fSmrgBool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) 827209ff23fSmrg{ 828209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 829209ff23fSmrg 830209ff23fSmrg if(!info->VBIOS) return FALSE; 831209ff23fSmrg 832209ff23fSmrg if (info->IsAtomBios) 833209ff23fSmrg return RADEONGetATOMConnectorInfoFromBIOS(pScrn); 834209ff23fSmrg else 835209ff23fSmrg return RADEONGetLegacyConnectorInfoFromBIOS(pScrn); 836209ff23fSmrg} 837209ff23fSmrg 838209ff23fSmrgBool RADEONGetTVInfoFromBIOS (xf86OutputPtr output) { 839209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 840209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 841209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 842b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 843209ff23fSmrg int offset, refclk, stds; 844209ff23fSmrg 845209ff23fSmrg if (!info->VBIOS) return FALSE; 846209ff23fSmrg 847b7e1c893Smrg if (info->IsAtomBios) 848209ff23fSmrg return RADEONGetATOMTVInfo(output); 849b7e1c893Smrg else { 850209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); 851209ff23fSmrg if (offset) { 852209ff23fSmrg if (RADEON_BIOS8(offset + 6) == 'T') { 853209ff23fSmrg switch (RADEON_BIOS8(offset + 7) & 0xf) { 854209ff23fSmrg case 1: 855b7e1c893Smrg tvout->default_tvStd = TV_STD_NTSC; 856209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC\n"); 857209ff23fSmrg break; 858209ff23fSmrg case 2: 859b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL; 860209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL\n"); 861209ff23fSmrg break; 862209ff23fSmrg case 3: 863b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL_M; 864209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-M\n"); 865209ff23fSmrg break; 866209ff23fSmrg case 4: 867b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL_60; 868209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-60\n"); 869209ff23fSmrg break; 870209ff23fSmrg case 5: 871b7e1c893Smrg tvout->default_tvStd = TV_STD_NTSC_J; 872209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC-J\n"); 873209ff23fSmrg break; 874209ff23fSmrg case 6: 875b7e1c893Smrg tvout->default_tvStd = TV_STD_SCART_PAL; 876209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: SCART-PAL\n"); 877209ff23fSmrg break; 878209ff23fSmrg default: 879b7e1c893Smrg tvout->default_tvStd = TV_STD_NTSC; 880209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unknown TV standard; defaulting to NTSC\n"); 881209ff23fSmrg break; 882209ff23fSmrg } 883b7e1c893Smrg tvout->tvStd = tvout->default_tvStd; 884209ff23fSmrg 885209ff23fSmrg refclk = (RADEON_BIOS8(offset + 9) >> 2) & 0x3; 886209ff23fSmrg if (refclk == 0) 887b7e1c893Smrg tvout->TVRefClk = 29.498928713; /* MHz */ 888209ff23fSmrg else if (refclk == 1) 889b7e1c893Smrg tvout->TVRefClk = 28.636360000; 890209ff23fSmrg else if (refclk == 2) 891b7e1c893Smrg tvout->TVRefClk = 14.318180000; 892209ff23fSmrg else if (refclk == 3) 893b7e1c893Smrg tvout->TVRefClk = 27.000000000; 894209ff23fSmrg 895b7e1c893Smrg tvout->SupportedTVStds = tvout->default_tvStd; 896209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standards supported by chip: "); 897209ff23fSmrg stds = RADEON_BIOS8(offset + 10) & 0x1f; 898209ff23fSmrg if (stds & TV_STD_NTSC) { 899b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_NTSC; 900209ff23fSmrg ErrorF("NTSC "); 901209ff23fSmrg } 902209ff23fSmrg if (stds & TV_STD_PAL) { 903b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL; 904209ff23fSmrg ErrorF("PAL "); 905209ff23fSmrg } 906209ff23fSmrg if (stds & TV_STD_PAL_M) { 907b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL_M; 908209ff23fSmrg ErrorF("PAL-M "); 909209ff23fSmrg } 910209ff23fSmrg if (stds & TV_STD_PAL_60) { 911b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL_60; 912209ff23fSmrg ErrorF("PAL-60 "); 913209ff23fSmrg } 914209ff23fSmrg if (stds & TV_STD_NTSC_J) { 915b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_NTSC_J; 916209ff23fSmrg ErrorF("NTSC-J "); 917209ff23fSmrg } 918209ff23fSmrg if (stds & TV_STD_SCART_PAL) { 919b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_SCART_PAL; 920209ff23fSmrg ErrorF("SCART-PAL"); 921209ff23fSmrg } 922209ff23fSmrg ErrorF("\n"); 923209ff23fSmrg 924209ff23fSmrg return TRUE; 925209ff23fSmrg } 926209ff23fSmrg } 927209ff23fSmrg } 928209ff23fSmrg return FALSE; 929209ff23fSmrg} 930209ff23fSmrg 931209ff23fSmrg/* Read PLL parameters from BIOS block. Default to typical values if there 932209ff23fSmrg is no BIOS. */ 933209ff23fSmrgBool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn) 934209ff23fSmrg{ 935209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 936209ff23fSmrg RADEONPLLPtr pll = &info->pll; 937209ff23fSmrg uint16_t pll_info_block; 938209ff23fSmrg 939209ff23fSmrg if (!info->VBIOS) { 940209ff23fSmrg return FALSE; 941209ff23fSmrg } else { 942209ff23fSmrg if (info->IsAtomBios) { 943209ff23fSmrg pll_info_block = RADEON_BIOS16 (info->MasterDataStart + 12); 944209ff23fSmrg 945209ff23fSmrg pll->reference_freq = RADEON_BIOS16 (pll_info_block + 82); 946209ff23fSmrg pll->reference_div = 0; /* Need to derive from existing setting 947209ff23fSmrg or use a new algorithm to calculate 948209ff23fSmrg from min_input and max_input 949209ff23fSmrg */ 950209ff23fSmrg pll->pll_out_min = RADEON_BIOS16 (pll_info_block + 78); 951209ff23fSmrg pll->pll_out_max = RADEON_BIOS32 (pll_info_block + 32); 952209ff23fSmrg 953209ff23fSmrg if (pll->pll_out_min == 0) { 954209ff23fSmrg if (IS_AVIVO_VARIANT) 955209ff23fSmrg pll->pll_out_min = 64800; 956209ff23fSmrg else 957209ff23fSmrg pll->pll_out_min = 20000; 958209ff23fSmrg } 959209ff23fSmrg 960209ff23fSmrg pll->pll_in_min = RADEON_BIOS16 (pll_info_block + 74); 961209ff23fSmrg pll->pll_in_max = RADEON_BIOS16 (pll_info_block + 76); 962209ff23fSmrg 963209ff23fSmrg pll->xclk = RADEON_BIOS16 (pll_info_block + 72); 964209ff23fSmrg 965209ff23fSmrg info->sclk = RADEON_BIOS32(pll_info_block + 8) / 100.0; 966209ff23fSmrg info->mclk = RADEON_BIOS32(pll_info_block + 12) / 100.0; 967209ff23fSmrg } else { 968209ff23fSmrg int rev; 969209ff23fSmrg 970209ff23fSmrg pll_info_block = RADEON_BIOS16 (info->ROMHeaderStart + 0x30); 971209ff23fSmrg 972209ff23fSmrg rev = RADEON_BIOS8(pll_info_block); 973209ff23fSmrg 974209ff23fSmrg pll->reference_freq = RADEON_BIOS16 (pll_info_block + 0x0e); 975209ff23fSmrg pll->reference_div = RADEON_BIOS16 (pll_info_block + 0x10); 976209ff23fSmrg pll->pll_out_min = RADEON_BIOS32 (pll_info_block + 0x12); 977209ff23fSmrg pll->pll_out_max = RADEON_BIOS32 (pll_info_block + 0x16); 978209ff23fSmrg 979209ff23fSmrg if (rev > 9) { 980209ff23fSmrg pll->pll_in_min = RADEON_BIOS32(pll_info_block + 0x36); 981209ff23fSmrg pll->pll_in_max = RADEON_BIOS32(pll_info_block + 0x3a); 982209ff23fSmrg } else { 983209ff23fSmrg pll->pll_in_min = 40; 984209ff23fSmrg pll->pll_in_max = 500; 985209ff23fSmrg } 986209ff23fSmrg 987209ff23fSmrg pll->xclk = RADEON_BIOS16(pll_info_block + 0x08); 988209ff23fSmrg 989b7e1c893Smrg info->sclk = RADEON_BIOS16(pll_info_block + 10) / 100.0; 990b7e1c893Smrg info->mclk = RADEON_BIOS16(pll_info_block + 8) / 100.0; 991209ff23fSmrg } 992209ff23fSmrg 993209ff23fSmrg if (info->sclk == 0) info->sclk = 200; 994209ff23fSmrg if (info->mclk == 0) info->mclk = 200; 995209ff23fSmrg } 996209ff23fSmrg 997209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_out_pll: %u, " 998209ff23fSmrg "max_out_pll: %u, min_in_pll: %u, max_in_pll: %u, xclk: %d, " 999209ff23fSmrg "sclk: %f, mclk: %f\n", 1000209ff23fSmrg pll->reference_freq, (unsigned)pll->pll_out_min, 1001209ff23fSmrg (unsigned)pll->pll_out_max, (unsigned)pll->pll_in_min, 1002209ff23fSmrg (unsigned)pll->pll_in_max, pll->xclk, info->sclk, info->mclk); 1003209ff23fSmrg 1004209ff23fSmrg return TRUE; 1005209ff23fSmrg} 1006209ff23fSmrg 1007b7e1c893SmrgBool RADEONGetDAC2InfoFromBIOS (ScrnInfoPtr pScrn, radeon_tvdac_ptr tvdac) 1008209ff23fSmrg{ 1009209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1010209ff23fSmrg int offset, rev, bg, dac; 1011209ff23fSmrg 1012209ff23fSmrg if (!info->VBIOS) return FALSE; 1013209ff23fSmrg 1014209ff23fSmrg if (xf86ReturnOptValBool(info->Options, OPTION_DEFAULT_TVDAC_ADJ, FALSE)) 1015209ff23fSmrg return FALSE; 1016209ff23fSmrg 1017209ff23fSmrg if (info->IsAtomBios) { 1018209ff23fSmrg /* not implemented yet */ 1019209ff23fSmrg return FALSE; 1020209ff23fSmrg } else { 1021209ff23fSmrg /* first check TV table */ 1022209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); 1023209ff23fSmrg if (offset) { 1024209ff23fSmrg rev = RADEON_BIOS8(offset + 0x3); 1025209ff23fSmrg if (rev > 4) { 1026209ff23fSmrg bg = RADEON_BIOS8(offset + 0xc) & 0xf; 1027209ff23fSmrg dac = RADEON_BIOS8(offset + 0xd) & 0xf; 1028b7e1c893Smrg tvdac->ps2_tvdac_adj = (bg << 16) | (dac << 20); 1029209ff23fSmrg 1030209ff23fSmrg bg = RADEON_BIOS8(offset + 0xe) & 0xf; 1031209ff23fSmrg dac = RADEON_BIOS8(offset + 0xf) & 0xf; 1032b7e1c893Smrg tvdac->pal_tvdac_adj = (bg << 16) | (dac << 20); 1033209ff23fSmrg 1034209ff23fSmrg bg = RADEON_BIOS8(offset + 0x10) & 0xf; 1035209ff23fSmrg dac = RADEON_BIOS8(offset + 0x11) & 0xf; 1036b7e1c893Smrg tvdac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); 1037209ff23fSmrg 1038209ff23fSmrg return TRUE; 1039209ff23fSmrg } else if (rev > 1) { 1040209ff23fSmrg bg = RADEON_BIOS8(offset + 0xc) & 0xf; 1041209ff23fSmrg dac = (RADEON_BIOS8(offset + 0xc) >> 4) & 0xf; 1042b7e1c893Smrg tvdac->ps2_tvdac_adj = (bg << 16) | (dac << 20); 1043209ff23fSmrg 1044209ff23fSmrg bg = RADEON_BIOS8(offset + 0xd) & 0xf; 1045209ff23fSmrg dac = (RADEON_BIOS8(offset + 0xd) >> 4) & 0xf; 1046b7e1c893Smrg tvdac->pal_tvdac_adj = (bg << 16) | (dac << 20); 1047209ff23fSmrg 1048209ff23fSmrg bg = RADEON_BIOS8(offset + 0xe) & 0xf; 1049209ff23fSmrg dac = (RADEON_BIOS8(offset + 0xe) >> 4) & 0xf; 1050b7e1c893Smrg tvdac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); 1051209ff23fSmrg 1052209ff23fSmrg return TRUE; 1053209ff23fSmrg } 1054209ff23fSmrg } 1055209ff23fSmrg /* then check CRT table */ 1056209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x60); 1057209ff23fSmrg if (offset) { 1058209ff23fSmrg rev = RADEON_BIOS8(offset) & 0x3; 1059209ff23fSmrg if (rev < 2) { 1060209ff23fSmrg bg = RADEON_BIOS8(offset + 0x3) & 0xf; 1061209ff23fSmrg dac = (RADEON_BIOS8(offset + 0x3) >> 4) & 0xf; 1062b7e1c893Smrg tvdac->ps2_tvdac_adj = (bg << 16) | (dac << 20); 1063b7e1c893Smrg tvdac->pal_tvdac_adj = tvdac->ps2_tvdac_adj; 1064b7e1c893Smrg tvdac->ntsc_tvdac_adj = tvdac->ps2_tvdac_adj; 1065209ff23fSmrg 1066209ff23fSmrg return TRUE; 1067209ff23fSmrg } else { 1068209ff23fSmrg bg = RADEON_BIOS8(offset + 0x4) & 0xf; 1069209ff23fSmrg dac = RADEON_BIOS8(offset + 0x5) & 0xf; 1070b7e1c893Smrg tvdac->ps2_tvdac_adj = (bg << 16) | (dac << 20); 1071b7e1c893Smrg tvdac->pal_tvdac_adj = tvdac->ps2_tvdac_adj; 1072b7e1c893Smrg tvdac->ntsc_tvdac_adj = tvdac->ps2_tvdac_adj; 1073209ff23fSmrg 1074209ff23fSmrg return TRUE; 1075209ff23fSmrg } 1076209ff23fSmrg } 1077209ff23fSmrg } 1078209ff23fSmrg 1079209ff23fSmrg return FALSE; 1080209ff23fSmrg} 1081209ff23fSmrg 1082b7e1c893SmrgBool 1083b7e1c893SmrgRADEONGetLVDSInfoFromBIOS(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds) 1084209ff23fSmrg{ 1085209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1086b7e1c893Smrg radeon_native_mode_ptr native_mode = &lvds->native_mode; 1087209ff23fSmrg unsigned long tmp, i; 1088209ff23fSmrg 1089b7e1c893Smrg if (!info->VBIOS) 1090b7e1c893Smrg return FALSE; 1091209ff23fSmrg 1092b7e1c893Smrg if (!info->IsAtomBios) { 1093209ff23fSmrg tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x40); 1094209ff23fSmrg 1095209ff23fSmrg if (!tmp) { 1096209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1097209ff23fSmrg "No Panel Info Table found in BIOS!\n"); 1098209ff23fSmrg return FALSE; 1099209ff23fSmrg } else { 1100209ff23fSmrg char stmp[30]; 1101209ff23fSmrg int tmp0; 1102209ff23fSmrg 1103209ff23fSmrg for (i = 0; i < 24; i++) 1104209ff23fSmrg stmp[i] = RADEON_BIOS8(tmp+i+1); 1105209ff23fSmrg stmp[24] = 0; 1106209ff23fSmrg 1107209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1108209ff23fSmrg "Panel ID string: %s\n", stmp); 1109209ff23fSmrg 1110b7e1c893Smrg native_mode->PanelXRes = RADEON_BIOS16(tmp+25); 1111b7e1c893Smrg native_mode->PanelYRes = RADEON_BIOS16(tmp+27); 1112209ff23fSmrg xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n", 1113b7e1c893Smrg native_mode->PanelXRes, native_mode->PanelYRes); 1114b7e1c893Smrg 1115b7e1c893Smrg lvds->PanelPwrDly = RADEON_BIOS16(tmp+44); 1116b7e1c893Smrg if (lvds->PanelPwrDly > 2000 || lvds->PanelPwrDly < 0) 1117b7e1c893Smrg lvds->PanelPwrDly = 2000; 1118209ff23fSmrg 1119209ff23fSmrg /* some panels only work well with certain divider combinations. 1120209ff23fSmrg */ 1121209ff23fSmrg info->RefDivider = RADEON_BIOS16(tmp+46); 1122209ff23fSmrg info->PostDivider = RADEON_BIOS8(tmp+48); 1123209ff23fSmrg info->FeedbackDivider = RADEON_BIOS16(tmp+49); 1124209ff23fSmrg if ((info->RefDivider != 0) && 1125209ff23fSmrg (info->FeedbackDivider > 3)) { 1126209ff23fSmrg info->UseBiosDividers = TRUE; 1127209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1128209ff23fSmrg "BIOS provided dividers will be used.\n"); 1129209ff23fSmrg } 1130209ff23fSmrg 1131209ff23fSmrg /* We don't use a while loop here just in case we have a corrupted BIOS image. 1132209ff23fSmrg The max number of table entries is 23 at present, but may grow in future. 1133209ff23fSmrg To ensure it works with future revisions we loop it to 32. 1134209ff23fSmrg */ 1135209ff23fSmrg for (i = 0; i < 32; i++) { 1136209ff23fSmrg tmp0 = RADEON_BIOS16(tmp+64+i*2); 1137209ff23fSmrg if (tmp0 == 0) break; 1138b7e1c893Smrg if ((RADEON_BIOS16(tmp0) == native_mode->PanelXRes) && 1139b7e1c893Smrg (RADEON_BIOS16(tmp0+2) == native_mode->PanelYRes)) { 1140b7e1c893Smrg native_mode->HBlank = (RADEON_BIOS16(tmp0+17) - 1141b7e1c893Smrg RADEON_BIOS16(tmp0+19)) * 8; 1142b7e1c893Smrg native_mode->HOverPlus = (RADEON_BIOS16(tmp0+21) - 1143b7e1c893Smrg RADEON_BIOS16(tmp0+19) - 1) * 8; 1144b7e1c893Smrg native_mode->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8; 1145b7e1c893Smrg native_mode->VBlank = (RADEON_BIOS16(tmp0+24) - 1146b7e1c893Smrg RADEON_BIOS16(tmp0+26)); 1147b7e1c893Smrg native_mode->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) - 1148b7e1c893Smrg RADEON_BIOS16(tmp0+26)); 1149b7e1c893Smrg native_mode->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800) >> 11); 1150b7e1c893Smrg native_mode->DotClock = RADEON_BIOS16(tmp0+9) * 10; 1151b7e1c893Smrg native_mode->Flags = 0; 1152209ff23fSmrg } 1153209ff23fSmrg } 1154209ff23fSmrg } 1155209ff23fSmrg 1156b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1157b7e1c893Smrg "LVDS Info:\n" 1158b7e1c893Smrg "XRes: %d, YRes: %d, DotClock: %d\n" 1159b7e1c893Smrg "HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n" 1160b7e1c893Smrg "VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n", 1161b7e1c893Smrg native_mode->PanelXRes, native_mode->PanelYRes, native_mode->DotClock, 1162b7e1c893Smrg native_mode->HBlank, native_mode->HOverPlus, native_mode->HSyncWidth, 1163b7e1c893Smrg native_mode->VBlank, native_mode->VOverPlus, native_mode->VSyncWidth); 1164209ff23fSmrg 1165b7e1c893Smrg return TRUE; 1166b7e1c893Smrg } 1167b7e1c893Smrg return FALSE; 1168209ff23fSmrg} 1169209ff23fSmrg 1170b7e1c893Smrgxf86MonPtr RADEONGetHardCodedEDIDFromBIOS (xf86OutputPtr output) 1171209ff23fSmrg{ 1172209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1173b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 1174209ff23fSmrg unsigned long tmp; 1175b7e1c893Smrg unsigned char edid[256]; 1176b7e1c893Smrg xf86MonPtr mon = NULL; 1177209ff23fSmrg 1178b7e1c893Smrg if (!info->VBIOS) 1179b7e1c893Smrg return mon; 1180209ff23fSmrg 1181b7e1c893Smrg if (!info->IsAtomBios) { 1182b7e1c893Smrg tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x4c); 1183b7e1c893Smrg if (tmp) { 1184b7e1c893Smrg memcpy(edid, (unsigned char*)(info->VBIOS + tmp), 256); 1185b7e1c893Smrg if (edid[1] == 0xff) 1186b7e1c893Smrg mon = xf86InterpretEDID(output->scrn->scrnIndex, edid); 1187209ff23fSmrg } 1188209ff23fSmrg } 1189b7e1c893Smrg 1190b7e1c893Smrg return mon; 1191209ff23fSmrg} 1192209ff23fSmrg 1193b7e1c893SmrgBool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn, radeon_tmds_ptr tmds) 1194209ff23fSmrg{ 1195209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1196209ff23fSmrg uint32_t tmp, maxfreq; 1197209ff23fSmrg int i, n; 1198209ff23fSmrg 1199209ff23fSmrg if (!info->VBIOS) return FALSE; 1200209ff23fSmrg 1201209ff23fSmrg if (info->IsAtomBios) { 1202209ff23fSmrg if((tmp = RADEON_BIOS16 (info->MasterDataStart + 18))) { 1203209ff23fSmrg 1204209ff23fSmrg maxfreq = RADEON_BIOS16(tmp+4); 1205b7e1c893Smrg 1206209ff23fSmrg for (i=0; i<4; i++) { 1207b7e1c893Smrg tmds->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*6+6); 1208209ff23fSmrg /* This assumes each field in TMDS_PLL has 6 bit as in R300/R420 */ 1209b7e1c893Smrg tmds->tmds_pll[i].value = ((RADEON_BIOS8(tmp+i*6+8) & 0x3f) | 1210209ff23fSmrg ((RADEON_BIOS8(tmp+i*6+10) & 0x3f)<<6) | 1211209ff23fSmrg ((RADEON_BIOS8(tmp+i*6+9) & 0xf)<<12) | 1212209ff23fSmrg ((RADEON_BIOS8(tmp+i*6+11) & 0xf)<<16)); 1213b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1214b7e1c893Smrg "TMDS PLL from BIOS: %u %x\n", 1215b7e1c893Smrg (unsigned)tmds->tmds_pll[i].freq, 1216b7e1c893Smrg (unsigned)tmds->tmds_pll[i].value); 1217b7e1c893Smrg 1218b7e1c893Smrg if (maxfreq == tmds->tmds_pll[i].freq) { 1219b7e1c893Smrg tmds->tmds_pll[i].freq = 0xffffffff; 1220209ff23fSmrg break; 1221209ff23fSmrg } 1222209ff23fSmrg } 1223209ff23fSmrg return TRUE; 1224209ff23fSmrg } 1225209ff23fSmrg } else { 1226209ff23fSmrg 1227209ff23fSmrg tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x34); 1228209ff23fSmrg if (tmp) { 1229209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1230209ff23fSmrg "DFP table revision: %d\n", RADEON_BIOS8(tmp)); 1231209ff23fSmrg if (RADEON_BIOS8(tmp) == 3) { 1232209ff23fSmrg n = RADEON_BIOS8(tmp + 5) + 1; 1233209ff23fSmrg if (n > 4) n = 4; 1234209ff23fSmrg for (i=0; i<n; i++) { 1235b7e1c893Smrg tmds->tmds_pll[i].value = RADEON_BIOS32(tmp+i*10+0x08); 1236b7e1c893Smrg tmds->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*10+0x10); 1237209ff23fSmrg } 1238209ff23fSmrg return TRUE; 1239209ff23fSmrg } else if (RADEON_BIOS8(tmp) == 4) { 1240209ff23fSmrg int stride = 0; 1241209ff23fSmrg n = RADEON_BIOS8(tmp + 5) + 1; 1242209ff23fSmrg if (n > 4) n = 4; 1243209ff23fSmrg for (i=0; i<n; i++) { 1244b7e1c893Smrg tmds->tmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); 1245b7e1c893Smrg tmds->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); 1246209ff23fSmrg if (i == 0) stride += 10; 1247209ff23fSmrg else stride += 6; 1248209ff23fSmrg } 1249209ff23fSmrg return TRUE; 1250209ff23fSmrg } 1251209ff23fSmrg } 1252209ff23fSmrg } 1253209ff23fSmrg return FALSE; 1254209ff23fSmrg} 1255209ff23fSmrg 1256b7e1c893Smrgstatic RADEONI2CBusRec 1257b7e1c893SmrgRADEONLookupI2CBlock(ScrnInfoPtr pScrn, int id) 1258b7e1c893Smrg{ 1259b7e1c893Smrg RADEONInfoPtr info = RADEONPTR (pScrn); 1260b7e1c893Smrg int offset, blocks, i; 1261b7e1c893Smrg RADEONI2CBusRec i2c; 1262b7e1c893Smrg 1263b7e1c893Smrg memset(&i2c, 0, sizeof(RADEONI2CBusRec)); 1264b7e1c893Smrg i2c.valid = FALSE; 1265b7e1c893Smrg 1266b7e1c893Smrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x70); 1267b7e1c893Smrg if (offset) { 1268b7e1c893Smrg blocks = RADEON_BIOS8(offset + 2); 1269b7e1c893Smrg for (i = 0; i < blocks; i++) { 1270b7e1c893Smrg int i2c_id = RADEON_BIOS8(offset + 3 + (i * 5) + 0); 1271b7e1c893Smrg if (id == i2c_id) { 1272b7e1c893Smrg int reg = RADEON_BIOS16(offset + 3 + (i * 5) + 1) * 4; 1273b7e1c893Smrg int clock_shift = RADEON_BIOS8(offset + 3 + (i * 5) + 3); 1274b7e1c893Smrg int data_shift = RADEON_BIOS8(offset + 3 + (i * 5) + 4); 1275b7e1c893Smrg 1276b7e1c893Smrg i2c.mask_clk_mask = (1 << clock_shift); 1277b7e1c893Smrg i2c.mask_data_mask = (1 << data_shift); 1278b7e1c893Smrg i2c.a_clk_mask = (1 << clock_shift); 1279b7e1c893Smrg i2c.a_data_mask = (1 << data_shift); 1280b7e1c893Smrg i2c.put_clk_mask = (1 << clock_shift); 1281b7e1c893Smrg i2c.put_data_mask = (1 << data_shift); 1282b7e1c893Smrg i2c.get_clk_mask = (1 << clock_shift); 1283b7e1c893Smrg i2c.get_data_mask = (1 << data_shift); 1284b7e1c893Smrg i2c.mask_clk_reg = reg; 1285b7e1c893Smrg i2c.mask_data_reg = reg; 1286b7e1c893Smrg i2c.a_clk_reg = reg; 1287b7e1c893Smrg i2c.a_data_reg = reg; 1288b7e1c893Smrg i2c.put_clk_reg = reg; 1289b7e1c893Smrg i2c.put_data_reg = reg; 1290b7e1c893Smrg i2c.get_clk_reg = reg; 1291b7e1c893Smrg i2c.get_data_reg = reg; 1292b7e1c893Smrg i2c.valid = TRUE; 1293b7e1c893Smrg break; 1294b7e1c893Smrg } 1295b7e1c893Smrg } 1296b7e1c893Smrg } 1297b7e1c893Smrg return i2c; 1298b7e1c893Smrg} 1299b7e1c893Smrg 1300b7e1c893SmrgBool RADEONGetExtTMDSInfoFromBIOS (ScrnInfoPtr pScrn, radeon_dvo_ptr dvo) 1301209ff23fSmrg{ 1302209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1303209ff23fSmrg int offset, table_start, max_freq, gpio_reg, flags; 1304209ff23fSmrg 1305b7e1c893Smrg if (!info->VBIOS) 1306b7e1c893Smrg return FALSE; 1307209ff23fSmrg 1308b7e1c893Smrg if (info->IsAtomBios) 1309209ff23fSmrg return FALSE; 1310b7e1c893Smrg else if (info->IsIGP) { 1311b7e1c893Smrg /* RS4xx TMDS stuff is in the mobile table */ 1312b7e1c893Smrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x42); 1313b7e1c893Smrg if (offset) { 1314b7e1c893Smrg int rev = RADEON_BIOS8(offset); 1315b7e1c893Smrg if (rev >= 6) { 1316b7e1c893Smrg offset = RADEON_BIOS16(offset + 0x17); 1317b7e1c893Smrg if (offset) { 1318b7e1c893Smrg offset = RADEON_BIOS16(offset + 2); 1319b7e1c893Smrg rev = RADEON_BIOS8(offset); 1320b7e1c893Smrg if (offset && (rev > 1)) { 1321b7e1c893Smrg int blocks = RADEON_BIOS8(offset + 3); 1322b7e1c893Smrg int index = offset + 4; 1323b7e1c893Smrg dvo->dvo_i2c.valid = FALSE; 1324b7e1c893Smrg while (blocks > 0) { 1325b7e1c893Smrg int id = RADEON_BIOS16(index); 1326b7e1c893Smrg index += 2; 1327b7e1c893Smrg switch (id >> 13) { 1328b7e1c893Smrg case 0: 1329b7e1c893Smrg index += 6; 1330b7e1c893Smrg break; 1331b7e1c893Smrg case 2: 1332b7e1c893Smrg index += 10; 1333b7e1c893Smrg break; 1334b7e1c893Smrg case 3: 1335b7e1c893Smrg index += 2; 1336b7e1c893Smrg break; 1337b7e1c893Smrg case 4: 1338b7e1c893Smrg index += 2; 1339b7e1c893Smrg break; 1340b7e1c893Smrg case 6: 1341b7e1c893Smrg dvo->dvo_i2c_slave_addr = 1342b7e1c893Smrg RADEON_BIOS16(index) & 0xff; 1343b7e1c893Smrg index += 2; 1344b7e1c893Smrg dvo->dvo_i2c = 1345b7e1c893Smrg RADEONLookupI2CBlock(pScrn, RADEON_BIOS8(index)); 1346b7e1c893Smrg return TRUE; 1347b7e1c893Smrg default: 1348b7e1c893Smrg break; 1349b7e1c893Smrg } 1350b7e1c893Smrg blocks--; 1351b7e1c893Smrg } 1352b7e1c893Smrg } 1353b7e1c893Smrg } 1354b7e1c893Smrg } 1355b7e1c893Smrg } 1356209ff23fSmrg } else { 1357209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58); 1358209ff23fSmrg if (offset) { 1359209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1360209ff23fSmrg "External TMDS Table revision: %d\n", 1361209ff23fSmrg RADEON_BIOS8(offset)); 1362209ff23fSmrg table_start = offset+4; 1363209ff23fSmrg max_freq = RADEON_BIOS16(table_start); 1364b7e1c893Smrg dvo->dvo_i2c_slave_addr = RADEON_BIOS8(table_start+2); 1365b7e1c893Smrg dvo->dvo_i2c.valid = FALSE; 1366209ff23fSmrg gpio_reg = RADEON_BIOS8(table_start+3); 1367209ff23fSmrg if (gpio_reg == 1) 1368b7e1c893Smrg dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); 1369209ff23fSmrg else if (gpio_reg == 2) 1370b7e1c893Smrg dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC); 1371209ff23fSmrg else if (gpio_reg == 3) 1372b7e1c893Smrg dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC); 1373209ff23fSmrg else if (gpio_reg == 4) 1374b7e1c893Smrg dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); 1375b7e1c893Smrg else if (gpio_reg == 5) { 1376209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1377209ff23fSmrg "unsupported MM gpio_reg\n"); 1378b7e1c893Smrg return FALSE; 1379b7e1c893Smrg } else { 1380209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1381209ff23fSmrg "Unknown gpio reg: %d\n", gpio_reg); 1382209ff23fSmrg return FALSE; 1383209ff23fSmrg } 1384209ff23fSmrg flags = RADEON_BIOS8(table_start+5); 1385b7e1c893Smrg dvo->dvo_duallink = flags & 0x01; 1386b7e1c893Smrg if (dvo->dvo_duallink) { 1387209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1388209ff23fSmrg "Duallink TMDS detected\n"); 1389209ff23fSmrg } 1390209ff23fSmrg return TRUE; 1391209ff23fSmrg } 1392209ff23fSmrg } 1393209ff23fSmrg 1394209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1395209ff23fSmrg "No External TMDS Table found\n"); 1396209ff23fSmrg 1397209ff23fSmrg return FALSE; 1398209ff23fSmrg} 1399209ff23fSmrg 1400209ff23fSmrgBool RADEONInitExtTMDSInfoFromBIOS (xf86OutputPtr output) 1401209ff23fSmrg{ 1402209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1403209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1404209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1405b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1406b7e1c893Smrg radeon_dvo_ptr dvo = NULL; 1407209ff23fSmrg int offset, index, id; 1408b7e1c893Smrg uint32_t val, reg, and_mask, or_mask; 1409209ff23fSmrg 1410b7e1c893Smrg if (radeon_encoder == NULL) 1411b7e1c893Smrg return FALSE; 1412209ff23fSmrg 1413b7e1c893Smrg dvo = (radeon_dvo_ptr)radeon_encoder->dev_priv; 1414b7e1c893Smrg 1415b7e1c893Smrg if (dvo == NULL) 1416b7e1c893Smrg return FALSE; 1417b7e1c893Smrg 1418b7e1c893Smrg if (!info->VBIOS) 1419b7e1c893Smrg return FALSE; 1420b7e1c893Smrg 1421b7e1c893Smrg if (info->IsAtomBios) 1422209ff23fSmrg return FALSE; 1423b7e1c893Smrg else if (info->IsIGP) { 1424b7e1c893Smrg /* RS4xx TMDS stuff is in the mobile table */ 1425b7e1c893Smrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x42); 1426b7e1c893Smrg if (offset) { 1427b7e1c893Smrg int rev = RADEON_BIOS8(offset); 1428b7e1c893Smrg if (rev >= 6) { 1429b7e1c893Smrg offset = RADEON_BIOS16(offset + 0x17); 1430b7e1c893Smrg if (offset) { 1431b7e1c893Smrg offset = RADEON_BIOS16(offset + 2); 1432b7e1c893Smrg rev = RADEON_BIOS8(offset); 1433b7e1c893Smrg if (offset && (rev > 1)) { 1434b7e1c893Smrg int blocks = RADEON_BIOS8(offset + 3); 1435b7e1c893Smrg index = offset + 4; 1436b7e1c893Smrg while (blocks > 0) { 1437b7e1c893Smrg id = RADEON_BIOS16(index); 1438b7e1c893Smrg index += 2; 1439b7e1c893Smrg switch (id >> 13) { 1440b7e1c893Smrg case 0: 1441b7e1c893Smrg reg = (id & 0x1fff) * 4; 1442b7e1c893Smrg val = RADEON_BIOS32(index); 1443b7e1c893Smrg index += 4; 1444b7e1c893Smrg ErrorF("MMIO: 0x%x 0x%x\n", 1445b7e1c893Smrg (unsigned)reg, (unsigned)val); 1446b7e1c893Smrg OUTREG(reg, val); 1447b7e1c893Smrg break; 1448b7e1c893Smrg case 2: 1449b7e1c893Smrg reg = (id & 0x1fff) * 4; 1450b7e1c893Smrg and_mask = RADEON_BIOS32(index); 1451b7e1c893Smrg index += 4; 1452b7e1c893Smrg or_mask = RADEON_BIOS32(index); 1453b7e1c893Smrg index += 4; 1454b7e1c893Smrg ErrorF("MMIO mask: 0x%x 0x%x 0x%x\n", 1455b7e1c893Smrg (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask); 1456b7e1c893Smrg val = INREG(reg); 1457b7e1c893Smrg val = (val & and_mask) | or_mask; 1458b7e1c893Smrg OUTREG(reg, val); 1459b7e1c893Smrg break; 1460b7e1c893Smrg case 3: 1461b7e1c893Smrg val = RADEON_BIOS16(index); 1462b7e1c893Smrg index += 2; 1463b7e1c893Smrg ErrorF("delay: %u\n", (unsigned)val); 1464b7e1c893Smrg usleep(val); 1465b7e1c893Smrg break; 1466b7e1c893Smrg case 4: 1467b7e1c893Smrg val = RADEON_BIOS16(index); 1468b7e1c893Smrg index += 2; 1469b7e1c893Smrg ErrorF("delay: %u\n", (unsigned)val * 1000); 1470b7e1c893Smrg usleep(val * 1000); 1471b7e1c893Smrg break; 1472b7e1c893Smrg case 6: 1473b7e1c893Smrg index++; 1474b7e1c893Smrg reg = RADEON_BIOS8(index); 1475b7e1c893Smrg index++; 1476b7e1c893Smrg val = RADEON_BIOS8(index); 1477b7e1c893Smrg index++; 1478b7e1c893Smrg ErrorF("i2c write: 0x%x, 0x%x\n", (unsigned)reg, 1479b7e1c893Smrg (unsigned)val); 1480b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, reg, val); 1481b7e1c893Smrg break; 1482b7e1c893Smrg default: 1483b7e1c893Smrg ErrorF("unknown id %d\n", id>>13); 1484b7e1c893Smrg return FALSE; 1485b7e1c893Smrg } 1486b7e1c893Smrg blocks--; 1487b7e1c893Smrg } 1488b7e1c893Smrg return TRUE; 1489b7e1c893Smrg } 1490b7e1c893Smrg } 1491b7e1c893Smrg } 1492b7e1c893Smrg } 1493209ff23fSmrg } else { 1494209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58); 1495209ff23fSmrg if (offset) { 1496209ff23fSmrg index = offset+10; 1497209ff23fSmrg id = RADEON_BIOS16(index); 1498209ff23fSmrg while (id != 0xffff) { 1499209ff23fSmrg index += 2; 1500209ff23fSmrg switch(id >> 13) { 1501209ff23fSmrg case 0: 1502b7e1c893Smrg reg = (id & 0x1fff) * 4; 1503209ff23fSmrg val = RADEON_BIOS32(index); 1504209ff23fSmrg index += 4; 1505b7e1c893Smrg ErrorF("MMIO: 0x%x 0x%x\n", 1506209ff23fSmrg (unsigned)reg, (unsigned)val); 1507b7e1c893Smrg OUTREG(reg, val); 1508209ff23fSmrg break; 1509209ff23fSmrg case 2: 1510b7e1c893Smrg reg = (id & 0x1fff) * 4; 1511b7e1c893Smrg and_mask = RADEON_BIOS32(index); 1512209ff23fSmrg index += 4; 1513b7e1c893Smrg or_mask = RADEON_BIOS32(index); 1514209ff23fSmrg index += 4; 1515209ff23fSmrg val = INREG(reg); 1516b7e1c893Smrg val = (val & and_mask) | or_mask; 1517b7e1c893Smrg ErrorF("MMIO mask: 0x%x 0x%x 0x%x\n", 1518b7e1c893Smrg (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask); 1519b7e1c893Smrg OUTREG(reg, val); 1520209ff23fSmrg break; 1521209ff23fSmrg case 4: 1522209ff23fSmrg val = RADEON_BIOS16(index); 1523209ff23fSmrg index += 2; 1524209ff23fSmrg ErrorF("delay: %u\n", (unsigned)val); 1525209ff23fSmrg usleep(val); 1526209ff23fSmrg break; 1527209ff23fSmrg case 5: 1528209ff23fSmrg reg = id & 0x1fff; 1529b7e1c893Smrg and_mask = RADEON_BIOS32(index); 1530209ff23fSmrg index += 4; 1531b7e1c893Smrg or_mask = RADEON_BIOS32(index); 1532209ff23fSmrg index += 4; 1533b7e1c893Smrg ErrorF("PLL mask: 0x%x 0x%x 0x%x\n", 1534b7e1c893Smrg (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask); 1535b7e1c893Smrg val = INPLL(pScrn, reg); 1536b7e1c893Smrg val = (val & and_mask) | or_mask; 1537b7e1c893Smrg OUTPLL(pScrn, reg, val); 1538209ff23fSmrg break; 1539209ff23fSmrg case 6: 1540209ff23fSmrg reg = id & 0x1fff; 1541209ff23fSmrg val = RADEON_BIOS8(index); 1542209ff23fSmrg index += 1; 1543209ff23fSmrg ErrorF("i2c write: 0x%x, 0x%x\n", (unsigned)reg, 1544209ff23fSmrg (unsigned)val); 1545b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, reg, val); 1546209ff23fSmrg break; 1547209ff23fSmrg default: 1548209ff23fSmrg ErrorF("unknown id %d\n", id>>13); 1549209ff23fSmrg return FALSE; 1550209ff23fSmrg }; 1551209ff23fSmrg id = RADEON_BIOS16(index); 1552209ff23fSmrg } 1553209ff23fSmrg return TRUE; 1554209ff23fSmrg } 1555209ff23fSmrg } 1556209ff23fSmrg 1557209ff23fSmrg return FALSE; 1558209ff23fSmrg} 1559209ff23fSmrg 1560209ff23fSmrg/* support for init from bios tables 1561209ff23fSmrg * 1562209ff23fSmrg * Based heavily on the netbsd radeonfb driver 1563209ff23fSmrg * Written by Garrett D'Amore 1564209ff23fSmrg * Copyright (c) 2006 Itronix Inc. 1565209ff23fSmrg * 1566209ff23fSmrg */ 1567209ff23fSmrg 1568209ff23fSmrg/* bios table defines */ 1569209ff23fSmrg 1570209ff23fSmrg#define RADEON_TABLE_ENTRY_FLAG_MASK 0xe000 1571209ff23fSmrg#define RADEON_TABLE_ENTRY_INDEX_MASK 0x1fff 1572209ff23fSmrg#define RADEON_TABLE_ENTRY_COMMAND_MASK 0x00ff 1573209ff23fSmrg 1574209ff23fSmrg#define RADEON_TABLE_FLAG_WRITE_INDEXED 0x0000 1575209ff23fSmrg#define RADEON_TABLE_FLAG_WRITE_DIRECT 0x2000 1576209ff23fSmrg#define RADEON_TABLE_FLAG_MASK_INDEXED 0x4000 1577209ff23fSmrg#define RADEON_TABLE_FLAG_MASK_DIRECT 0x6000 1578209ff23fSmrg#define RADEON_TABLE_FLAG_DELAY 0x8000 1579209ff23fSmrg#define RADEON_TABLE_FLAG_SCOMMAND 0xa000 1580209ff23fSmrg 1581209ff23fSmrg#define RADEON_TABLE_SCOMMAND_WAIT_MC_BUSY_MASK 0x03 1582209ff23fSmrg#define RADEON_TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE 0x08 1583209ff23fSmrg 1584209ff23fSmrg#define RADEON_PLL_FLAG_MASK 0xc0 1585209ff23fSmrg#define RADEON_PLL_INDEX_MASK 0x3f 1586209ff23fSmrg 1587209ff23fSmrg#define RADEON_PLL_FLAG_WRITE 0x00 1588209ff23fSmrg#define RADEON_PLL_FLAG_MASK_BYTE 0x40 1589209ff23fSmrg#define RADEON_PLL_FLAG_WAIT 0x80 1590209ff23fSmrg 1591209ff23fSmrg#define RADEON_PLL_WAIT_150MKS 1 1592209ff23fSmrg#define RADEON_PLL_WAIT_5MS 2 1593209ff23fSmrg#define RADEON_PLL_WAIT_MC_BUSY_MASK 3 1594209ff23fSmrg#define RADEON_PLL_WAIT_DLL_READY_MASK 4 1595209ff23fSmrg#define RADEON_PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24 5 1596209ff23fSmrg 1597209ff23fSmrgstatic uint16_t 1598209ff23fSmrgRADEONValidateBIOSOffset(ScrnInfoPtr pScrn, uint16_t offset) 1599209ff23fSmrg{ 1600209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1601209ff23fSmrg uint8_t revision = RADEON_BIOS8(offset - 1); 1602209ff23fSmrg 1603209ff23fSmrg if (revision > 0x10) { 1604209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1605209ff23fSmrg "Bad revision %d for BIOS table\n", revision); 1606209ff23fSmrg return 0; 1607209ff23fSmrg } 1608209ff23fSmrg 1609209ff23fSmrg if (offset < 0x60) { 1610209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1611209ff23fSmrg "Bad offset 0x%x for BIOS Table\n", offset); 1612209ff23fSmrg return 0; 1613209ff23fSmrg } 1614209ff23fSmrg 1615209ff23fSmrg return offset; 1616209ff23fSmrg} 1617209ff23fSmrg 1618209ff23fSmrgBool 1619209ff23fSmrgRADEONGetBIOSInitTableOffsets(ScrnInfoPtr pScrn) 1620209ff23fSmrg{ 1621209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1622209ff23fSmrg uint8_t val; 1623209ff23fSmrg 1624209ff23fSmrg if (!info->VBIOS) { 1625209ff23fSmrg return FALSE; 1626209ff23fSmrg } else { 1627209ff23fSmrg if (info->IsAtomBios) { 1628209ff23fSmrg return FALSE; 1629209ff23fSmrg } else { 1630209ff23fSmrg info->BiosTable.revision = RADEON_BIOS8(info->ROMHeaderStart + 4); 1631209ff23fSmrg info->BiosTable.rr1_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x0c); 1632209ff23fSmrg if (info->BiosTable.rr1_offset) { 1633209ff23fSmrg info->BiosTable.rr1_offset = 1634209ff23fSmrg RADEONValidateBIOSOffset(pScrn, info->BiosTable.rr1_offset); 1635209ff23fSmrg } 1636209ff23fSmrg if (info->BiosTable.revision > 0x09) 1637209ff23fSmrg return TRUE; 1638209ff23fSmrg info->BiosTable.rr2_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x4e); 1639209ff23fSmrg if (info->BiosTable.rr2_offset) { 1640209ff23fSmrg info->BiosTable.rr2_offset = 1641209ff23fSmrg RADEONValidateBIOSOffset(pScrn, info->BiosTable.rr2_offset); 1642209ff23fSmrg } 1643209ff23fSmrg info->BiosTable.dyn_clk_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x52); 1644209ff23fSmrg if (info->BiosTable.dyn_clk_offset) { 1645209ff23fSmrg info->BiosTable.dyn_clk_offset = 1646209ff23fSmrg RADEONValidateBIOSOffset(pScrn, info->BiosTable.dyn_clk_offset); 1647209ff23fSmrg } 1648209ff23fSmrg info->BiosTable.pll_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x46); 1649209ff23fSmrg if (info->BiosTable.pll_offset) { 1650209ff23fSmrg info->BiosTable.pll_offset = 1651209ff23fSmrg RADEONValidateBIOSOffset(pScrn, info->BiosTable.pll_offset); 1652209ff23fSmrg } 1653209ff23fSmrg info->BiosTable.mem_config_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x48); 1654209ff23fSmrg if (info->BiosTable.mem_config_offset) { 1655209ff23fSmrg info->BiosTable.mem_config_offset = 1656209ff23fSmrg RADEONValidateBIOSOffset(pScrn, info->BiosTable.mem_config_offset); 1657209ff23fSmrg } 1658209ff23fSmrg if (info->BiosTable.mem_config_offset) { 1659209ff23fSmrg info->BiosTable.mem_reset_offset = info->BiosTable.mem_config_offset; 1660209ff23fSmrg if (info->BiosTable.mem_reset_offset) { 1661209ff23fSmrg while (RADEON_BIOS8(info->BiosTable.mem_reset_offset)) 1662209ff23fSmrg info->BiosTable.mem_reset_offset++; 1663209ff23fSmrg info->BiosTable.mem_reset_offset++; 1664209ff23fSmrg info->BiosTable.mem_reset_offset += 2; 1665209ff23fSmrg } 1666209ff23fSmrg } 1667209ff23fSmrg if (info->BiosTable.mem_config_offset) { 1668209ff23fSmrg info->BiosTable.short_mem_offset = info->BiosTable.mem_config_offset; 1669209ff23fSmrg if ((info->BiosTable.short_mem_offset != 0) && 1670209ff23fSmrg (RADEON_BIOS8(info->BiosTable.short_mem_offset - 2) <= 64)) 1671209ff23fSmrg info->BiosTable.short_mem_offset += 1672209ff23fSmrg RADEON_BIOS8(info->BiosTable.short_mem_offset - 3); 1673209ff23fSmrg } 1674209ff23fSmrg if (info->BiosTable.rr2_offset) { 1675209ff23fSmrg info->BiosTable.rr3_offset = info->BiosTable.rr2_offset; 1676209ff23fSmrg if (info->BiosTable.rr3_offset) { 1677209ff23fSmrg while ((val = RADEON_BIOS8(info->BiosTable.rr3_offset + 1)) != 0) { 1678209ff23fSmrg if (val & 0x40) 1679209ff23fSmrg info->BiosTable.rr3_offset += 10; 1680209ff23fSmrg else if (val & 0x80) 1681209ff23fSmrg info->BiosTable.rr3_offset += 4; 1682209ff23fSmrg else 1683209ff23fSmrg info->BiosTable.rr3_offset += 6; 1684209ff23fSmrg } 1685209ff23fSmrg info->BiosTable.rr3_offset += 2; 1686209ff23fSmrg } 1687209ff23fSmrg } 1688209ff23fSmrg 1689209ff23fSmrg if (info->BiosTable.rr3_offset) { 1690209ff23fSmrg info->BiosTable.rr4_offset = info->BiosTable.rr3_offset; 1691209ff23fSmrg if (info->BiosTable.rr4_offset) { 1692209ff23fSmrg while ((val = RADEON_BIOS8(info->BiosTable.rr4_offset + 1)) != 0) { 1693209ff23fSmrg if (val & 0x40) 1694209ff23fSmrg info->BiosTable.rr4_offset += 10; 1695209ff23fSmrg else if (val & 0x80) 1696209ff23fSmrg info->BiosTable.rr4_offset += 4; 1697209ff23fSmrg else 1698209ff23fSmrg info->BiosTable.rr4_offset += 6; 1699209ff23fSmrg } 1700209ff23fSmrg info->BiosTable.rr4_offset += 2; 1701209ff23fSmrg } 1702209ff23fSmrg } 1703209ff23fSmrg 1704209ff23fSmrg if (info->BiosTable.rr3_offset + 1 == info->BiosTable.pll_offset) { 1705209ff23fSmrg info->BiosTable.rr3_offset = 0; 1706209ff23fSmrg info->BiosTable.rr4_offset = 0; 1707209ff23fSmrg } 1708209ff23fSmrg 1709209ff23fSmrg return TRUE; 1710209ff23fSmrg 1711209ff23fSmrg } 1712209ff23fSmrg } 1713209ff23fSmrg} 1714209ff23fSmrg 1715209ff23fSmrgstatic void 1716209ff23fSmrgRADEONRestoreBIOSRegBlock(ScrnInfoPtr pScrn, uint16_t table_offset) 1717209ff23fSmrg{ 1718209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1719209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1720209ff23fSmrg uint16_t offset = table_offset; 1721209ff23fSmrg uint16_t value, flag, index, count; 1722209ff23fSmrg uint32_t andmask, ormask, val, channel_complete_mask; 1723209ff23fSmrg uint8_t command; 1724209ff23fSmrg 1725209ff23fSmrg if (offset == 0) 1726209ff23fSmrg return; 1727209ff23fSmrg 1728209ff23fSmrg while ((value = RADEON_BIOS16(offset)) != 0) { 1729209ff23fSmrg flag = value & RADEON_TABLE_ENTRY_FLAG_MASK; 1730209ff23fSmrg index = value & RADEON_TABLE_ENTRY_INDEX_MASK; 1731209ff23fSmrg command = value & RADEON_TABLE_ENTRY_COMMAND_MASK; 1732209ff23fSmrg 1733209ff23fSmrg offset += 2; 1734209ff23fSmrg 1735209ff23fSmrg switch (flag) { 1736209ff23fSmrg case RADEON_TABLE_FLAG_WRITE_INDEXED: 1737209ff23fSmrg val = RADEON_BIOS32(offset); 1738209ff23fSmrg ErrorF("WRITE INDEXED: 0x%x 0x%x\n", 1739209ff23fSmrg index, (unsigned)val); 1740209ff23fSmrg OUTREG(RADEON_MM_INDEX, index); 1741209ff23fSmrg OUTREG(RADEON_MM_DATA, val); 1742209ff23fSmrg offset += 4; 1743209ff23fSmrg break; 1744209ff23fSmrg 1745209ff23fSmrg case RADEON_TABLE_FLAG_WRITE_DIRECT: 1746209ff23fSmrg val = RADEON_BIOS32(offset); 1747209ff23fSmrg ErrorF("WRITE DIRECT: 0x%x 0x%x\n", index, (unsigned)val); 1748209ff23fSmrg OUTREG(index, val); 1749209ff23fSmrg offset += 4; 1750209ff23fSmrg break; 1751209ff23fSmrg 1752209ff23fSmrg case RADEON_TABLE_FLAG_MASK_INDEXED: 1753209ff23fSmrg andmask = RADEON_BIOS32(offset); 1754209ff23fSmrg offset += 4; 1755209ff23fSmrg ormask = RADEON_BIOS32(offset); 1756209ff23fSmrg offset += 4; 1757209ff23fSmrg ErrorF("MASK INDEXED: 0x%x 0x%x 0x%x\n", 1758209ff23fSmrg index, (unsigned)andmask, (unsigned)ormask); 1759209ff23fSmrg OUTREG(RADEON_MM_INDEX, index); 1760209ff23fSmrg val = INREG(RADEON_MM_DATA); 1761209ff23fSmrg val = (val & andmask) | ormask; 1762209ff23fSmrg OUTREG(RADEON_MM_DATA, val); 1763209ff23fSmrg break; 1764209ff23fSmrg 1765209ff23fSmrg case RADEON_TABLE_FLAG_MASK_DIRECT: 1766209ff23fSmrg andmask = RADEON_BIOS32(offset); 1767209ff23fSmrg offset += 4; 1768209ff23fSmrg ormask = RADEON_BIOS32(offset); 1769209ff23fSmrg offset += 4; 1770209ff23fSmrg ErrorF("MASK DIRECT: 0x%x 0x%x 0x%x\n", 1771209ff23fSmrg index, (unsigned)andmask, (unsigned)ormask); 1772209ff23fSmrg val = INREG(index); 1773209ff23fSmrg val = (val & andmask) | ormask; 1774209ff23fSmrg OUTREG(index, val); 1775209ff23fSmrg break; 1776209ff23fSmrg 1777209ff23fSmrg case RADEON_TABLE_FLAG_DELAY: 1778209ff23fSmrg count = RADEON_BIOS16(offset); 1779209ff23fSmrg ErrorF("delay: %d\n", count); 1780209ff23fSmrg usleep(count); 1781209ff23fSmrg offset += 2; 1782209ff23fSmrg break; 1783209ff23fSmrg 1784209ff23fSmrg case RADEON_TABLE_FLAG_SCOMMAND: 1785209ff23fSmrg ErrorF("SCOMMAND 0x%x\n", command); 1786209ff23fSmrg switch (command) { 1787209ff23fSmrg case RADEON_TABLE_SCOMMAND_WAIT_MC_BUSY_MASK: 1788209ff23fSmrg count = RADEON_BIOS16(offset); 1789209ff23fSmrg ErrorF("SCOMMAND_WAIT_MC_BUSY_MASK %d\n", count); 1790209ff23fSmrg while (count--) { 1791209ff23fSmrg if (!(INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & 1792209ff23fSmrg RADEON_MC_BUSY)) 1793209ff23fSmrg break; 1794209ff23fSmrg } 1795209ff23fSmrg break; 1796209ff23fSmrg 1797209ff23fSmrg case RADEON_TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE: 1798209ff23fSmrg count = RADEON_BIOS16(offset); 1799209ff23fSmrg ErrorF("SCOMMAND_WAIT_MEM_PWRUP_COMPLETE %d\n", count); 1800209ff23fSmrg /* may need to take into account how many memory channels 1801209ff23fSmrg * each card has 1802209ff23fSmrg */ 1803209ff23fSmrg if (IS_R300_VARIANT) 1804209ff23fSmrg channel_complete_mask = R300_MEM_PWRUP_COMPLETE; 1805209ff23fSmrg else 1806209ff23fSmrg channel_complete_mask = RADEON_MEM_PWRUP_COMPLETE; 1807209ff23fSmrg while (count--) { 1808209ff23fSmrg /* XXX: may need indexed access */ 1809209ff23fSmrg if ((INREG(RADEON_MEM_STR_CNTL) & 1810209ff23fSmrg channel_complete_mask) == 1811209ff23fSmrg channel_complete_mask) 1812209ff23fSmrg break; 1813209ff23fSmrg } 1814209ff23fSmrg break; 1815209ff23fSmrg 1816209ff23fSmrg } 1817209ff23fSmrg offset += 2; 1818209ff23fSmrg break; 1819209ff23fSmrg } 1820209ff23fSmrg } 1821209ff23fSmrg} 1822209ff23fSmrg 1823209ff23fSmrgstatic void 1824209ff23fSmrgRADEONRestoreBIOSMemBlock(ScrnInfoPtr pScrn, uint16_t table_offset) 1825209ff23fSmrg{ 1826209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1827209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1828209ff23fSmrg uint16_t offset = table_offset; 1829209ff23fSmrg uint16_t count; 1830209ff23fSmrg uint32_t ormask, val, channel_complete_mask; 1831209ff23fSmrg uint8_t index; 1832209ff23fSmrg 1833209ff23fSmrg if (offset == 0) 1834209ff23fSmrg return; 1835209ff23fSmrg 1836209ff23fSmrg while ((index = RADEON_BIOS8(offset)) != 0xff) { 1837209ff23fSmrg offset++; 1838209ff23fSmrg if (index == 0x0f) { 1839209ff23fSmrg count = 20000; 1840209ff23fSmrg ErrorF("MEM_WAIT_MEM_PWRUP_COMPLETE %d\n", count); 1841209ff23fSmrg /* may need to take into account how many memory channels 1842209ff23fSmrg * each card has 1843209ff23fSmrg */ 1844209ff23fSmrg if (IS_R300_VARIANT) 1845209ff23fSmrg channel_complete_mask = R300_MEM_PWRUP_COMPLETE; 1846209ff23fSmrg else 1847209ff23fSmrg channel_complete_mask = RADEON_MEM_PWRUP_COMPLETE; 1848209ff23fSmrg while (count--) { 1849209ff23fSmrg /* XXX: may need indexed access */ 1850209ff23fSmrg if ((INREG(RADEON_MEM_STR_CNTL) & 1851209ff23fSmrg channel_complete_mask) == 1852209ff23fSmrg channel_complete_mask) 1853209ff23fSmrg break; 1854209ff23fSmrg } 1855209ff23fSmrg } else { 1856209ff23fSmrg ormask = RADEON_BIOS16(offset); 1857209ff23fSmrg offset += 2; 1858209ff23fSmrg 1859209ff23fSmrg ErrorF("INDEX RADEON_MEM_SDRAM_MODE_REG %x %x\n", 1860209ff23fSmrg RADEON_SDRAM_MODE_MASK, (unsigned)ormask); 1861209ff23fSmrg 1862209ff23fSmrg /* can this use direct access? */ 1863209ff23fSmrg OUTREG(RADEON_MM_INDEX, RADEON_MEM_SDRAM_MODE_REG); 1864209ff23fSmrg val = INREG(RADEON_MM_DATA); 1865209ff23fSmrg val = (val & RADEON_SDRAM_MODE_MASK) | ormask; 1866209ff23fSmrg OUTREG(RADEON_MM_DATA, val); 1867209ff23fSmrg 1868209ff23fSmrg ormask = (uint32_t)index << 24; 1869209ff23fSmrg 1870209ff23fSmrg ErrorF("INDEX RADEON_MEM_SDRAM_MODE_REG %x %x\n", 1871209ff23fSmrg RADEON_B3MEM_RESET_MASK, (unsigned)ormask); 1872209ff23fSmrg 1873209ff23fSmrg /* can this use direct access? */ 1874209ff23fSmrg OUTREG(RADEON_MM_INDEX, RADEON_MEM_SDRAM_MODE_REG); 1875209ff23fSmrg val = INREG(RADEON_MM_DATA); 1876209ff23fSmrg val = (val & RADEON_B3MEM_RESET_MASK) | ormask; 1877209ff23fSmrg OUTREG(RADEON_MM_DATA, val); 1878209ff23fSmrg } 1879209ff23fSmrg } 1880209ff23fSmrg} 1881209ff23fSmrg 1882209ff23fSmrgstatic void 1883209ff23fSmrgRADEONRestoreBIOSPllBlock(ScrnInfoPtr pScrn, uint16_t table_offset) 1884209ff23fSmrg{ 1885209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1886209ff23fSmrg uint16_t offset = table_offset; 1887209ff23fSmrg uint8_t index, shift; 1888209ff23fSmrg uint32_t andmask, ormask, val, clk_pwrmgt_cntl; 1889209ff23fSmrg uint16_t count; 1890209ff23fSmrg 1891209ff23fSmrg if (offset == 0) 1892209ff23fSmrg return; 1893209ff23fSmrg 1894209ff23fSmrg while ((index = RADEON_BIOS8(offset)) != 0) { 1895209ff23fSmrg offset++; 1896209ff23fSmrg 1897209ff23fSmrg switch (index & RADEON_PLL_FLAG_MASK) { 1898209ff23fSmrg case RADEON_PLL_FLAG_WAIT: 1899209ff23fSmrg switch (index & RADEON_PLL_INDEX_MASK) { 1900209ff23fSmrg case RADEON_PLL_WAIT_150MKS: 1901209ff23fSmrg ErrorF("delay: 150 us\n"); 1902209ff23fSmrg usleep(150); 1903209ff23fSmrg break; 1904209ff23fSmrg case RADEON_PLL_WAIT_5MS: 1905209ff23fSmrg ErrorF("delay: 5 ms\n"); 1906209ff23fSmrg usleep(5000); 1907209ff23fSmrg break; 1908209ff23fSmrg 1909209ff23fSmrg case RADEON_PLL_WAIT_MC_BUSY_MASK: 1910209ff23fSmrg count = 1000; 1911209ff23fSmrg ErrorF("PLL_WAIT_MC_BUSY_MASK %d\n", count); 1912209ff23fSmrg while (count--) { 1913209ff23fSmrg if (!(INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & 1914209ff23fSmrg RADEON_MC_BUSY)) 1915209ff23fSmrg break; 1916209ff23fSmrg } 1917209ff23fSmrg break; 1918209ff23fSmrg 1919209ff23fSmrg case RADEON_PLL_WAIT_DLL_READY_MASK: 1920209ff23fSmrg count = 1000; 1921209ff23fSmrg ErrorF("PLL_WAIT_DLL_READY_MASK %d\n", count); 1922209ff23fSmrg while (count--) { 1923209ff23fSmrg if (INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & 1924209ff23fSmrg RADEON_DLL_READY) 1925209ff23fSmrg break; 1926209ff23fSmrg } 1927209ff23fSmrg break; 1928209ff23fSmrg 1929209ff23fSmrg case RADEON_PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24: 1930209ff23fSmrg ErrorF("PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24\n"); 1931209ff23fSmrg clk_pwrmgt_cntl = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL); 1932209ff23fSmrg if (clk_pwrmgt_cntl & RADEON_CG_NO1_DEBUG_0) { 1933209ff23fSmrg val = INPLL(pScrn, RADEON_MCLK_CNTL); 1934209ff23fSmrg /* is this right? */ 1935209ff23fSmrg val = (val & 0xFFFF0000) | 0x1111; /* seems like we should clear these... */ 1936209ff23fSmrg OUTPLL(pScrn, RADEON_MCLK_CNTL, val); 1937209ff23fSmrg usleep(10000); 1938209ff23fSmrg OUTPLL(pScrn, RADEON_CLK_PWRMGT_CNTL, 1939209ff23fSmrg clk_pwrmgt_cntl & ~RADEON_CG_NO1_DEBUG_0); 1940209ff23fSmrg usleep(10000); 1941209ff23fSmrg } 1942209ff23fSmrg break; 1943209ff23fSmrg } 1944209ff23fSmrg break; 1945209ff23fSmrg 1946209ff23fSmrg case RADEON_PLL_FLAG_MASK_BYTE: 1947209ff23fSmrg shift = RADEON_BIOS8(offset) * 8; 1948209ff23fSmrg offset++; 1949209ff23fSmrg 1950209ff23fSmrg andmask = 1951209ff23fSmrg (((uint32_t)RADEON_BIOS8(offset)) << shift) | 1952209ff23fSmrg ~((uint32_t)0xff << shift); 1953209ff23fSmrg offset++; 1954209ff23fSmrg 1955209ff23fSmrg ormask = ((uint32_t)RADEON_BIOS8(offset)) << shift; 1956209ff23fSmrg offset++; 1957209ff23fSmrg 1958209ff23fSmrg ErrorF("PLL_MASK_BYTE 0x%x 0x%x 0x%x 0x%x\n", 1959209ff23fSmrg index, shift, (unsigned)andmask, (unsigned)ormask); 1960209ff23fSmrg val = INPLL(pScrn, index); 1961209ff23fSmrg val = (val & andmask) | ormask; 1962209ff23fSmrg OUTPLL(pScrn, index, val); 1963209ff23fSmrg break; 1964209ff23fSmrg 1965209ff23fSmrg case RADEON_PLL_FLAG_WRITE: 1966209ff23fSmrg val = RADEON_BIOS32(offset); 1967209ff23fSmrg ErrorF("PLL_WRITE 0x%x 0x%x\n", index, (unsigned)val); 1968209ff23fSmrg OUTPLL(pScrn, index, val); 1969209ff23fSmrg offset += 4; 1970209ff23fSmrg break; 1971209ff23fSmrg } 1972209ff23fSmrg } 1973209ff23fSmrg} 1974209ff23fSmrg 1975209ff23fSmrgBool 1976209ff23fSmrgRADEONPostCardFromBIOSTables(ScrnInfoPtr pScrn) 1977209ff23fSmrg{ 1978209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1979209ff23fSmrg 1980209ff23fSmrg if (!info->VBIOS) { 1981209ff23fSmrg return FALSE; 1982209ff23fSmrg } else { 1983209ff23fSmrg if (info->IsAtomBios) { 1984209ff23fSmrg return FALSE; 1985209ff23fSmrg } else { 1986209ff23fSmrg if (info->BiosTable.rr1_offset) { 1987209ff23fSmrg ErrorF("rr1 restore, 0x%x\n", info->BiosTable.rr1_offset); 1988209ff23fSmrg RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr1_offset); 1989209ff23fSmrg } 1990209ff23fSmrg if (info->BiosTable.revision < 0x09) { 1991209ff23fSmrg if (info->BiosTable.pll_offset) { 1992209ff23fSmrg ErrorF("pll restore, 0x%x\n", info->BiosTable.pll_offset); 1993209ff23fSmrg RADEONRestoreBIOSPllBlock(pScrn, info->BiosTable.pll_offset); 1994209ff23fSmrg } 1995209ff23fSmrg if (info->BiosTable.rr2_offset) { 1996209ff23fSmrg ErrorF("rr2 restore, 0x%x\n", info->BiosTable.rr2_offset); 1997209ff23fSmrg RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr2_offset); 1998209ff23fSmrg } 1999209ff23fSmrg if (info->BiosTable.rr4_offset) { 2000209ff23fSmrg ErrorF("rr4 restore, 0x%x\n", info->BiosTable.rr4_offset); 2001209ff23fSmrg RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr4_offset); 2002209ff23fSmrg } 2003209ff23fSmrg if (info->BiosTable.mem_reset_offset) { 2004209ff23fSmrg ErrorF("mem reset restore, 0x%x\n", info->BiosTable.mem_reset_offset); 2005209ff23fSmrg RADEONRestoreBIOSMemBlock(pScrn, info->BiosTable.mem_reset_offset); 2006209ff23fSmrg } 2007209ff23fSmrg if (info->BiosTable.rr3_offset) { 2008209ff23fSmrg ErrorF("rr3 restore, 0x%x\n", info->BiosTable.rr3_offset); 2009209ff23fSmrg RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr3_offset); 2010209ff23fSmrg } 2011209ff23fSmrg if (info->BiosTable.dyn_clk_offset) { 2012209ff23fSmrg ErrorF("dyn_clk restore, 0x%x\n", info->BiosTable.dyn_clk_offset); 2013209ff23fSmrg RADEONRestoreBIOSPllBlock(pScrn, info->BiosTable.dyn_clk_offset); 2014209ff23fSmrg } 2015209ff23fSmrg } 2016209ff23fSmrg } 2017209ff23fSmrg } 2018209ff23fSmrg return TRUE; 2019209ff23fSmrg} 2020