radeon_bios.c revision 2f39173d
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 110ad43ddacSmrg if (info->ChipFamily >= CHIP_FAMILY_RV770) { 111ad43ddacSmrg uint32_t viph_control = INREG(RADEON_VIPH_CONTROL); 112ad43ddacSmrg uint32_t bus_cntl = INREG(RADEON_BUS_CNTL); 113ad43ddacSmrg uint32_t d1vga_control = INREG(AVIVO_D1VGA_CONTROL); 114ad43ddacSmrg uint32_t d2vga_control = INREG(AVIVO_D2VGA_CONTROL); 115ad43ddacSmrg uint32_t vga_render_control = INREG(AVIVO_VGA_RENDER_CONTROL); 116ad43ddacSmrg uint32_t rom_cntl = INREG(R600_ROM_CNTL); 117ad43ddacSmrg uint32_t cg_spll_func_cntl = 0; 118ad43ddacSmrg uint32_t cg_spll_status; 119ad43ddacSmrg 120ad43ddacSmrg /* disable VIP */ 121ad43ddacSmrg OUTREG(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 122ad43ddacSmrg 123ad43ddacSmrg /* enable the rom */ 124ad43ddacSmrg OUTREG(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); 125ad43ddacSmrg 126ad43ddacSmrg /* Disable VGA mode */ 127ad43ddacSmrg OUTREG(AVIVO_D1VGA_CONTROL, (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 128ad43ddacSmrg AVIVO_DVGA_CONTROL_TIMING_SELECT))); 129ad43ddacSmrg OUTREG(AVIVO_D2VGA_CONTROL, (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 130ad43ddacSmrg AVIVO_DVGA_CONTROL_TIMING_SELECT))); 131ad43ddacSmrg OUTREG(AVIVO_VGA_RENDER_CONTROL, (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 132ad43ddacSmrg 133ad43ddacSmrg if (info->ChipFamily == CHIP_FAMILY_RV730) { 134ad43ddacSmrg cg_spll_func_cntl = INREG(R600_CG_SPLL_FUNC_CNTL); 135ad43ddacSmrg 136ad43ddacSmrg /* enable bypass mode */ 137ad43ddacSmrg OUTREG(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl | R600_SPLL_BYPASS_EN)); 138ad43ddacSmrg 139ad43ddacSmrg /* wait for SPLL_CHG_STATUS to change to 1 */ 140ad43ddacSmrg cg_spll_status = 0; 141ad43ddacSmrg while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) 142ad43ddacSmrg cg_spll_status = INREG(R600_CG_SPLL_STATUS); 143ad43ddacSmrg 144ad43ddacSmrg OUTREG(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE)); 145ad43ddacSmrg } else 146ad43ddacSmrg OUTREG(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE)); 147ad43ddacSmrg 148ad43ddacSmrg ret = radeon_read_bios(pScrn); 149ad43ddacSmrg 150ad43ddacSmrg /* restore regs */ 151ad43ddacSmrg if (info->ChipFamily == CHIP_FAMILY_RV730) { 152ad43ddacSmrg OUTREG(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl); 153ad43ddacSmrg 154ad43ddacSmrg /* wait for SPLL_CHG_STATUS to change to 1 */ 155ad43ddacSmrg cg_spll_status = 0; 156ad43ddacSmrg while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) 157ad43ddacSmrg cg_spll_status = INREG(R600_CG_SPLL_STATUS); 158ad43ddacSmrg } 159ad43ddacSmrg OUTREG(RADEON_VIPH_CONTROL, viph_control); 160ad43ddacSmrg OUTREG(RADEON_BUS_CNTL, bus_cntl); 161ad43ddacSmrg OUTREG(AVIVO_D1VGA_CONTROL, d1vga_control); 162ad43ddacSmrg OUTREG(AVIVO_D2VGA_CONTROL, d2vga_control); 163ad43ddacSmrg OUTREG(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 164ad43ddacSmrg OUTREG(R600_ROM_CNTL, rom_cntl); 165ad43ddacSmrg } else if (info->ChipFamily >= CHIP_FAMILY_R600) { 166209ff23fSmrg uint32_t viph_control = INREG(RADEON_VIPH_CONTROL); 167209ff23fSmrg uint32_t bus_cntl = INREG(RADEON_BUS_CNTL); 168209ff23fSmrg uint32_t d1vga_control = INREG(AVIVO_D1VGA_CONTROL); 169209ff23fSmrg uint32_t d2vga_control = INREG(AVIVO_D2VGA_CONTROL); 170209ff23fSmrg uint32_t vga_render_control = INREG(AVIVO_VGA_RENDER_CONTROL); 171209ff23fSmrg uint32_t rom_cntl = INREG(R600_ROM_CNTL); 172209ff23fSmrg uint32_t general_pwrmgt = INREG(R600_GENERAL_PWRMGT); 173209ff23fSmrg uint32_t low_vid_lower_gpio_cntl = INREG(R600_LOW_VID_LOWER_GPIO_CNTL); 174209ff23fSmrg uint32_t medium_vid_lower_gpio_cntl = INREG(R600_MEDIUM_VID_LOWER_GPIO_CNTL); 175209ff23fSmrg uint32_t high_vid_lower_gpio_cntl = INREG(R600_HIGH_VID_LOWER_GPIO_CNTL); 176209ff23fSmrg uint32_t ctxsw_vid_lower_gpio_cntl = INREG(R600_CTXSW_VID_LOWER_GPIO_CNTL); 177209ff23fSmrg uint32_t lower_gpio_enable = INREG(R600_LOWER_GPIO_ENABLE); 178209ff23fSmrg 179209ff23fSmrg /* disable VIP */ 180209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 181209ff23fSmrg 182209ff23fSmrg /* enable the rom */ 183209ff23fSmrg OUTREG(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); 184209ff23fSmrg 185ad43ddacSmrg /* Disable VGA mode */ 186209ff23fSmrg OUTREG(AVIVO_D1VGA_CONTROL, (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 187209ff23fSmrg AVIVO_DVGA_CONTROL_TIMING_SELECT))); 188209ff23fSmrg OUTREG(AVIVO_D2VGA_CONTROL, (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 189209ff23fSmrg AVIVO_DVGA_CONTROL_TIMING_SELECT))); 190209ff23fSmrg OUTREG(AVIVO_VGA_RENDER_CONTROL, (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 191209ff23fSmrg 192209ff23fSmrg OUTREG(R600_ROM_CNTL, ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) | 193209ff23fSmrg (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | 194209ff23fSmrg R600_SCK_OVERWRITE)); 195209ff23fSmrg 196209ff23fSmrg OUTREG(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS)); 197209ff23fSmrg 198209ff23fSmrg OUTREG(R600_LOW_VID_LOWER_GPIO_CNTL, (low_vid_lower_gpio_cntl & ~0x400)); 199209ff23fSmrg 200209ff23fSmrg OUTREG(R600_MEDIUM_VID_LOWER_GPIO_CNTL, (medium_vid_lower_gpio_cntl & ~0x400)); 201209ff23fSmrg 202209ff23fSmrg OUTREG(R600_HIGH_VID_LOWER_GPIO_CNTL, (high_vid_lower_gpio_cntl & ~0x400)); 203209ff23fSmrg 204209ff23fSmrg OUTREG(R600_CTXSW_VID_LOWER_GPIO_CNTL, (ctxsw_vid_lower_gpio_cntl & ~0x400)); 205209ff23fSmrg 206209ff23fSmrg OUTREG(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400)); 207209ff23fSmrg 208209ff23fSmrg ret = radeon_read_bios(pScrn); 209209ff23fSmrg 210209ff23fSmrg /* restore regs */ 211209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, viph_control); 212209ff23fSmrg OUTREG(RADEON_BUS_CNTL, bus_cntl); 213209ff23fSmrg OUTREG(AVIVO_D1VGA_CONTROL, d1vga_control); 214209ff23fSmrg OUTREG(AVIVO_D2VGA_CONTROL, d2vga_control); 215209ff23fSmrg OUTREG(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 216209ff23fSmrg OUTREG(R600_ROM_CNTL, rom_cntl); 217209ff23fSmrg OUTREG(R600_GENERAL_PWRMGT, general_pwrmgt); 218209ff23fSmrg OUTREG(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl); 219209ff23fSmrg OUTREG(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl); 220209ff23fSmrg OUTREG(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl); 221209ff23fSmrg OUTREG(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl); 222209ff23fSmrg OUTREG(R600_LOWER_GPIO_ENABLE, lower_gpio_enable); 223209ff23fSmrg 224209ff23fSmrg } else if (info->ChipFamily >= CHIP_FAMILY_RV515) { 225209ff23fSmrg uint32_t seprom_cntl1 = INREG(RADEON_SEPROM_CNTL1); 226209ff23fSmrg uint32_t viph_control = INREG(RADEON_VIPH_CONTROL); 227209ff23fSmrg uint32_t bus_cntl = INREG(RADEON_BUS_CNTL); 228209ff23fSmrg uint32_t d1vga_control = INREG(AVIVO_D1VGA_CONTROL); 229209ff23fSmrg uint32_t d2vga_control = INREG(AVIVO_D2VGA_CONTROL); 230209ff23fSmrg uint32_t vga_render_control = INREG(AVIVO_VGA_RENDER_CONTROL); 231209ff23fSmrg uint32_t gpiopad_a = INREG(RADEON_GPIOPAD_A); 232209ff23fSmrg uint32_t gpiopad_en = INREG(RADEON_GPIOPAD_EN); 233209ff23fSmrg uint32_t gpiopad_mask = INREG(RADEON_GPIOPAD_MASK); 234209ff23fSmrg 235209ff23fSmrg OUTREG(RADEON_SEPROM_CNTL1, ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | 236209ff23fSmrg (0xc << RADEON_SCK_PRESCALE_SHIFT))); 237209ff23fSmrg 238209ff23fSmrg OUTREG(RADEON_GPIOPAD_A, 0); 239209ff23fSmrg OUTREG(RADEON_GPIOPAD_EN, 0); 240209ff23fSmrg OUTREG(RADEON_GPIOPAD_MASK, 0); 241209ff23fSmrg 242209ff23fSmrg /* disable VIP */ 243209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 244209ff23fSmrg 245209ff23fSmrg /* enable the rom */ 246209ff23fSmrg OUTREG(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); 247209ff23fSmrg 248209ff23fSmrg /* Disable VGA mode */ 249209ff23fSmrg OUTREG(AVIVO_D1VGA_CONTROL, (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 250209ff23fSmrg AVIVO_DVGA_CONTROL_TIMING_SELECT))); 251209ff23fSmrg OUTREG(AVIVO_D2VGA_CONTROL, (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | 252209ff23fSmrg AVIVO_DVGA_CONTROL_TIMING_SELECT))); 253209ff23fSmrg OUTREG(AVIVO_VGA_RENDER_CONTROL, (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); 254209ff23fSmrg 255209ff23fSmrg ret = radeon_read_bios(pScrn); 256209ff23fSmrg 257209ff23fSmrg /* restore regs */ 258209ff23fSmrg OUTREG(RADEON_SEPROM_CNTL1, seprom_cntl1); 259209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, viph_control); 260209ff23fSmrg OUTREG(RADEON_BUS_CNTL, bus_cntl); 261209ff23fSmrg OUTREG(AVIVO_D1VGA_CONTROL, d1vga_control); 262209ff23fSmrg OUTREG(AVIVO_D2VGA_CONTROL, d2vga_control); 263209ff23fSmrg OUTREG(AVIVO_VGA_RENDER_CONTROL, vga_render_control); 264209ff23fSmrg OUTREG(RADEON_GPIOPAD_A, gpiopad_a); 265209ff23fSmrg OUTREG(RADEON_GPIOPAD_EN, gpiopad_en); 266209ff23fSmrg OUTREG(RADEON_GPIOPAD_MASK, gpiopad_mask); 267209ff23fSmrg 268209ff23fSmrg } else { 269209ff23fSmrg uint32_t seprom_cntl1 = INREG(RADEON_SEPROM_CNTL1); 270209ff23fSmrg uint32_t viph_control = INREG(RADEON_VIPH_CONTROL); 271209ff23fSmrg uint32_t bus_cntl = INREG(RADEON_BUS_CNTL); 272209ff23fSmrg uint32_t crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); 273209ff23fSmrg uint32_t crtc2_gen_cntl = 0; 274209ff23fSmrg uint32_t crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); 275209ff23fSmrg uint32_t fp2_gen_cntl = 0; 276209ff23fSmrg 277209ff23fSmrg if (PCI_DEV_DEVICE_ID(info->PciInfo) == PCI_CHIP_RV100_QY) 278209ff23fSmrg fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); 279209ff23fSmrg 280209ff23fSmrg if (pRADEONEnt->HasCRTC2) 281209ff23fSmrg crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); 282209ff23fSmrg 283209ff23fSmrg OUTREG(RADEON_SEPROM_CNTL1, ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | 284209ff23fSmrg (0xc << RADEON_SCK_PRESCALE_SHIFT))); 285209ff23fSmrg 286209ff23fSmrg /* disable VIP */ 287209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); 288209ff23fSmrg 289209ff23fSmrg /* enable the rom */ 290209ff23fSmrg OUTREG(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); 291209ff23fSmrg 292209ff23fSmrg /* Turn off mem requests and CRTC for both controllers */ 293209ff23fSmrg OUTREG(RADEON_CRTC_GEN_CNTL, ((crtc_gen_cntl & ~RADEON_CRTC_EN) | 294209ff23fSmrg (RADEON_CRTC_DISP_REQ_EN_B | 295209ff23fSmrg RADEON_CRTC_EXT_DISP_EN))); 296209ff23fSmrg if (pRADEONEnt->HasCRTC2) 297209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) | 298209ff23fSmrg RADEON_CRTC2_DISP_REQ_EN_B)); 299209ff23fSmrg 300209ff23fSmrg /* Turn off CRTC */ 301209ff23fSmrg OUTREG(RADEON_CRTC_EXT_CNTL, ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) | 302209ff23fSmrg (RADEON_CRTC_SYNC_TRISTAT | 303209ff23fSmrg RADEON_CRTC_DISPLAY_DIS))); 304209ff23fSmrg 305209ff23fSmrg if (PCI_DEV_DEVICE_ID(info->PciInfo) == PCI_CHIP_RV100_QY) 306209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON)); 307209ff23fSmrg 308209ff23fSmrg ret = radeon_read_bios(pScrn); 309209ff23fSmrg 310209ff23fSmrg /* restore regs */ 311209ff23fSmrg OUTREG(RADEON_SEPROM_CNTL1, seprom_cntl1); 312209ff23fSmrg OUTREG(RADEON_VIPH_CONTROL, viph_control); 313209ff23fSmrg OUTREG(RADEON_BUS_CNTL, bus_cntl); 314209ff23fSmrg OUTREG(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); 315209ff23fSmrg if (pRADEONEnt->HasCRTC2) 316209ff23fSmrg OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); 317209ff23fSmrg OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); 318209ff23fSmrg if (PCI_DEV_DEVICE_ID(info->PciInfo) == PCI_CHIP_RV100_QY) 319209ff23fSmrg OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); 320209ff23fSmrg } 321209ff23fSmrg return ret; 322209ff23fSmrg} 323209ff23fSmrg 324b7e1c893SmrgBool 325b7e1c893Smrgradeon_card_posted(ScrnInfoPtr pScrn) 326b7e1c893Smrg{ 327b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 328b7e1c893Smrg unsigned char *RADEONMMIO = info->MMIO; 329b7e1c893Smrg uint32_t reg; 330b7e1c893Smrg 331c503f109Smrg /* first check CRTCs */ 332b7e1c893Smrg if (IS_AVIVO_VARIANT) { 333b7e1c893Smrg reg = INREG(AVIVO_D1CRTC_CONTROL) | INREG(AVIVO_D2CRTC_CONTROL); 334b7e1c893Smrg if (reg & AVIVO_CRTC_EN) 335b7e1c893Smrg return TRUE; 336b7e1c893Smrg } else { 337b7e1c893Smrg reg = INREG(RADEON_CRTC_GEN_CNTL) | INREG(RADEON_CRTC2_GEN_CNTL); 338b7e1c893Smrg if (reg & RADEON_CRTC_EN) 339b7e1c893Smrg return TRUE; 340b7e1c893Smrg } 341b7e1c893Smrg 342c503f109Smrg /* then check MEM_SIZE, in case something turned the crtcs off */ 343c503f109Smrg if (info->ChipFamily >= CHIP_FAMILY_R600) 344c503f109Smrg reg = INREG(R600_CONFIG_MEMSIZE); 345c503f109Smrg else 346c503f109Smrg reg = INREG(RADEON_CONFIG_MEMSIZE); 347c503f109Smrg 348c503f109Smrg if (reg) 349c503f109Smrg return TRUE; 350c503f109Smrg 351b7e1c893Smrg return FALSE; 352b7e1c893Smrg} 353b7e1c893Smrg 354209ff23fSmrg/* Read the Video BIOS block and the FP registers (if applicable). */ 355209ff23fSmrgBool 356209ff23fSmrgRADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) 357209ff23fSmrg{ 358209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 359209ff23fSmrg int tmp; 360209ff23fSmrg unsigned short dptr; 361209ff23fSmrg 362209ff23fSmrg#ifdef XSERVER_LIBPCIACCESS 363209ff23fSmrg int size = info->PciInfo->rom_size > RADEON_VBIOS_SIZE ? info->PciInfo->rom_size : RADEON_VBIOS_SIZE; 3642f39173dSmrg info->VBIOS = malloc(size); 365209ff23fSmrg#else 3662f39173dSmrg info->VBIOS = malloc(RADEON_VBIOS_SIZE); 367209ff23fSmrg#endif 368209ff23fSmrg if (!info->VBIOS) { 369209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 370209ff23fSmrg "Cannot allocate space for hold Video BIOS!\n"); 371209ff23fSmrg return FALSE; 372209ff23fSmrg } else { 373209ff23fSmrg if (pInt10) { 374209ff23fSmrg info->BIOSAddr = pInt10->BIOSseg << 4; 375209ff23fSmrg (void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr), 376209ff23fSmrg RADEON_VBIOS_SIZE); 377b7e1c893Smrg } else if (!radeon_read_bios(pScrn)) 378b7e1c893Smrg (void)radeon_read_disabled_bios(pScrn); 379209ff23fSmrg } 380209ff23fSmrg 381209ff23fSmrg if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { 382209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 383209ff23fSmrg "Unrecognized BIOS signature, BIOS data will not be used\n"); 3842f39173dSmrg free (info->VBIOS); 385209ff23fSmrg info->VBIOS = NULL; 386209ff23fSmrg return FALSE; 387209ff23fSmrg } 388209ff23fSmrg 389209ff23fSmrg /* Verify it's an x86 BIOS not OF firmware, copied from radeonfb */ 390209ff23fSmrg dptr = RADEON_BIOS16(0x18); 391209ff23fSmrg /* If PCI data signature is wrong assume x86 video BIOS anyway */ 392209ff23fSmrg if (RADEON_BIOS32(dptr) != (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) { 393209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 394209ff23fSmrg "ROM PCI data signature incorrect, ignoring\n"); 395209ff23fSmrg } 396209ff23fSmrg else if (info->VBIOS[dptr + 0x14] != 0x0) { 397209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 398209ff23fSmrg "Not an x86 BIOS ROM image, BIOS data will not be used\n"); 3992f39173dSmrg free (info->VBIOS); 400209ff23fSmrg info->VBIOS = NULL; 401209ff23fSmrg return FALSE; 402209ff23fSmrg } 403209ff23fSmrg 404209ff23fSmrg if (info->VBIOS) info->ROMHeaderStart = RADEON_BIOS16(0x48); 405209ff23fSmrg 406209ff23fSmrg if(!info->ROMHeaderStart) { 407209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 408209ff23fSmrg "Invalid ROM pointer, BIOS data will not be used\n"); 4092f39173dSmrg free (info->VBIOS); 410209ff23fSmrg info->VBIOS = NULL; 411209ff23fSmrg return FALSE; 412209ff23fSmrg } 413b7e1c893Smrg 414209ff23fSmrg tmp = info->ROMHeaderStart + 4; 415209ff23fSmrg if ((RADEON_BIOS8(tmp) == 'A' && 416209ff23fSmrg RADEON_BIOS8(tmp+1) == 'T' && 417209ff23fSmrg RADEON_BIOS8(tmp+2) == 'O' && 418209ff23fSmrg RADEON_BIOS8(tmp+3) == 'M') || 419209ff23fSmrg (RADEON_BIOS8(tmp) == 'M' && 420209ff23fSmrg RADEON_BIOS8(tmp+1) == 'O' && 421209ff23fSmrg RADEON_BIOS8(tmp+2) == 'T' && 422209ff23fSmrg RADEON_BIOS8(tmp+3) == 'A')) 423209ff23fSmrg info->IsAtomBios = TRUE; 424209ff23fSmrg else 425209ff23fSmrg info->IsAtomBios = FALSE; 426209ff23fSmrg 427209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s BIOS detected\n", 428209ff23fSmrg info->IsAtomBios ? "ATOM":"Legacy"); 429209ff23fSmrg 430209ff23fSmrg if (info->IsAtomBios) { 431b7e1c893Smrg AtomBiosArgRec atomBiosArg; 432209ff23fSmrg 433b7e1c893Smrg if (RHDAtomBiosFunc(pScrn->scrnIndex, NULL, ATOMBIOS_INIT, &atomBiosArg) 434b7e1c893Smrg == ATOM_SUCCESS) { 435b7e1c893Smrg info->atomBIOS = atomBiosArg.atomhandle; 436b7e1c893Smrg } 437209ff23fSmrg 438b7e1c893Smrg atomBiosArg.fb.start = info->FbFreeStart; 439b7e1c893Smrg atomBiosArg.fb.size = info->FbFreeSize; 440b7e1c893Smrg if (RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, ATOMBIOS_ALLOCATE_FB_SCRATCH, 441209ff23fSmrg &atomBiosArg) == ATOM_SUCCESS) { 442209ff23fSmrg 443209ff23fSmrg info->FbFreeStart = atomBiosArg.fb.start; 444209ff23fSmrg info->FbFreeSize = atomBiosArg.fb.size; 445b7e1c893Smrg } 446b7e1c893Smrg 447b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, GET_DEFAULT_ENGINE_CLOCK, 448b7e1c893Smrg &atomBiosArg); 449b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, GET_DEFAULT_MEMORY_CLOCK, 450b7e1c893Smrg &atomBiosArg); 451b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 452b7e1c893Smrg GET_MAX_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg); 453b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 454b7e1c893Smrg GET_MIN_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg); 455b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 456b7e1c893Smrg GET_MAX_PIXEL_CLOCK_PLL_INPUT, &atomBiosArg); 457b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 458209ff23fSmrg GET_MIN_PIXEL_CLOCK_PLL_INPUT, &atomBiosArg); 459b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 460209ff23fSmrg GET_MAX_PIXEL_CLK, &atomBiosArg); 461b7e1c893Smrg RHDAtomBiosFunc(pScrn->scrnIndex, info->atomBIOS, 462b7e1c893Smrg GET_REF_CLOCK, &atomBiosArg); 463209ff23fSmrg 464209ff23fSmrg info->MasterDataStart = RADEON_BIOS16 (info->ROMHeaderStart + 32); 465209ff23fSmrg } 466b7e1c893Smrg 467b7e1c893Smrg /* We are a bit too quick at using this "unposted" to re-post the 468b7e1c893Smrg * card. This causes some problems with VT switch on some machines, 469b7e1c893Smrg * so let's work around this for now by only POSTing if none of the 470b7e1c893Smrg * CRTCs are enabled 471b7e1c893Smrg */ 472b7e1c893Smrg if ((!radeon_card_posted(pScrn)) && info->VBIOS) { 473b7e1c893Smrg if (info->IsAtomBios) { 474b7e1c893Smrg if (!rhdAtomASICInit(info->atomBIOS)) 475b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 476b7e1c893Smrg "%s: AsicInit failed.\n",__func__); 477b7e1c893Smrg } else { 478209ff23fSmrg#if 0 479b7e1c893Smrg /* FIX ME */ 480b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Attempting to POST via legacy BIOS tables\n"); 481209ff23fSmrg RADEONGetBIOSInitTableOffsets(pScrn); 482209ff23fSmrg RADEONPostCardFromBIOSTables(pScrn); 483b7e1c893Smrg#endif 484209ff23fSmrg } 485209ff23fSmrg } 486b7e1c893Smrg 487209ff23fSmrg return TRUE; 488209ff23fSmrg} 489209ff23fSmrg 490209ff23fSmrgstatic Bool RADEONGetATOMConnectorInfoFromBIOS (ScrnInfoPtr pScrn) 491209ff23fSmrg{ 492209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 493209ff23fSmrg 494209ff23fSmrg if (!info->VBIOS) return FALSE; 495b7e1c893Smrg 496209ff23fSmrg if (RADEONGetATOMConnectorInfoFromBIOSObject(pScrn)) 497209ff23fSmrg return TRUE; 498209ff23fSmrg 499209ff23fSmrg if (RADEONGetATOMConnectorInfoFromBIOSConnectorTable(pScrn)) 500209ff23fSmrg return TRUE; 501209ff23fSmrg 502209ff23fSmrg return FALSE; 503209ff23fSmrg} 504209ff23fSmrg 505209ff23fSmrgstatic void RADEONApplyLegacyQuirks(ScrnInfoPtr pScrn, int index) 506209ff23fSmrg{ 507209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 508209ff23fSmrg 509b7e1c893Smrg /* XPRESS DDC quirks */ 510209ff23fSmrg if ((info->ChipFamily == CHIP_FAMILY_RS400 || 511209ff23fSmrg info->ChipFamily == CHIP_FAMILY_RS480) && 512209ff23fSmrg info->BiosConnector[index].ddc_i2c.mask_clk_reg == RADEON_GPIO_CRT2_DDC) { 513209ff23fSmrg info->BiosConnector[index].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); 514b7e1c893Smrg } else if ((info->ChipFamily == CHIP_FAMILY_RS400 || 515b7e1c893Smrg info->ChipFamily == CHIP_FAMILY_RS480) && 516b7e1c893Smrg info->BiosConnector[index].ddc_i2c.mask_clk_reg == RADEON_GPIO_MONID) { 517b7e1c893Smrg info->BiosConnector[index].ddc_i2c.valid = TRUE; 518b7e1c893Smrg info->BiosConnector[index].ddc_i2c.mask_clk_mask = (0x20 << 8); 519b7e1c893Smrg info->BiosConnector[index].ddc_i2c.mask_data_mask = 0x80; 520b7e1c893Smrg info->BiosConnector[index].ddc_i2c.a_clk_mask = (0x20 << 8); 521b7e1c893Smrg info->BiosConnector[index].ddc_i2c.a_data_mask = 0x80; 522b7e1c893Smrg info->BiosConnector[index].ddc_i2c.put_clk_mask = (0x20 << 8); 523b7e1c893Smrg info->BiosConnector[index].ddc_i2c.put_data_mask = 0x80; 524b7e1c893Smrg info->BiosConnector[index].ddc_i2c.get_clk_mask = (0x20 << 8); 525b7e1c893Smrg info->BiosConnector[index].ddc_i2c.get_data_mask = 0x80; 526b7e1c893Smrg info->BiosConnector[index].ddc_i2c.mask_clk_reg = RADEON_GPIOPAD_MASK; 527b7e1c893Smrg info->BiosConnector[index].ddc_i2c.mask_data_reg = RADEON_GPIOPAD_MASK; 528b7e1c893Smrg info->BiosConnector[index].ddc_i2c.a_clk_reg = RADEON_GPIOPAD_A; 529b7e1c893Smrg info->BiosConnector[index].ddc_i2c.a_data_reg = RADEON_GPIOPAD_A; 530b7e1c893Smrg info->BiosConnector[index].ddc_i2c.put_clk_reg = RADEON_GPIOPAD_EN; 531b7e1c893Smrg info->BiosConnector[index].ddc_i2c.put_data_reg = RADEON_GPIOPAD_EN; 532b7e1c893Smrg info->BiosConnector[index].ddc_i2c.get_clk_reg = RADEON_LCD_GPIO_Y_REG; 533b7e1c893Smrg info->BiosConnector[index].ddc_i2c.get_data_reg = RADEON_LCD_GPIO_Y_REG; 534209ff23fSmrg } 535209ff23fSmrg 536ad43ddacSmrg /* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */ 537ad43ddacSmrg if ((IS_R300_VARIANT) && 538ad43ddacSmrg info->BiosConnector[index].ddc_i2c.mask_clk_reg == RADEON_GPIO_CRT2_DDC) 539ad43ddacSmrg info->BiosConnector[index].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC); 540ad43ddacSmrg 541209ff23fSmrg /* Certain IBM chipset RN50s have a BIOS reporting two VGAs, 542209ff23fSmrg one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */ 543209ff23fSmrg if (info->Chipset == PCI_CHIP_RN50_515E && 544209ff23fSmrg PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1014) { 545209ff23fSmrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_VGA && 546209ff23fSmrg info->BiosConnector[index].ddc_i2c.mask_clk_reg == RADEON_GPIO_CRT2_DDC) { 547209ff23fSmrg info->BiosConnector[index].valid = FALSE; 548209ff23fSmrg } 549209ff23fSmrg } 550209ff23fSmrg 551b7e1c893Smrg /* X300 card with extra non-existent DVI port */ 552b7e1c893Smrg if (info->Chipset == PCI_CHIP_RV370_5B60 && 553b7e1c893Smrg PCI_SUB_VENDOR_ID(info->PciInfo) == 0x17af && 554b7e1c893Smrg PCI_SUB_DEVICE_ID(info->PciInfo) == 0x201e && 555b7e1c893Smrg index == 2) { 556b7e1c893Smrg if (info->BiosConnector[index].ConnectorType == CONNECTOR_DVI_I) { 557b7e1c893Smrg info->BiosConnector[index].valid = FALSE; 558b7e1c893Smrg } 559b7e1c893Smrg } 560b7e1c893Smrg 561b7e1c893Smrg /* r200 card with primary dac routed to both VGA and DVI - disable load detection 562b7e1c893Smrg * otherwise you end up detecing load if either port is attached 563b7e1c893Smrg */ 564b7e1c893Smrg if (info->Chipset == PCI_CHIP_R200_QL && 565b7e1c893Smrg PCI_SUB_VENDOR_ID(info->PciInfo) == 0x1569 && 566b7e1c893Smrg PCI_SUB_DEVICE_ID(info->PciInfo) == 0x514c && 567b7e1c893Smrg (info->BiosConnector[index].devices & ATOM_DEVICE_CRT1_SUPPORT)) { 568b7e1c893Smrg info->BiosConnector[index].load_detection = FALSE; 569b7e1c893Smrg } 570b7e1c893Smrg 571209ff23fSmrg} 572209ff23fSmrg 573209ff23fSmrgstatic Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) 574209ff23fSmrg{ 575209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 576209ff23fSmrg int offset, i, entry, tmp, tmp0, tmp1; 577209ff23fSmrg RADEONLegacyDDCType DDCType; 578209ff23fSmrg RADEONLegacyConnectorType ConnectorType; 579209ff23fSmrg 580209ff23fSmrg if (!info->VBIOS) return FALSE; 581209ff23fSmrg 582209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x50); 583209ff23fSmrg if (offset) { 584209ff23fSmrg for (i = 0; i < 4; i++) { 585209ff23fSmrg entry = offset + 2 + i*2; 586209ff23fSmrg 587209ff23fSmrg if (!RADEON_BIOS16(entry)) { 588209ff23fSmrg break; 589209ff23fSmrg } 590209ff23fSmrg info->BiosConnector[i].valid = TRUE; 591209ff23fSmrg tmp = RADEON_BIOS16(entry); 592209ff23fSmrg info->BiosConnector[i].ConnectorType = (tmp >> 12) & 0xf; 593209ff23fSmrg ConnectorType = (tmp >> 12) & 0xf; 594209ff23fSmrg switch (ConnectorType) { 595209ff23fSmrg case CONNECTOR_PROPRIETARY_LEGACY: 596b7e1c893Smrg info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_D; 597b7e1c893Smrg if ((tmp >> 4) & 0x1) { 598b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP2_SUPPORT; 599b7e1c893Smrg if (!radeon_add_encoder(pScrn, 600b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 601b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT, 602b7e1c893Smrg 0), 603b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT)) 604b7e1c893Smrg return FALSE; 605b7e1c893Smrg } else { 606b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP1_SUPPORT; 607b7e1c893Smrg if (!radeon_add_encoder(pScrn, 608b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 609b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT, 610b7e1c893Smrg 0), 611b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT)) 612b7e1c893Smrg return FALSE; 613b7e1c893Smrg } 614209ff23fSmrg break; 615209ff23fSmrg case CONNECTOR_CRT_LEGACY: 616209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_VGA; 617b7e1c893Smrg if (tmp & 0x1) { 618b7e1c893Smrg info->BiosConnector[i].load_detection = FALSE; 619b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_CRT2_SUPPORT; 620b7e1c893Smrg if (!radeon_add_encoder(pScrn, 621b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 622b7e1c893Smrg ATOM_DEVICE_CRT2_SUPPORT, 623b7e1c893Smrg 2), 624b7e1c893Smrg ATOM_DEVICE_CRT2_SUPPORT)) 625b7e1c893Smrg return FALSE; 626b7e1c893Smrg } else { 627b7e1c893Smrg info->BiosConnector[i].load_detection = TRUE; 628b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_CRT1_SUPPORT; 629b7e1c893Smrg if (!radeon_add_encoder(pScrn, 630b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 631b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT, 632b7e1c893Smrg 1), 633b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT)) 634b7e1c893Smrg return FALSE; 635b7e1c893Smrg } 636209ff23fSmrg break; 637209ff23fSmrg case CONNECTOR_DVI_I_LEGACY: 638209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_I; 639b7e1c893Smrg if (tmp & 0x1) { 640b7e1c893Smrg info->BiosConnector[i].load_detection = FALSE; 641b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_CRT2_SUPPORT; 642b7e1c893Smrg if (!radeon_add_encoder(pScrn, 643b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 644b7e1c893Smrg ATOM_DEVICE_CRT2_SUPPORT, 645b7e1c893Smrg 2), 646b7e1c893Smrg ATOM_DEVICE_CRT2_SUPPORT)) 647b7e1c893Smrg return FALSE; 648b7e1c893Smrg } else { 649b7e1c893Smrg info->BiosConnector[i].load_detection = TRUE; 650b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_CRT1_SUPPORT; 651b7e1c893Smrg if (!radeon_add_encoder(pScrn, 652b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 653b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT, 654b7e1c893Smrg 1), 655b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT)) 656b7e1c893Smrg return FALSE; 657b7e1c893Smrg } 658b7e1c893Smrg if ((tmp >> 4) & 0x1) { 659b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP2_SUPPORT; 660b7e1c893Smrg if (!radeon_add_encoder(pScrn, 661b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 662b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT, 663b7e1c893Smrg 0), 664b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT)) 665b7e1c893Smrg return FALSE; 666b7e1c893Smrg } else { 667b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP1_SUPPORT; 668b7e1c893Smrg if (!radeon_add_encoder(pScrn, 669b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 670b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT, 671b7e1c893Smrg 0), 672b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT)) 673b7e1c893Smrg return FALSE; 674b7e1c893Smrg } 675209ff23fSmrg break; 676209ff23fSmrg case CONNECTOR_DVI_D_LEGACY: 677209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_DVI_D; 678b7e1c893Smrg if ((tmp >> 4) & 0x1) { 679b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP2_SUPPORT; 680b7e1c893Smrg if (!radeon_add_encoder(pScrn, 681b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 682b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT, 683b7e1c893Smrg 0), 684b7e1c893Smrg ATOM_DEVICE_DFP2_SUPPORT)) 685b7e1c893Smrg return FALSE; 686b7e1c893Smrg } else { 687b7e1c893Smrg info->BiosConnector[i].devices |= ATOM_DEVICE_DFP1_SUPPORT; 688b7e1c893Smrg if (!radeon_add_encoder(pScrn, 689b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 690b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT, 691b7e1c893Smrg 0), 692b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT)) 693b7e1c893Smrg return FALSE; 694b7e1c893Smrg } 695209ff23fSmrg break; 696209ff23fSmrg case CONNECTOR_CTV_LEGACY: 697209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_CTV; 698b7e1c893Smrg info->BiosConnector[i].load_detection = FALSE; 699b7e1c893Smrg info->BiosConnector[i].devices = ATOM_DEVICE_TV1_SUPPORT; 700b7e1c893Smrg if (!radeon_add_encoder(pScrn, 701b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 702b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT, 703b7e1c893Smrg 2), 704b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT)) 705b7e1c893Smrg return FALSE; 706209ff23fSmrg break; 707209ff23fSmrg case CONNECTOR_STV_LEGACY: 708209ff23fSmrg info->BiosConnector[i].ConnectorType = CONNECTOR_STV; 709b7e1c893Smrg info->BiosConnector[i].load_detection = FALSE; 710b7e1c893Smrg info->BiosConnector[i].devices = ATOM_DEVICE_TV1_SUPPORT; 711b7e1c893Smrg if (!radeon_add_encoder(pScrn, 712b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 713b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT, 714b7e1c893Smrg 2), 715b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT)) 716b7e1c893Smrg return FALSE; 717209ff23fSmrg break; 718209ff23fSmrg default: 719209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown Connector Type: %d\n", ConnectorType); 720209ff23fSmrg info->BiosConnector[i].valid = FALSE; 721209ff23fSmrg break; 722209ff23fSmrg } 723209ff23fSmrg 724209ff23fSmrg info->BiosConnector[i].ddc_i2c.valid = FALSE; 725209ff23fSmrg 726209ff23fSmrg DDCType = (tmp >> 8) & 0xf; 727209ff23fSmrg switch (DDCType) { 728209ff23fSmrg case DDC_MONID: 729209ff23fSmrg info->BiosConnector[i].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); 730209ff23fSmrg break; 731209ff23fSmrg case DDC_DVI: 732209ff23fSmrg info->BiosConnector[i].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC); 733209ff23fSmrg break; 734209ff23fSmrg case DDC_VGA: 735209ff23fSmrg info->BiosConnector[i].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC); 736209ff23fSmrg break; 737209ff23fSmrg case DDC_CRT2: 738209ff23fSmrg info->BiosConnector[i].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); 739209ff23fSmrg break; 740209ff23fSmrg default: 741209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown DDC Type: %d\n", DDCType); 742209ff23fSmrg break; 743209ff23fSmrg } 744209ff23fSmrg 745209ff23fSmrg RADEONApplyLegacyQuirks(pScrn, i); 746209ff23fSmrg 747209ff23fSmrg } 748209ff23fSmrg } else { 749209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n"); 750209ff23fSmrg 751209ff23fSmrg /* old radeons and r128 didn't use connector tables you just check 752209ff23fSmrg * for LVDS, DVI, TV, etc. tables 753209ff23fSmrg */ 754209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x34); 755209ff23fSmrg if (offset) { 756209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 757209ff23fSmrg "Found DFP table, assuming DVI connector\n"); 758209ff23fSmrg info->BiosConnector[0].valid = TRUE; 759209ff23fSmrg info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I; 760b7e1c893Smrg info->BiosConnector[0].load_detection = TRUE; 761209ff23fSmrg info->BiosConnector[0].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC); 762b7e1c893Smrg info->BiosConnector[0].devices = ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_DFP1_SUPPORT; 763b7e1c893Smrg if (!radeon_add_encoder(pScrn, 764b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 765b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT, 766b7e1c893Smrg 0), 767b7e1c893Smrg ATOM_DEVICE_DFP1_SUPPORT)) 768b7e1c893Smrg return FALSE; 769b7e1c893Smrg if (!radeon_add_encoder(pScrn, 770b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 771b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT, 772b7e1c893Smrg 1), 773b7e1c893Smrg ATOM_DEVICE_CRT1_SUPPORT)) 774b7e1c893Smrg return FALSE; 775209ff23fSmrg } else 776209ff23fSmrg return FALSE; 777209ff23fSmrg } 778209ff23fSmrg 779209ff23fSmrg /* check LVDS table */ 780b7e1c893Smrg /* IGP can be mobile or desktop so check the connectors */ 781b7e1c893Smrg if (info->IsMobility || info->IsIGP) { 782209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x40); 783209ff23fSmrg if (offset) { 784209ff23fSmrg info->BiosConnector[4].valid = TRUE; 785209ff23fSmrg info->BiosConnector[4].ConnectorType = CONNECTOR_LVDS; 786209ff23fSmrg info->BiosConnector[4].ddc_i2c.valid = FALSE; 787209ff23fSmrg 788b7e1c893Smrg info->BiosConnector[4].devices = ATOM_DEVICE_LCD1_SUPPORT; 789b7e1c893Smrg if (!radeon_add_encoder(pScrn, 790b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 791b7e1c893Smrg ATOM_DEVICE_LCD1_SUPPORT, 792b7e1c893Smrg 0), 793b7e1c893Smrg ATOM_DEVICE_LCD1_SUPPORT)) 794b7e1c893Smrg return FALSE; 795b7e1c893Smrg 796209ff23fSmrg tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42); 797209ff23fSmrg if (tmp) { 798209ff23fSmrg tmp0 = RADEON_BIOS16(tmp + 0x15); 799209ff23fSmrg if (tmp0) { 800209ff23fSmrg tmp1 = RADEON_BIOS8(tmp0+2) & 0x07; 801209ff23fSmrg if (tmp1) { 802209ff23fSmrg DDCType = tmp1; 803209ff23fSmrg switch (DDCType) { 804b7e1c893Smrg case DDC_NONE_DETECTED: 805b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DDC for LCD\n"); 806b7e1c893Smrg break; 807209ff23fSmrg case DDC_MONID: 808209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); 809209ff23fSmrg break; 810209ff23fSmrg case DDC_DVI: 811209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC); 812209ff23fSmrg break; 813209ff23fSmrg case DDC_VGA: 814209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC); 815209ff23fSmrg break; 816209ff23fSmrg case DDC_CRT2: 817209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); 818209ff23fSmrg break; 819209ff23fSmrg case DDC_LCD: 820209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_LCD_GPIO_MASK); 821b7e1c893Smrg info->BiosConnector[4].ddc_i2c.mask_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 822b7e1c893Smrg info->BiosConnector[4].ddc_i2c.mask_data_mask = RADEON_BIOS32(tmp0 + 0x07); 823b7e1c893Smrg info->BiosConnector[4].ddc_i2c.a_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 824b7e1c893Smrg info->BiosConnector[4].ddc_i2c.a_data_mask = RADEON_BIOS32(tmp0 + 0x07); 825209ff23fSmrg info->BiosConnector[4].ddc_i2c.put_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 826209ff23fSmrg info->BiosConnector[4].ddc_i2c.put_data_mask = RADEON_BIOS32(tmp0 + 0x07); 827209ff23fSmrg info->BiosConnector[4].ddc_i2c.get_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 828209ff23fSmrg info->BiosConnector[4].ddc_i2c.get_data_mask = RADEON_BIOS32(tmp0 + 0x07); 829209ff23fSmrg break; 830209ff23fSmrg case DDC_GPIO: 831209ff23fSmrg info->BiosConnector[4].ddc_i2c = legacy_setup_i2c_bus(RADEON_MDGPIO_EN_REG); 832b7e1c893Smrg info->BiosConnector[4].ddc_i2c.mask_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 833b7e1c893Smrg info->BiosConnector[4].ddc_i2c.mask_data_mask = RADEON_BIOS32(tmp0 + 0x07); 834b7e1c893Smrg info->BiosConnector[4].ddc_i2c.a_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 835b7e1c893Smrg info->BiosConnector[4].ddc_i2c.a_data_mask = RADEON_BIOS32(tmp0 + 0x07); 836209ff23fSmrg info->BiosConnector[4].ddc_i2c.put_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 837209ff23fSmrg info->BiosConnector[4].ddc_i2c.put_data_mask = RADEON_BIOS32(tmp0 + 0x07); 838209ff23fSmrg info->BiosConnector[4].ddc_i2c.get_clk_mask = RADEON_BIOS32(tmp0 + 0x03); 839209ff23fSmrg info->BiosConnector[4].ddc_i2c.get_data_mask = RADEON_BIOS32(tmp0 + 0x07); 840209ff23fSmrg break; 841209ff23fSmrg default: 842209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown DDC Type: %d\n", DDCType); 843209ff23fSmrg break; 844209ff23fSmrg } 845209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); 846209ff23fSmrg } 847209ff23fSmrg } 848b7e1c893Smrg } else 849209ff23fSmrg info->BiosConnector[4].ddc_i2c.valid = FALSE; 850209ff23fSmrg } 851209ff23fSmrg } 852209ff23fSmrg 853209ff23fSmrg /* check TV table */ 854209ff23fSmrg if (info->InternalTVOut) { 855209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); 856209ff23fSmrg if (offset) { 857209ff23fSmrg if (RADEON_BIOS8(offset + 6) == 'T') { 858209ff23fSmrg info->BiosConnector[5].valid = TRUE; 859209ff23fSmrg /* assume s-video for now */ 860209ff23fSmrg info->BiosConnector[5].ConnectorType = CONNECTOR_STV; 861b7e1c893Smrg info->BiosConnector[5].load_detection = FALSE; 862209ff23fSmrg info->BiosConnector[5].ddc_i2c.valid = FALSE; 863b7e1c893Smrg info->BiosConnector[5].devices = ATOM_DEVICE_TV1_SUPPORT; 864b7e1c893Smrg if (!radeon_add_encoder(pScrn, 865b7e1c893Smrg radeon_get_encoder_id_from_supported_device(pScrn, 866b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT, 867b7e1c893Smrg 2), 868b7e1c893Smrg ATOM_DEVICE_TV1_SUPPORT)) 869b7e1c893Smrg return FALSE; 870209ff23fSmrg } 871209ff23fSmrg } 872209ff23fSmrg } 873209ff23fSmrg 874209ff23fSmrg return TRUE; 875209ff23fSmrg} 876209ff23fSmrg 877209ff23fSmrgBool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) 878209ff23fSmrg{ 879209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 880209ff23fSmrg 881209ff23fSmrg if(!info->VBIOS) return FALSE; 882209ff23fSmrg 883209ff23fSmrg if (info->IsAtomBios) 884209ff23fSmrg return RADEONGetATOMConnectorInfoFromBIOS(pScrn); 885209ff23fSmrg else 886209ff23fSmrg return RADEONGetLegacyConnectorInfoFromBIOS(pScrn); 887209ff23fSmrg} 888209ff23fSmrg 889209ff23fSmrgBool RADEONGetTVInfoFromBIOS (xf86OutputPtr output) { 890209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 891209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 892209ff23fSmrg RADEONOutputPrivatePtr radeon_output = output->driver_private; 893b7e1c893Smrg radeon_tvout_ptr tvout = &radeon_output->tvout; 894209ff23fSmrg int offset, refclk, stds; 895209ff23fSmrg 896209ff23fSmrg if (!info->VBIOS) return FALSE; 897209ff23fSmrg 898b7e1c893Smrg if (info->IsAtomBios) 899209ff23fSmrg return RADEONGetATOMTVInfo(output); 900b7e1c893Smrg else { 901209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); 902209ff23fSmrg if (offset) { 903209ff23fSmrg if (RADEON_BIOS8(offset + 6) == 'T') { 904209ff23fSmrg switch (RADEON_BIOS8(offset + 7) & 0xf) { 905209ff23fSmrg case 1: 906b7e1c893Smrg tvout->default_tvStd = TV_STD_NTSC; 907209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC\n"); 908209ff23fSmrg break; 909209ff23fSmrg case 2: 910b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL; 911209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL\n"); 912209ff23fSmrg break; 913209ff23fSmrg case 3: 914b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL_M; 915209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-M\n"); 916209ff23fSmrg break; 917209ff23fSmrg case 4: 918b7e1c893Smrg tvout->default_tvStd = TV_STD_PAL_60; 919209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-60\n"); 920209ff23fSmrg break; 921209ff23fSmrg case 5: 922b7e1c893Smrg tvout->default_tvStd = TV_STD_NTSC_J; 923209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC-J\n"); 924209ff23fSmrg break; 925209ff23fSmrg case 6: 926b7e1c893Smrg tvout->default_tvStd = TV_STD_SCART_PAL; 927209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: SCART-PAL\n"); 928209ff23fSmrg break; 929209ff23fSmrg default: 930b7e1c893Smrg tvout->default_tvStd = TV_STD_NTSC; 931209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unknown TV standard; defaulting to NTSC\n"); 932209ff23fSmrg break; 933209ff23fSmrg } 934b7e1c893Smrg tvout->tvStd = tvout->default_tvStd; 935209ff23fSmrg 936209ff23fSmrg refclk = (RADEON_BIOS8(offset + 9) >> 2) & 0x3; 937209ff23fSmrg if (refclk == 0) 938b7e1c893Smrg tvout->TVRefClk = 29.498928713; /* MHz */ 939209ff23fSmrg else if (refclk == 1) 940b7e1c893Smrg tvout->TVRefClk = 28.636360000; 941209ff23fSmrg else if (refclk == 2) 942b7e1c893Smrg tvout->TVRefClk = 14.318180000; 943209ff23fSmrg else if (refclk == 3) 944b7e1c893Smrg tvout->TVRefClk = 27.000000000; 945209ff23fSmrg 946b7e1c893Smrg tvout->SupportedTVStds = tvout->default_tvStd; 947209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standards supported by chip: "); 948209ff23fSmrg stds = RADEON_BIOS8(offset + 10) & 0x1f; 949209ff23fSmrg if (stds & TV_STD_NTSC) { 950b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_NTSC; 951209ff23fSmrg ErrorF("NTSC "); 952209ff23fSmrg } 953209ff23fSmrg if (stds & TV_STD_PAL) { 954b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL; 955209ff23fSmrg ErrorF("PAL "); 956209ff23fSmrg } 957209ff23fSmrg if (stds & TV_STD_PAL_M) { 958b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL_M; 959209ff23fSmrg ErrorF("PAL-M "); 960209ff23fSmrg } 961209ff23fSmrg if (stds & TV_STD_PAL_60) { 962b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_PAL_60; 963209ff23fSmrg ErrorF("PAL-60 "); 964209ff23fSmrg } 965209ff23fSmrg if (stds & TV_STD_NTSC_J) { 966b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_NTSC_J; 967209ff23fSmrg ErrorF("NTSC-J "); 968209ff23fSmrg } 969209ff23fSmrg if (stds & TV_STD_SCART_PAL) { 970b7e1c893Smrg tvout->SupportedTVStds |= TV_STD_SCART_PAL; 971209ff23fSmrg ErrorF("SCART-PAL"); 972209ff23fSmrg } 973209ff23fSmrg ErrorF("\n"); 974209ff23fSmrg 975209ff23fSmrg return TRUE; 976209ff23fSmrg } 977209ff23fSmrg } 978209ff23fSmrg } 979209ff23fSmrg return FALSE; 980209ff23fSmrg} 981209ff23fSmrg 982209ff23fSmrg/* Read PLL parameters from BIOS block. Default to typical values if there 983209ff23fSmrg is no BIOS. */ 984209ff23fSmrgBool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn) 985209ff23fSmrg{ 986209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 987209ff23fSmrg RADEONPLLPtr pll = &info->pll; 988209ff23fSmrg uint16_t pll_info_block; 989209ff23fSmrg 990209ff23fSmrg if (!info->VBIOS) { 991209ff23fSmrg return FALSE; 992209ff23fSmrg } else { 993209ff23fSmrg if (info->IsAtomBios) { 994ad43ddacSmrg return RADEONGetATOMClockInfo(pScrn); 995209ff23fSmrg } else { 996209ff23fSmrg int rev; 997209ff23fSmrg 998209ff23fSmrg pll_info_block = RADEON_BIOS16 (info->ROMHeaderStart + 0x30); 999209ff23fSmrg 1000209ff23fSmrg rev = RADEON_BIOS8(pll_info_block); 1001209ff23fSmrg 1002209ff23fSmrg pll->reference_freq = RADEON_BIOS16 (pll_info_block + 0x0e); 1003209ff23fSmrg pll->reference_div = RADEON_BIOS16 (pll_info_block + 0x10); 1004209ff23fSmrg pll->pll_out_min = RADEON_BIOS32 (pll_info_block + 0x12); 1005209ff23fSmrg pll->pll_out_max = RADEON_BIOS32 (pll_info_block + 0x16); 1006209ff23fSmrg 1007209ff23fSmrg if (rev > 9) { 1008209ff23fSmrg pll->pll_in_min = RADEON_BIOS32(pll_info_block + 0x36); 1009209ff23fSmrg pll->pll_in_max = RADEON_BIOS32(pll_info_block + 0x3a); 1010209ff23fSmrg } else { 1011209ff23fSmrg pll->pll_in_min = 40; 1012209ff23fSmrg pll->pll_in_max = 500; 1013209ff23fSmrg } 1014209ff23fSmrg 1015209ff23fSmrg pll->xclk = RADEON_BIOS16(pll_info_block + 0x08); 1016209ff23fSmrg 1017b7e1c893Smrg info->sclk = RADEON_BIOS16(pll_info_block + 10) / 100.0; 1018b7e1c893Smrg info->mclk = RADEON_BIOS16(pll_info_block + 8) / 100.0; 1019209ff23fSmrg } 1020209ff23fSmrg 1021209ff23fSmrg if (info->sclk == 0) info->sclk = 200; 1022209ff23fSmrg if (info->mclk == 0) info->mclk = 200; 1023209ff23fSmrg } 1024209ff23fSmrg 1025209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_out_pll: %u, " 1026209ff23fSmrg "max_out_pll: %u, min_in_pll: %u, max_in_pll: %u, xclk: %d, " 1027209ff23fSmrg "sclk: %f, mclk: %f\n", 1028209ff23fSmrg pll->reference_freq, (unsigned)pll->pll_out_min, 1029209ff23fSmrg (unsigned)pll->pll_out_max, (unsigned)pll->pll_in_min, 1030209ff23fSmrg (unsigned)pll->pll_in_max, pll->xclk, info->sclk, info->mclk); 1031209ff23fSmrg 1032209ff23fSmrg return TRUE; 1033209ff23fSmrg} 1034209ff23fSmrg 1035b7e1c893SmrgBool RADEONGetDAC2InfoFromBIOS (ScrnInfoPtr pScrn, radeon_tvdac_ptr tvdac) 1036209ff23fSmrg{ 1037209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1038209ff23fSmrg int offset, rev, bg, dac; 1039209ff23fSmrg 1040209ff23fSmrg if (!info->VBIOS) return FALSE; 1041209ff23fSmrg 1042209ff23fSmrg if (xf86ReturnOptValBool(info->Options, OPTION_DEFAULT_TVDAC_ADJ, FALSE)) 1043209ff23fSmrg return FALSE; 1044209ff23fSmrg 1045209ff23fSmrg if (info->IsAtomBios) { 1046209ff23fSmrg /* not implemented yet */ 1047209ff23fSmrg return FALSE; 1048209ff23fSmrg } else { 1049209ff23fSmrg /* first check TV table */ 1050209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); 1051209ff23fSmrg if (offset) { 1052209ff23fSmrg rev = RADEON_BIOS8(offset + 0x3); 1053209ff23fSmrg if (rev > 4) { 1054209ff23fSmrg bg = RADEON_BIOS8(offset + 0xc) & 0xf; 1055209ff23fSmrg dac = RADEON_BIOS8(offset + 0xd) & 0xf; 1056b7e1c893Smrg tvdac->ps2_tvdac_adj = (bg << 16) | (dac << 20); 1057209ff23fSmrg 1058209ff23fSmrg bg = RADEON_BIOS8(offset + 0xe) & 0xf; 1059209ff23fSmrg dac = RADEON_BIOS8(offset + 0xf) & 0xf; 1060b7e1c893Smrg tvdac->pal_tvdac_adj = (bg << 16) | (dac << 20); 1061209ff23fSmrg 1062209ff23fSmrg bg = RADEON_BIOS8(offset + 0x10) & 0xf; 1063209ff23fSmrg dac = RADEON_BIOS8(offset + 0x11) & 0xf; 1064b7e1c893Smrg tvdac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); 1065209ff23fSmrg 1066209ff23fSmrg return TRUE; 1067209ff23fSmrg } else if (rev > 1) { 1068209ff23fSmrg bg = RADEON_BIOS8(offset + 0xc) & 0xf; 1069209ff23fSmrg dac = (RADEON_BIOS8(offset + 0xc) >> 4) & 0xf; 1070b7e1c893Smrg tvdac->ps2_tvdac_adj = (bg << 16) | (dac << 20); 1071209ff23fSmrg 1072209ff23fSmrg bg = RADEON_BIOS8(offset + 0xd) & 0xf; 1073209ff23fSmrg dac = (RADEON_BIOS8(offset + 0xd) >> 4) & 0xf; 1074b7e1c893Smrg tvdac->pal_tvdac_adj = (bg << 16) | (dac << 20); 1075209ff23fSmrg 1076209ff23fSmrg bg = RADEON_BIOS8(offset + 0xe) & 0xf; 1077209ff23fSmrg dac = (RADEON_BIOS8(offset + 0xe) >> 4) & 0xf; 1078b7e1c893Smrg tvdac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); 1079209ff23fSmrg 1080209ff23fSmrg return TRUE; 1081209ff23fSmrg } 1082209ff23fSmrg } 1083209ff23fSmrg /* then check CRT table */ 1084209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x60); 1085209ff23fSmrg if (offset) { 1086209ff23fSmrg rev = RADEON_BIOS8(offset) & 0x3; 1087209ff23fSmrg if (rev < 2) { 1088209ff23fSmrg bg = RADEON_BIOS8(offset + 0x3) & 0xf; 1089209ff23fSmrg dac = (RADEON_BIOS8(offset + 0x3) >> 4) & 0xf; 1090b7e1c893Smrg tvdac->ps2_tvdac_adj = (bg << 16) | (dac << 20); 1091b7e1c893Smrg tvdac->pal_tvdac_adj = tvdac->ps2_tvdac_adj; 1092b7e1c893Smrg tvdac->ntsc_tvdac_adj = tvdac->ps2_tvdac_adj; 1093209ff23fSmrg 1094209ff23fSmrg return TRUE; 1095209ff23fSmrg } else { 1096209ff23fSmrg bg = RADEON_BIOS8(offset + 0x4) & 0xf; 1097209ff23fSmrg dac = RADEON_BIOS8(offset + 0x5) & 0xf; 1098b7e1c893Smrg tvdac->ps2_tvdac_adj = (bg << 16) | (dac << 20); 1099b7e1c893Smrg tvdac->pal_tvdac_adj = tvdac->ps2_tvdac_adj; 1100b7e1c893Smrg tvdac->ntsc_tvdac_adj = tvdac->ps2_tvdac_adj; 1101209ff23fSmrg 1102209ff23fSmrg return TRUE; 1103209ff23fSmrg } 1104209ff23fSmrg } 1105209ff23fSmrg } 1106209ff23fSmrg 1107209ff23fSmrg return FALSE; 1108209ff23fSmrg} 1109209ff23fSmrg 1110b7e1c893SmrgBool 1111b7e1c893SmrgRADEONGetLVDSInfoFromBIOS(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds) 1112209ff23fSmrg{ 1113209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1114b7e1c893Smrg radeon_native_mode_ptr native_mode = &lvds->native_mode; 1115209ff23fSmrg unsigned long tmp, i; 1116209ff23fSmrg 1117b7e1c893Smrg if (!info->VBIOS) 1118b7e1c893Smrg return FALSE; 1119209ff23fSmrg 1120b7e1c893Smrg if (!info->IsAtomBios) { 1121209ff23fSmrg tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x40); 1122209ff23fSmrg 1123209ff23fSmrg if (!tmp) { 1124209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1125209ff23fSmrg "No Panel Info Table found in BIOS!\n"); 1126209ff23fSmrg return FALSE; 1127209ff23fSmrg } else { 1128209ff23fSmrg char stmp[30]; 1129209ff23fSmrg int tmp0; 1130209ff23fSmrg 1131209ff23fSmrg for (i = 0; i < 24; i++) 1132209ff23fSmrg stmp[i] = RADEON_BIOS8(tmp+i+1); 1133209ff23fSmrg stmp[24] = 0; 1134209ff23fSmrg 1135209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1136209ff23fSmrg "Panel ID string: %s\n", stmp); 1137209ff23fSmrg 1138b7e1c893Smrg native_mode->PanelXRes = RADEON_BIOS16(tmp+25); 1139b7e1c893Smrg native_mode->PanelYRes = RADEON_BIOS16(tmp+27); 1140209ff23fSmrg xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n", 1141b7e1c893Smrg native_mode->PanelXRes, native_mode->PanelYRes); 1142b7e1c893Smrg 1143b7e1c893Smrg lvds->PanelPwrDly = RADEON_BIOS16(tmp+44); 1144b7e1c893Smrg if (lvds->PanelPwrDly > 2000 || lvds->PanelPwrDly < 0) 1145b7e1c893Smrg lvds->PanelPwrDly = 2000; 1146209ff23fSmrg 1147209ff23fSmrg /* some panels only work well with certain divider combinations. 1148209ff23fSmrg */ 1149209ff23fSmrg info->RefDivider = RADEON_BIOS16(tmp+46); 1150209ff23fSmrg info->PostDivider = RADEON_BIOS8(tmp+48); 1151209ff23fSmrg info->FeedbackDivider = RADEON_BIOS16(tmp+49); 1152209ff23fSmrg if ((info->RefDivider != 0) && 1153209ff23fSmrg (info->FeedbackDivider > 3)) { 1154209ff23fSmrg info->UseBiosDividers = TRUE; 1155209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1156209ff23fSmrg "BIOS provided dividers will be used.\n"); 1157209ff23fSmrg } 1158209ff23fSmrg 1159209ff23fSmrg /* We don't use a while loop here just in case we have a corrupted BIOS image. 1160209ff23fSmrg The max number of table entries is 23 at present, but may grow in future. 1161209ff23fSmrg To ensure it works with future revisions we loop it to 32. 1162209ff23fSmrg */ 1163209ff23fSmrg for (i = 0; i < 32; i++) { 1164209ff23fSmrg tmp0 = RADEON_BIOS16(tmp+64+i*2); 1165209ff23fSmrg if (tmp0 == 0) break; 1166b7e1c893Smrg if ((RADEON_BIOS16(tmp0) == native_mode->PanelXRes) && 1167b7e1c893Smrg (RADEON_BIOS16(tmp0+2) == native_mode->PanelYRes)) { 1168b7e1c893Smrg native_mode->HBlank = (RADEON_BIOS16(tmp0+17) - 1169b7e1c893Smrg RADEON_BIOS16(tmp0+19)) * 8; 1170b7e1c893Smrg native_mode->HOverPlus = (RADEON_BIOS16(tmp0+21) - 1171b7e1c893Smrg RADEON_BIOS16(tmp0+19) - 1) * 8; 1172b7e1c893Smrg native_mode->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8; 1173b7e1c893Smrg native_mode->VBlank = (RADEON_BIOS16(tmp0+24) - 1174b7e1c893Smrg RADEON_BIOS16(tmp0+26)); 1175b7e1c893Smrg native_mode->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) - 1176b7e1c893Smrg RADEON_BIOS16(tmp0+26)); 1177b7e1c893Smrg native_mode->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800) >> 11); 1178b7e1c893Smrg native_mode->DotClock = RADEON_BIOS16(tmp0+9) * 10; 1179b7e1c893Smrg native_mode->Flags = 0; 1180209ff23fSmrg } 1181209ff23fSmrg } 1182209ff23fSmrg } 1183209ff23fSmrg 1184b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1185b7e1c893Smrg "LVDS Info:\n" 1186b7e1c893Smrg "XRes: %d, YRes: %d, DotClock: %d\n" 1187b7e1c893Smrg "HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n" 1188b7e1c893Smrg "VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n", 1189b7e1c893Smrg native_mode->PanelXRes, native_mode->PanelYRes, native_mode->DotClock, 1190b7e1c893Smrg native_mode->HBlank, native_mode->HOverPlus, native_mode->HSyncWidth, 1191b7e1c893Smrg native_mode->VBlank, native_mode->VOverPlus, native_mode->VSyncWidth); 1192209ff23fSmrg 1193b7e1c893Smrg return TRUE; 1194b7e1c893Smrg } 1195b7e1c893Smrg return FALSE; 1196209ff23fSmrg} 1197209ff23fSmrg 1198b7e1c893Smrgxf86MonPtr RADEONGetHardCodedEDIDFromBIOS (xf86OutputPtr output) 1199209ff23fSmrg{ 1200209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1201b7e1c893Smrg RADEONInfoPtr info = RADEONPTR(pScrn); 1202209ff23fSmrg unsigned long tmp; 1203b7e1c893Smrg unsigned char edid[256]; 1204b7e1c893Smrg xf86MonPtr mon = NULL; 1205209ff23fSmrg 1206b7e1c893Smrg if (!info->VBIOS) 1207b7e1c893Smrg return mon; 1208209ff23fSmrg 1209b7e1c893Smrg if (!info->IsAtomBios) { 1210b7e1c893Smrg tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x4c); 1211b7e1c893Smrg if (tmp) { 1212b7e1c893Smrg memcpy(edid, (unsigned char*)(info->VBIOS + tmp), 256); 1213b7e1c893Smrg if (edid[1] == 0xff) 1214b7e1c893Smrg mon = xf86InterpretEDID(output->scrn->scrnIndex, edid); 1215209ff23fSmrg } 1216209ff23fSmrg } 1217b7e1c893Smrg 1218b7e1c893Smrg return mon; 1219209ff23fSmrg} 1220209ff23fSmrg 1221b7e1c893SmrgBool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn, radeon_tmds_ptr tmds) 1222209ff23fSmrg{ 1223209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1224209ff23fSmrg uint32_t tmp, maxfreq; 1225209ff23fSmrg int i, n; 1226209ff23fSmrg 1227209ff23fSmrg if (!info->VBIOS) return FALSE; 1228209ff23fSmrg 1229209ff23fSmrg if (info->IsAtomBios) { 1230209ff23fSmrg if((tmp = RADEON_BIOS16 (info->MasterDataStart + 18))) { 1231209ff23fSmrg 1232209ff23fSmrg maxfreq = RADEON_BIOS16(tmp+4); 1233b7e1c893Smrg 1234209ff23fSmrg for (i=0; i<4; i++) { 1235b7e1c893Smrg tmds->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*6+6); 1236209ff23fSmrg /* This assumes each field in TMDS_PLL has 6 bit as in R300/R420 */ 1237b7e1c893Smrg tmds->tmds_pll[i].value = ((RADEON_BIOS8(tmp+i*6+8) & 0x3f) | 1238209ff23fSmrg ((RADEON_BIOS8(tmp+i*6+10) & 0x3f)<<6) | 1239209ff23fSmrg ((RADEON_BIOS8(tmp+i*6+9) & 0xf)<<12) | 1240209ff23fSmrg ((RADEON_BIOS8(tmp+i*6+11) & 0xf)<<16)); 1241b7e1c893Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1242b7e1c893Smrg "TMDS PLL from BIOS: %u %x\n", 1243b7e1c893Smrg (unsigned)tmds->tmds_pll[i].freq, 1244b7e1c893Smrg (unsigned)tmds->tmds_pll[i].value); 1245b7e1c893Smrg 1246b7e1c893Smrg if (maxfreq == tmds->tmds_pll[i].freq) { 1247b7e1c893Smrg tmds->tmds_pll[i].freq = 0xffffffff; 1248209ff23fSmrg break; 1249209ff23fSmrg } 1250209ff23fSmrg } 1251209ff23fSmrg return TRUE; 1252209ff23fSmrg } 1253209ff23fSmrg } else { 1254209ff23fSmrg 1255209ff23fSmrg tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x34); 1256209ff23fSmrg if (tmp) { 1257209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1258209ff23fSmrg "DFP table revision: %d\n", RADEON_BIOS8(tmp)); 1259209ff23fSmrg if (RADEON_BIOS8(tmp) == 3) { 1260209ff23fSmrg n = RADEON_BIOS8(tmp + 5) + 1; 1261209ff23fSmrg if (n > 4) n = 4; 1262209ff23fSmrg for (i=0; i<n; i++) { 1263b7e1c893Smrg tmds->tmds_pll[i].value = RADEON_BIOS32(tmp+i*10+0x08); 1264b7e1c893Smrg tmds->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*10+0x10); 1265209ff23fSmrg } 1266209ff23fSmrg return TRUE; 1267209ff23fSmrg } else if (RADEON_BIOS8(tmp) == 4) { 1268209ff23fSmrg int stride = 0; 1269209ff23fSmrg n = RADEON_BIOS8(tmp + 5) + 1; 1270209ff23fSmrg if (n > 4) n = 4; 1271209ff23fSmrg for (i=0; i<n; i++) { 1272b7e1c893Smrg tmds->tmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); 1273b7e1c893Smrg tmds->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); 1274209ff23fSmrg if (i == 0) stride += 10; 1275209ff23fSmrg else stride += 6; 1276209ff23fSmrg } 1277209ff23fSmrg return TRUE; 1278209ff23fSmrg } 1279209ff23fSmrg } 1280209ff23fSmrg } 1281209ff23fSmrg return FALSE; 1282209ff23fSmrg} 1283209ff23fSmrg 1284b7e1c893Smrgstatic RADEONI2CBusRec 1285b7e1c893SmrgRADEONLookupI2CBlock(ScrnInfoPtr pScrn, int id) 1286b7e1c893Smrg{ 1287b7e1c893Smrg RADEONInfoPtr info = RADEONPTR (pScrn); 1288b7e1c893Smrg int offset, blocks, i; 1289b7e1c893Smrg RADEONI2CBusRec i2c; 1290b7e1c893Smrg 1291b7e1c893Smrg memset(&i2c, 0, sizeof(RADEONI2CBusRec)); 1292b7e1c893Smrg i2c.valid = FALSE; 1293b7e1c893Smrg 1294b7e1c893Smrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x70); 1295b7e1c893Smrg if (offset) { 1296b7e1c893Smrg blocks = RADEON_BIOS8(offset + 2); 1297b7e1c893Smrg for (i = 0; i < blocks; i++) { 1298b7e1c893Smrg int i2c_id = RADEON_BIOS8(offset + 3 + (i * 5) + 0); 1299b7e1c893Smrg if (id == i2c_id) { 1300b7e1c893Smrg int clock_shift = RADEON_BIOS8(offset + 3 + (i * 5) + 3); 1301b7e1c893Smrg int data_shift = RADEON_BIOS8(offset + 3 + (i * 5) + 4); 1302b7e1c893Smrg 1303b7e1c893Smrg i2c.mask_clk_mask = (1 << clock_shift); 1304b7e1c893Smrg i2c.mask_data_mask = (1 << data_shift); 1305b7e1c893Smrg i2c.a_clk_mask = (1 << clock_shift); 1306b7e1c893Smrg i2c.a_data_mask = (1 << data_shift); 1307b7e1c893Smrg i2c.put_clk_mask = (1 << clock_shift); 1308b7e1c893Smrg i2c.put_data_mask = (1 << data_shift); 1309b7e1c893Smrg i2c.get_clk_mask = (1 << clock_shift); 1310b7e1c893Smrg i2c.get_data_mask = (1 << data_shift); 1311ad43ddacSmrg i2c.mask_clk_reg = RADEON_GPIOPAD_MASK; 1312ad43ddacSmrg i2c.mask_data_reg = RADEON_GPIOPAD_MASK; 1313ad43ddacSmrg i2c.a_clk_reg = RADEON_GPIOPAD_A; 1314ad43ddacSmrg i2c.a_data_reg = RADEON_GPIOPAD_A; 1315ad43ddacSmrg i2c.put_clk_reg = RADEON_GPIOPAD_EN; 1316ad43ddacSmrg i2c.put_data_reg = RADEON_GPIOPAD_EN; 1317ad43ddacSmrg i2c.get_clk_reg = RADEON_LCD_GPIO_Y_REG; 1318ad43ddacSmrg i2c.get_data_reg = RADEON_LCD_GPIO_Y_REG; 1319b7e1c893Smrg i2c.valid = TRUE; 1320b7e1c893Smrg break; 1321b7e1c893Smrg } 1322b7e1c893Smrg } 1323b7e1c893Smrg } 1324b7e1c893Smrg return i2c; 1325b7e1c893Smrg} 1326b7e1c893Smrg 1327b7e1c893SmrgBool RADEONGetExtTMDSInfoFromBIOS (ScrnInfoPtr pScrn, radeon_dvo_ptr dvo) 1328209ff23fSmrg{ 1329209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1330209ff23fSmrg int offset, table_start, max_freq, gpio_reg, flags; 1331209ff23fSmrg 1332b7e1c893Smrg if (!info->VBIOS) 1333b7e1c893Smrg return FALSE; 1334209ff23fSmrg 1335b7e1c893Smrg if (info->IsAtomBios) 1336209ff23fSmrg return FALSE; 1337b7e1c893Smrg else if (info->IsIGP) { 1338b7e1c893Smrg /* RS4xx TMDS stuff is in the mobile table */ 1339b7e1c893Smrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x42); 1340b7e1c893Smrg if (offset) { 1341b7e1c893Smrg int rev = RADEON_BIOS8(offset); 1342b7e1c893Smrg if (rev >= 6) { 1343b7e1c893Smrg offset = RADEON_BIOS16(offset + 0x17); 1344b7e1c893Smrg if (offset) { 1345b7e1c893Smrg offset = RADEON_BIOS16(offset + 2); 1346b7e1c893Smrg rev = RADEON_BIOS8(offset); 1347b7e1c893Smrg if (offset && (rev > 1)) { 1348b7e1c893Smrg int blocks = RADEON_BIOS8(offset + 3); 1349b7e1c893Smrg int index = offset + 4; 1350b7e1c893Smrg dvo->dvo_i2c.valid = FALSE; 1351b7e1c893Smrg while (blocks > 0) { 1352b7e1c893Smrg int id = RADEON_BIOS16(index); 1353b7e1c893Smrg index += 2; 1354b7e1c893Smrg switch (id >> 13) { 1355b7e1c893Smrg case 0: 1356b7e1c893Smrg index += 6; 1357b7e1c893Smrg break; 1358b7e1c893Smrg case 2: 1359b7e1c893Smrg index += 10; 1360b7e1c893Smrg break; 1361b7e1c893Smrg case 3: 1362b7e1c893Smrg index += 2; 1363b7e1c893Smrg break; 1364b7e1c893Smrg case 4: 1365b7e1c893Smrg index += 2; 1366b7e1c893Smrg break; 1367b7e1c893Smrg case 6: 1368b7e1c893Smrg dvo->dvo_i2c_slave_addr = 1369b7e1c893Smrg RADEON_BIOS16(index) & 0xff; 1370b7e1c893Smrg index += 2; 1371b7e1c893Smrg dvo->dvo_i2c = 1372b7e1c893Smrg RADEONLookupI2CBlock(pScrn, RADEON_BIOS8(index)); 1373b7e1c893Smrg return TRUE; 1374b7e1c893Smrg default: 1375b7e1c893Smrg break; 1376b7e1c893Smrg } 1377b7e1c893Smrg blocks--; 1378b7e1c893Smrg } 1379b7e1c893Smrg } 1380b7e1c893Smrg } 1381b7e1c893Smrg } 1382ad43ddacSmrg } else { 1383ad43ddacSmrg dvo->dvo_i2c_slave_addr = 0x70; 1384ad43ddacSmrg dvo->dvo_i2c = RADEONLookupI2CBlock(pScrn, 136); 1385ad43ddacSmrg info->ext_tmds_chip = RADEON_SIL_164; 1386b7e1c893Smrg } 1387209ff23fSmrg } else { 1388209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58); 1389209ff23fSmrg if (offset) { 1390209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1391209ff23fSmrg "External TMDS Table revision: %d\n", 1392209ff23fSmrg RADEON_BIOS8(offset)); 1393209ff23fSmrg table_start = offset+4; 1394209ff23fSmrg max_freq = RADEON_BIOS16(table_start); 1395b7e1c893Smrg dvo->dvo_i2c_slave_addr = RADEON_BIOS8(table_start+2); 1396b7e1c893Smrg dvo->dvo_i2c.valid = FALSE; 1397209ff23fSmrg gpio_reg = RADEON_BIOS8(table_start+3); 1398209ff23fSmrg if (gpio_reg == 1) 1399b7e1c893Smrg dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); 1400209ff23fSmrg else if (gpio_reg == 2) 1401b7e1c893Smrg dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_DVI_DDC); 1402209ff23fSmrg else if (gpio_reg == 3) 1403b7e1c893Smrg dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_VGA_DDC); 1404ad43ddacSmrg else if (gpio_reg == 4) { 1405ad43ddacSmrg if (IS_R300_VARIANT) 1406ad43ddacSmrg dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_MONID); 1407ad43ddacSmrg else 1408ad43ddacSmrg dvo->dvo_i2c = legacy_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); 1409ad43ddacSmrg } else if (gpio_reg == 5) { 1410209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1411209ff23fSmrg "unsupported MM gpio_reg\n"); 1412b7e1c893Smrg return FALSE; 1413b7e1c893Smrg } else { 1414209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1415209ff23fSmrg "Unknown gpio reg: %d\n", gpio_reg); 1416209ff23fSmrg return FALSE; 1417209ff23fSmrg } 1418209ff23fSmrg flags = RADEON_BIOS8(table_start+5); 1419b7e1c893Smrg dvo->dvo_duallink = flags & 0x01; 1420b7e1c893Smrg if (dvo->dvo_duallink) { 1421209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1422209ff23fSmrg "Duallink TMDS detected\n"); 1423209ff23fSmrg } 1424209ff23fSmrg return TRUE; 1425209ff23fSmrg } 1426209ff23fSmrg } 1427209ff23fSmrg 1428209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1429209ff23fSmrg "No External TMDS Table found\n"); 1430209ff23fSmrg 1431209ff23fSmrg return FALSE; 1432209ff23fSmrg} 1433209ff23fSmrg 1434209ff23fSmrgBool RADEONInitExtTMDSInfoFromBIOS (xf86OutputPtr output) 1435209ff23fSmrg{ 1436209ff23fSmrg ScrnInfoPtr pScrn = output->scrn; 1437209ff23fSmrg RADEONInfoPtr info = RADEONPTR(pScrn); 1438209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1439b7e1c893Smrg radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); 1440b7e1c893Smrg radeon_dvo_ptr dvo = NULL; 1441209ff23fSmrg int offset, index, id; 1442b7e1c893Smrg uint32_t val, reg, and_mask, or_mask; 1443209ff23fSmrg 1444b7e1c893Smrg if (radeon_encoder == NULL) 1445b7e1c893Smrg return FALSE; 1446209ff23fSmrg 1447b7e1c893Smrg dvo = (radeon_dvo_ptr)radeon_encoder->dev_priv; 1448b7e1c893Smrg 1449b7e1c893Smrg if (dvo == NULL) 1450b7e1c893Smrg return FALSE; 1451b7e1c893Smrg 1452b7e1c893Smrg if (!info->VBIOS) 1453b7e1c893Smrg return FALSE; 1454b7e1c893Smrg 1455b7e1c893Smrg if (info->IsAtomBios) 1456209ff23fSmrg return FALSE; 1457b7e1c893Smrg else if (info->IsIGP) { 1458b7e1c893Smrg /* RS4xx TMDS stuff is in the mobile table */ 1459b7e1c893Smrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x42); 1460b7e1c893Smrg if (offset) { 1461b7e1c893Smrg int rev = RADEON_BIOS8(offset); 1462b7e1c893Smrg if (rev >= 6) { 1463b7e1c893Smrg offset = RADEON_BIOS16(offset + 0x17); 1464b7e1c893Smrg if (offset) { 1465b7e1c893Smrg offset = RADEON_BIOS16(offset + 2); 1466b7e1c893Smrg rev = RADEON_BIOS8(offset); 1467b7e1c893Smrg if (offset && (rev > 1)) { 1468b7e1c893Smrg int blocks = RADEON_BIOS8(offset + 3); 1469b7e1c893Smrg index = offset + 4; 1470b7e1c893Smrg while (blocks > 0) { 1471b7e1c893Smrg id = RADEON_BIOS16(index); 1472b7e1c893Smrg index += 2; 1473b7e1c893Smrg switch (id >> 13) { 1474b7e1c893Smrg case 0: 1475b7e1c893Smrg reg = (id & 0x1fff) * 4; 1476b7e1c893Smrg val = RADEON_BIOS32(index); 1477b7e1c893Smrg index += 4; 1478b7e1c893Smrg ErrorF("MMIO: 0x%x 0x%x\n", 1479b7e1c893Smrg (unsigned)reg, (unsigned)val); 1480b7e1c893Smrg OUTREG(reg, val); 1481b7e1c893Smrg break; 1482b7e1c893Smrg case 2: 1483b7e1c893Smrg reg = (id & 0x1fff) * 4; 1484b7e1c893Smrg and_mask = RADEON_BIOS32(index); 1485b7e1c893Smrg index += 4; 1486b7e1c893Smrg or_mask = RADEON_BIOS32(index); 1487b7e1c893Smrg index += 4; 1488b7e1c893Smrg ErrorF("MMIO mask: 0x%x 0x%x 0x%x\n", 1489b7e1c893Smrg (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask); 1490b7e1c893Smrg val = INREG(reg); 1491b7e1c893Smrg val = (val & and_mask) | or_mask; 1492b7e1c893Smrg OUTREG(reg, val); 1493b7e1c893Smrg break; 1494b7e1c893Smrg case 3: 1495b7e1c893Smrg val = RADEON_BIOS16(index); 1496b7e1c893Smrg index += 2; 1497b7e1c893Smrg ErrorF("delay: %u\n", (unsigned)val); 1498b7e1c893Smrg usleep(val); 1499b7e1c893Smrg break; 1500b7e1c893Smrg case 4: 1501b7e1c893Smrg val = RADEON_BIOS16(index); 1502b7e1c893Smrg index += 2; 1503b7e1c893Smrg ErrorF("delay: %u\n", (unsigned)val * 1000); 1504b7e1c893Smrg usleep(val * 1000); 1505b7e1c893Smrg break; 1506b7e1c893Smrg case 6: 1507b7e1c893Smrg index++; 1508b7e1c893Smrg reg = RADEON_BIOS8(index); 1509b7e1c893Smrg index++; 1510b7e1c893Smrg val = RADEON_BIOS8(index); 1511b7e1c893Smrg index++; 1512b7e1c893Smrg ErrorF("i2c write: 0x%x, 0x%x\n", (unsigned)reg, 1513b7e1c893Smrg (unsigned)val); 1514b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, reg, val); 1515b7e1c893Smrg break; 1516b7e1c893Smrg default: 1517b7e1c893Smrg ErrorF("unknown id %d\n", id>>13); 1518b7e1c893Smrg return FALSE; 1519b7e1c893Smrg } 1520b7e1c893Smrg blocks--; 1521b7e1c893Smrg } 1522b7e1c893Smrg return TRUE; 1523b7e1c893Smrg } 1524b7e1c893Smrg } 1525b7e1c893Smrg } 1526b7e1c893Smrg } 1527209ff23fSmrg } else { 1528209ff23fSmrg offset = RADEON_BIOS16(info->ROMHeaderStart + 0x58); 1529209ff23fSmrg if (offset) { 1530209ff23fSmrg index = offset+10; 1531209ff23fSmrg id = RADEON_BIOS16(index); 1532209ff23fSmrg while (id != 0xffff) { 1533209ff23fSmrg index += 2; 1534209ff23fSmrg switch(id >> 13) { 1535209ff23fSmrg case 0: 1536b7e1c893Smrg reg = (id & 0x1fff) * 4; 1537209ff23fSmrg val = RADEON_BIOS32(index); 1538209ff23fSmrg index += 4; 1539b7e1c893Smrg ErrorF("MMIO: 0x%x 0x%x\n", 1540209ff23fSmrg (unsigned)reg, (unsigned)val); 1541b7e1c893Smrg OUTREG(reg, val); 1542209ff23fSmrg break; 1543209ff23fSmrg case 2: 1544b7e1c893Smrg reg = (id & 0x1fff) * 4; 1545b7e1c893Smrg and_mask = RADEON_BIOS32(index); 1546209ff23fSmrg index += 4; 1547b7e1c893Smrg or_mask = RADEON_BIOS32(index); 1548209ff23fSmrg index += 4; 1549209ff23fSmrg val = INREG(reg); 1550b7e1c893Smrg val = (val & and_mask) | or_mask; 1551b7e1c893Smrg ErrorF("MMIO mask: 0x%x 0x%x 0x%x\n", 1552b7e1c893Smrg (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask); 1553b7e1c893Smrg OUTREG(reg, val); 1554209ff23fSmrg break; 1555209ff23fSmrg case 4: 1556209ff23fSmrg val = RADEON_BIOS16(index); 1557209ff23fSmrg index += 2; 1558209ff23fSmrg ErrorF("delay: %u\n", (unsigned)val); 1559209ff23fSmrg usleep(val); 1560209ff23fSmrg break; 1561209ff23fSmrg case 5: 1562209ff23fSmrg reg = id & 0x1fff; 1563b7e1c893Smrg and_mask = RADEON_BIOS32(index); 1564209ff23fSmrg index += 4; 1565b7e1c893Smrg or_mask = RADEON_BIOS32(index); 1566209ff23fSmrg index += 4; 1567b7e1c893Smrg ErrorF("PLL mask: 0x%x 0x%x 0x%x\n", 1568b7e1c893Smrg (unsigned)reg, (unsigned)and_mask, (unsigned)or_mask); 1569b7e1c893Smrg val = INPLL(pScrn, reg); 1570b7e1c893Smrg val = (val & and_mask) | or_mask; 1571b7e1c893Smrg OUTPLL(pScrn, reg, val); 1572209ff23fSmrg break; 1573209ff23fSmrg case 6: 1574209ff23fSmrg reg = id & 0x1fff; 1575209ff23fSmrg val = RADEON_BIOS8(index); 1576209ff23fSmrg index += 1; 1577209ff23fSmrg ErrorF("i2c write: 0x%x, 0x%x\n", (unsigned)reg, 1578209ff23fSmrg (unsigned)val); 1579b7e1c893Smrg RADEONDVOWriteByte(dvo->DVOChip, reg, val); 1580209ff23fSmrg break; 1581209ff23fSmrg default: 1582209ff23fSmrg ErrorF("unknown id %d\n", id>>13); 1583209ff23fSmrg return FALSE; 1584209ff23fSmrg }; 1585209ff23fSmrg id = RADEON_BIOS16(index); 1586209ff23fSmrg } 1587209ff23fSmrg return TRUE; 1588209ff23fSmrg } 1589209ff23fSmrg } 1590209ff23fSmrg 1591209ff23fSmrg return FALSE; 1592209ff23fSmrg} 1593209ff23fSmrg 1594209ff23fSmrg/* support for init from bios tables 1595209ff23fSmrg * 1596209ff23fSmrg * Based heavily on the netbsd radeonfb driver 1597209ff23fSmrg * Written by Garrett D'Amore 1598209ff23fSmrg * Copyright (c) 2006 Itronix Inc. 1599209ff23fSmrg * 1600209ff23fSmrg */ 1601209ff23fSmrg 1602209ff23fSmrg/* bios table defines */ 1603209ff23fSmrg 1604209ff23fSmrg#define RADEON_TABLE_ENTRY_FLAG_MASK 0xe000 1605209ff23fSmrg#define RADEON_TABLE_ENTRY_INDEX_MASK 0x1fff 1606209ff23fSmrg#define RADEON_TABLE_ENTRY_COMMAND_MASK 0x00ff 1607209ff23fSmrg 1608209ff23fSmrg#define RADEON_TABLE_FLAG_WRITE_INDEXED 0x0000 1609209ff23fSmrg#define RADEON_TABLE_FLAG_WRITE_DIRECT 0x2000 1610209ff23fSmrg#define RADEON_TABLE_FLAG_MASK_INDEXED 0x4000 1611209ff23fSmrg#define RADEON_TABLE_FLAG_MASK_DIRECT 0x6000 1612209ff23fSmrg#define RADEON_TABLE_FLAG_DELAY 0x8000 1613209ff23fSmrg#define RADEON_TABLE_FLAG_SCOMMAND 0xa000 1614209ff23fSmrg 1615209ff23fSmrg#define RADEON_TABLE_SCOMMAND_WAIT_MC_BUSY_MASK 0x03 1616209ff23fSmrg#define RADEON_TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE 0x08 1617209ff23fSmrg 1618209ff23fSmrg#define RADEON_PLL_FLAG_MASK 0xc0 1619209ff23fSmrg#define RADEON_PLL_INDEX_MASK 0x3f 1620209ff23fSmrg 1621209ff23fSmrg#define RADEON_PLL_FLAG_WRITE 0x00 1622209ff23fSmrg#define RADEON_PLL_FLAG_MASK_BYTE 0x40 1623209ff23fSmrg#define RADEON_PLL_FLAG_WAIT 0x80 1624209ff23fSmrg 1625209ff23fSmrg#define RADEON_PLL_WAIT_150MKS 1 1626209ff23fSmrg#define RADEON_PLL_WAIT_5MS 2 1627209ff23fSmrg#define RADEON_PLL_WAIT_MC_BUSY_MASK 3 1628209ff23fSmrg#define RADEON_PLL_WAIT_DLL_READY_MASK 4 1629209ff23fSmrg#define RADEON_PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24 5 1630209ff23fSmrg 1631209ff23fSmrgstatic uint16_t 1632209ff23fSmrgRADEONValidateBIOSOffset(ScrnInfoPtr pScrn, uint16_t offset) 1633209ff23fSmrg{ 1634209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1635209ff23fSmrg uint8_t revision = RADEON_BIOS8(offset - 1); 1636209ff23fSmrg 1637209ff23fSmrg if (revision > 0x10) { 1638209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1639209ff23fSmrg "Bad revision %d for BIOS table\n", revision); 1640209ff23fSmrg return 0; 1641209ff23fSmrg } 1642209ff23fSmrg 1643209ff23fSmrg if (offset < 0x60) { 1644209ff23fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1645209ff23fSmrg "Bad offset 0x%x for BIOS Table\n", offset); 1646209ff23fSmrg return 0; 1647209ff23fSmrg } 1648209ff23fSmrg 1649209ff23fSmrg return offset; 1650209ff23fSmrg} 1651209ff23fSmrg 1652209ff23fSmrgBool 1653209ff23fSmrgRADEONGetBIOSInitTableOffsets(ScrnInfoPtr pScrn) 1654209ff23fSmrg{ 1655209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1656209ff23fSmrg uint8_t val; 1657209ff23fSmrg 1658209ff23fSmrg if (!info->VBIOS) { 1659209ff23fSmrg return FALSE; 1660209ff23fSmrg } else { 1661209ff23fSmrg if (info->IsAtomBios) { 1662209ff23fSmrg return FALSE; 1663209ff23fSmrg } else { 1664209ff23fSmrg info->BiosTable.revision = RADEON_BIOS8(info->ROMHeaderStart + 4); 1665209ff23fSmrg info->BiosTable.rr1_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x0c); 1666209ff23fSmrg if (info->BiosTable.rr1_offset) { 1667209ff23fSmrg info->BiosTable.rr1_offset = 1668209ff23fSmrg RADEONValidateBIOSOffset(pScrn, info->BiosTable.rr1_offset); 1669209ff23fSmrg } 1670209ff23fSmrg if (info->BiosTable.revision > 0x09) 1671209ff23fSmrg return TRUE; 1672209ff23fSmrg info->BiosTable.rr2_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x4e); 1673209ff23fSmrg if (info->BiosTable.rr2_offset) { 1674209ff23fSmrg info->BiosTable.rr2_offset = 1675209ff23fSmrg RADEONValidateBIOSOffset(pScrn, info->BiosTable.rr2_offset); 1676209ff23fSmrg } 1677209ff23fSmrg info->BiosTable.dyn_clk_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x52); 1678209ff23fSmrg if (info->BiosTable.dyn_clk_offset) { 1679209ff23fSmrg info->BiosTable.dyn_clk_offset = 1680209ff23fSmrg RADEONValidateBIOSOffset(pScrn, info->BiosTable.dyn_clk_offset); 1681209ff23fSmrg } 1682209ff23fSmrg info->BiosTable.pll_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x46); 1683209ff23fSmrg if (info->BiosTable.pll_offset) { 1684209ff23fSmrg info->BiosTable.pll_offset = 1685209ff23fSmrg RADEONValidateBIOSOffset(pScrn, info->BiosTable.pll_offset); 1686209ff23fSmrg } 1687209ff23fSmrg info->BiosTable.mem_config_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x48); 1688209ff23fSmrg if (info->BiosTable.mem_config_offset) { 1689209ff23fSmrg info->BiosTable.mem_config_offset = 1690209ff23fSmrg RADEONValidateBIOSOffset(pScrn, info->BiosTable.mem_config_offset); 1691209ff23fSmrg } 1692209ff23fSmrg if (info->BiosTable.mem_config_offset) { 1693209ff23fSmrg info->BiosTable.mem_reset_offset = info->BiosTable.mem_config_offset; 1694209ff23fSmrg if (info->BiosTable.mem_reset_offset) { 1695209ff23fSmrg while (RADEON_BIOS8(info->BiosTable.mem_reset_offset)) 1696209ff23fSmrg info->BiosTable.mem_reset_offset++; 1697209ff23fSmrg info->BiosTable.mem_reset_offset++; 1698209ff23fSmrg info->BiosTable.mem_reset_offset += 2; 1699209ff23fSmrg } 1700209ff23fSmrg } 1701209ff23fSmrg if (info->BiosTable.mem_config_offset) { 1702209ff23fSmrg info->BiosTable.short_mem_offset = info->BiosTable.mem_config_offset; 1703209ff23fSmrg if ((info->BiosTable.short_mem_offset != 0) && 1704209ff23fSmrg (RADEON_BIOS8(info->BiosTable.short_mem_offset - 2) <= 64)) 1705209ff23fSmrg info->BiosTable.short_mem_offset += 1706209ff23fSmrg RADEON_BIOS8(info->BiosTable.short_mem_offset - 3); 1707209ff23fSmrg } 1708209ff23fSmrg if (info->BiosTable.rr2_offset) { 1709209ff23fSmrg info->BiosTable.rr3_offset = info->BiosTable.rr2_offset; 1710209ff23fSmrg if (info->BiosTable.rr3_offset) { 1711209ff23fSmrg while ((val = RADEON_BIOS8(info->BiosTable.rr3_offset + 1)) != 0) { 1712209ff23fSmrg if (val & 0x40) 1713209ff23fSmrg info->BiosTable.rr3_offset += 10; 1714209ff23fSmrg else if (val & 0x80) 1715209ff23fSmrg info->BiosTable.rr3_offset += 4; 1716209ff23fSmrg else 1717209ff23fSmrg info->BiosTable.rr3_offset += 6; 1718209ff23fSmrg } 1719209ff23fSmrg info->BiosTable.rr3_offset += 2; 1720209ff23fSmrg } 1721209ff23fSmrg } 1722209ff23fSmrg 1723209ff23fSmrg if (info->BiosTable.rr3_offset) { 1724209ff23fSmrg info->BiosTable.rr4_offset = info->BiosTable.rr3_offset; 1725209ff23fSmrg if (info->BiosTable.rr4_offset) { 1726209ff23fSmrg while ((val = RADEON_BIOS8(info->BiosTable.rr4_offset + 1)) != 0) { 1727209ff23fSmrg if (val & 0x40) 1728209ff23fSmrg info->BiosTable.rr4_offset += 10; 1729209ff23fSmrg else if (val & 0x80) 1730209ff23fSmrg info->BiosTable.rr4_offset += 4; 1731209ff23fSmrg else 1732209ff23fSmrg info->BiosTable.rr4_offset += 6; 1733209ff23fSmrg } 1734209ff23fSmrg info->BiosTable.rr4_offset += 2; 1735209ff23fSmrg } 1736209ff23fSmrg } 1737209ff23fSmrg 1738209ff23fSmrg if (info->BiosTable.rr3_offset + 1 == info->BiosTable.pll_offset) { 1739209ff23fSmrg info->BiosTable.rr3_offset = 0; 1740209ff23fSmrg info->BiosTable.rr4_offset = 0; 1741209ff23fSmrg } 1742209ff23fSmrg 1743209ff23fSmrg return TRUE; 1744209ff23fSmrg 1745209ff23fSmrg } 1746209ff23fSmrg } 1747209ff23fSmrg} 1748209ff23fSmrg 1749209ff23fSmrgstatic void 1750209ff23fSmrgRADEONRestoreBIOSRegBlock(ScrnInfoPtr pScrn, uint16_t table_offset) 1751209ff23fSmrg{ 1752209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1753209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1754209ff23fSmrg uint16_t offset = table_offset; 1755209ff23fSmrg uint16_t value, flag, index, count; 1756209ff23fSmrg uint32_t andmask, ormask, val, channel_complete_mask; 1757209ff23fSmrg uint8_t command; 1758209ff23fSmrg 1759209ff23fSmrg if (offset == 0) 1760209ff23fSmrg return; 1761209ff23fSmrg 1762209ff23fSmrg while ((value = RADEON_BIOS16(offset)) != 0) { 1763209ff23fSmrg flag = value & RADEON_TABLE_ENTRY_FLAG_MASK; 1764209ff23fSmrg index = value & RADEON_TABLE_ENTRY_INDEX_MASK; 1765209ff23fSmrg command = value & RADEON_TABLE_ENTRY_COMMAND_MASK; 1766209ff23fSmrg 1767209ff23fSmrg offset += 2; 1768209ff23fSmrg 1769209ff23fSmrg switch (flag) { 1770209ff23fSmrg case RADEON_TABLE_FLAG_WRITE_INDEXED: 1771209ff23fSmrg val = RADEON_BIOS32(offset); 1772209ff23fSmrg ErrorF("WRITE INDEXED: 0x%x 0x%x\n", 1773209ff23fSmrg index, (unsigned)val); 1774209ff23fSmrg OUTREG(RADEON_MM_INDEX, index); 1775209ff23fSmrg OUTREG(RADEON_MM_DATA, val); 1776209ff23fSmrg offset += 4; 1777209ff23fSmrg break; 1778209ff23fSmrg 1779209ff23fSmrg case RADEON_TABLE_FLAG_WRITE_DIRECT: 1780209ff23fSmrg val = RADEON_BIOS32(offset); 1781209ff23fSmrg ErrorF("WRITE DIRECT: 0x%x 0x%x\n", index, (unsigned)val); 1782209ff23fSmrg OUTREG(index, val); 1783209ff23fSmrg offset += 4; 1784209ff23fSmrg break; 1785209ff23fSmrg 1786209ff23fSmrg case RADEON_TABLE_FLAG_MASK_INDEXED: 1787209ff23fSmrg andmask = RADEON_BIOS32(offset); 1788209ff23fSmrg offset += 4; 1789209ff23fSmrg ormask = RADEON_BIOS32(offset); 1790209ff23fSmrg offset += 4; 1791209ff23fSmrg ErrorF("MASK INDEXED: 0x%x 0x%x 0x%x\n", 1792209ff23fSmrg index, (unsigned)andmask, (unsigned)ormask); 1793209ff23fSmrg OUTREG(RADEON_MM_INDEX, index); 1794209ff23fSmrg val = INREG(RADEON_MM_DATA); 1795209ff23fSmrg val = (val & andmask) | ormask; 1796209ff23fSmrg OUTREG(RADEON_MM_DATA, val); 1797209ff23fSmrg break; 1798209ff23fSmrg 1799209ff23fSmrg case RADEON_TABLE_FLAG_MASK_DIRECT: 1800209ff23fSmrg andmask = RADEON_BIOS32(offset); 1801209ff23fSmrg offset += 4; 1802209ff23fSmrg ormask = RADEON_BIOS32(offset); 1803209ff23fSmrg offset += 4; 1804209ff23fSmrg ErrorF("MASK DIRECT: 0x%x 0x%x 0x%x\n", 1805209ff23fSmrg index, (unsigned)andmask, (unsigned)ormask); 1806209ff23fSmrg val = INREG(index); 1807209ff23fSmrg val = (val & andmask) | ormask; 1808209ff23fSmrg OUTREG(index, val); 1809209ff23fSmrg break; 1810209ff23fSmrg 1811209ff23fSmrg case RADEON_TABLE_FLAG_DELAY: 1812209ff23fSmrg count = RADEON_BIOS16(offset); 1813209ff23fSmrg ErrorF("delay: %d\n", count); 1814209ff23fSmrg usleep(count); 1815209ff23fSmrg offset += 2; 1816209ff23fSmrg break; 1817209ff23fSmrg 1818209ff23fSmrg case RADEON_TABLE_FLAG_SCOMMAND: 1819209ff23fSmrg ErrorF("SCOMMAND 0x%x\n", command); 1820209ff23fSmrg switch (command) { 1821209ff23fSmrg case RADEON_TABLE_SCOMMAND_WAIT_MC_BUSY_MASK: 1822209ff23fSmrg count = RADEON_BIOS16(offset); 1823209ff23fSmrg ErrorF("SCOMMAND_WAIT_MC_BUSY_MASK %d\n", count); 1824209ff23fSmrg while (count--) { 1825209ff23fSmrg if (!(INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & 1826209ff23fSmrg RADEON_MC_BUSY)) 1827209ff23fSmrg break; 1828209ff23fSmrg } 1829209ff23fSmrg break; 1830209ff23fSmrg 1831209ff23fSmrg case RADEON_TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE: 1832209ff23fSmrg count = RADEON_BIOS16(offset); 1833209ff23fSmrg ErrorF("SCOMMAND_WAIT_MEM_PWRUP_COMPLETE %d\n", count); 1834209ff23fSmrg /* may need to take into account how many memory channels 1835209ff23fSmrg * each card has 1836209ff23fSmrg */ 1837209ff23fSmrg if (IS_R300_VARIANT) 1838209ff23fSmrg channel_complete_mask = R300_MEM_PWRUP_COMPLETE; 1839209ff23fSmrg else 1840209ff23fSmrg channel_complete_mask = RADEON_MEM_PWRUP_COMPLETE; 1841209ff23fSmrg while (count--) { 1842209ff23fSmrg /* XXX: may need indexed access */ 1843209ff23fSmrg if ((INREG(RADEON_MEM_STR_CNTL) & 1844209ff23fSmrg channel_complete_mask) == 1845209ff23fSmrg channel_complete_mask) 1846209ff23fSmrg break; 1847209ff23fSmrg } 1848209ff23fSmrg break; 1849209ff23fSmrg 1850209ff23fSmrg } 1851209ff23fSmrg offset += 2; 1852209ff23fSmrg break; 1853209ff23fSmrg } 1854209ff23fSmrg } 1855209ff23fSmrg} 1856209ff23fSmrg 1857209ff23fSmrgstatic void 1858209ff23fSmrgRADEONRestoreBIOSMemBlock(ScrnInfoPtr pScrn, uint16_t table_offset) 1859209ff23fSmrg{ 1860209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1861209ff23fSmrg unsigned char *RADEONMMIO = info->MMIO; 1862209ff23fSmrg uint16_t offset = table_offset; 1863209ff23fSmrg uint16_t count; 1864209ff23fSmrg uint32_t ormask, val, channel_complete_mask; 1865209ff23fSmrg uint8_t index; 1866209ff23fSmrg 1867209ff23fSmrg if (offset == 0) 1868209ff23fSmrg return; 1869209ff23fSmrg 1870209ff23fSmrg while ((index = RADEON_BIOS8(offset)) != 0xff) { 1871209ff23fSmrg offset++; 1872209ff23fSmrg if (index == 0x0f) { 1873209ff23fSmrg count = 20000; 1874209ff23fSmrg ErrorF("MEM_WAIT_MEM_PWRUP_COMPLETE %d\n", count); 1875209ff23fSmrg /* may need to take into account how many memory channels 1876209ff23fSmrg * each card has 1877209ff23fSmrg */ 1878209ff23fSmrg if (IS_R300_VARIANT) 1879209ff23fSmrg channel_complete_mask = R300_MEM_PWRUP_COMPLETE; 1880209ff23fSmrg else 1881209ff23fSmrg channel_complete_mask = RADEON_MEM_PWRUP_COMPLETE; 1882209ff23fSmrg while (count--) { 1883209ff23fSmrg /* XXX: may need indexed access */ 1884209ff23fSmrg if ((INREG(RADEON_MEM_STR_CNTL) & 1885209ff23fSmrg channel_complete_mask) == 1886209ff23fSmrg channel_complete_mask) 1887209ff23fSmrg break; 1888209ff23fSmrg } 1889209ff23fSmrg } else { 1890209ff23fSmrg ormask = RADEON_BIOS16(offset); 1891209ff23fSmrg offset += 2; 1892209ff23fSmrg 1893209ff23fSmrg ErrorF("INDEX RADEON_MEM_SDRAM_MODE_REG %x %x\n", 1894209ff23fSmrg RADEON_SDRAM_MODE_MASK, (unsigned)ormask); 1895209ff23fSmrg 1896209ff23fSmrg /* can this use direct access? */ 1897209ff23fSmrg OUTREG(RADEON_MM_INDEX, RADEON_MEM_SDRAM_MODE_REG); 1898209ff23fSmrg val = INREG(RADEON_MM_DATA); 1899209ff23fSmrg val = (val & RADEON_SDRAM_MODE_MASK) | ormask; 1900209ff23fSmrg OUTREG(RADEON_MM_DATA, val); 1901209ff23fSmrg 1902209ff23fSmrg ormask = (uint32_t)index << 24; 1903209ff23fSmrg 1904209ff23fSmrg ErrorF("INDEX RADEON_MEM_SDRAM_MODE_REG %x %x\n", 1905209ff23fSmrg RADEON_B3MEM_RESET_MASK, (unsigned)ormask); 1906209ff23fSmrg 1907209ff23fSmrg /* can this use direct access? */ 1908209ff23fSmrg OUTREG(RADEON_MM_INDEX, RADEON_MEM_SDRAM_MODE_REG); 1909209ff23fSmrg val = INREG(RADEON_MM_DATA); 1910209ff23fSmrg val = (val & RADEON_B3MEM_RESET_MASK) | ormask; 1911209ff23fSmrg OUTREG(RADEON_MM_DATA, val); 1912209ff23fSmrg } 1913209ff23fSmrg } 1914209ff23fSmrg} 1915209ff23fSmrg 1916209ff23fSmrgstatic void 1917209ff23fSmrgRADEONRestoreBIOSPllBlock(ScrnInfoPtr pScrn, uint16_t table_offset) 1918209ff23fSmrg{ 1919209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 1920209ff23fSmrg uint16_t offset = table_offset; 1921209ff23fSmrg uint8_t index, shift; 1922209ff23fSmrg uint32_t andmask, ormask, val, clk_pwrmgt_cntl; 1923209ff23fSmrg uint16_t count; 1924209ff23fSmrg 1925209ff23fSmrg if (offset == 0) 1926209ff23fSmrg return; 1927209ff23fSmrg 1928209ff23fSmrg while ((index = RADEON_BIOS8(offset)) != 0) { 1929209ff23fSmrg offset++; 1930209ff23fSmrg 1931209ff23fSmrg switch (index & RADEON_PLL_FLAG_MASK) { 1932209ff23fSmrg case RADEON_PLL_FLAG_WAIT: 1933209ff23fSmrg switch (index & RADEON_PLL_INDEX_MASK) { 1934209ff23fSmrg case RADEON_PLL_WAIT_150MKS: 1935209ff23fSmrg ErrorF("delay: 150 us\n"); 1936209ff23fSmrg usleep(150); 1937209ff23fSmrg break; 1938209ff23fSmrg case RADEON_PLL_WAIT_5MS: 1939209ff23fSmrg ErrorF("delay: 5 ms\n"); 1940209ff23fSmrg usleep(5000); 1941209ff23fSmrg break; 1942209ff23fSmrg 1943209ff23fSmrg case RADEON_PLL_WAIT_MC_BUSY_MASK: 1944209ff23fSmrg count = 1000; 1945209ff23fSmrg ErrorF("PLL_WAIT_MC_BUSY_MASK %d\n", count); 1946209ff23fSmrg while (count--) { 1947209ff23fSmrg if (!(INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & 1948209ff23fSmrg RADEON_MC_BUSY)) 1949209ff23fSmrg break; 1950209ff23fSmrg } 1951209ff23fSmrg break; 1952209ff23fSmrg 1953209ff23fSmrg case RADEON_PLL_WAIT_DLL_READY_MASK: 1954209ff23fSmrg count = 1000; 1955209ff23fSmrg ErrorF("PLL_WAIT_DLL_READY_MASK %d\n", count); 1956209ff23fSmrg while (count--) { 1957209ff23fSmrg if (INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & 1958209ff23fSmrg RADEON_DLL_READY) 1959209ff23fSmrg break; 1960209ff23fSmrg } 1961209ff23fSmrg break; 1962209ff23fSmrg 1963209ff23fSmrg case RADEON_PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24: 1964209ff23fSmrg ErrorF("PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24\n"); 1965209ff23fSmrg clk_pwrmgt_cntl = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL); 1966209ff23fSmrg if (clk_pwrmgt_cntl & RADEON_CG_NO1_DEBUG_0) { 1967209ff23fSmrg val = INPLL(pScrn, RADEON_MCLK_CNTL); 1968209ff23fSmrg /* is this right? */ 1969209ff23fSmrg val = (val & 0xFFFF0000) | 0x1111; /* seems like we should clear these... */ 1970209ff23fSmrg OUTPLL(pScrn, RADEON_MCLK_CNTL, val); 1971209ff23fSmrg usleep(10000); 1972209ff23fSmrg OUTPLL(pScrn, RADEON_CLK_PWRMGT_CNTL, 1973209ff23fSmrg clk_pwrmgt_cntl & ~RADEON_CG_NO1_DEBUG_0); 1974209ff23fSmrg usleep(10000); 1975209ff23fSmrg } 1976209ff23fSmrg break; 1977209ff23fSmrg } 1978209ff23fSmrg break; 1979209ff23fSmrg 1980209ff23fSmrg case RADEON_PLL_FLAG_MASK_BYTE: 1981209ff23fSmrg shift = RADEON_BIOS8(offset) * 8; 1982209ff23fSmrg offset++; 1983209ff23fSmrg 1984209ff23fSmrg andmask = 1985209ff23fSmrg (((uint32_t)RADEON_BIOS8(offset)) << shift) | 1986209ff23fSmrg ~((uint32_t)0xff << shift); 1987209ff23fSmrg offset++; 1988209ff23fSmrg 1989209ff23fSmrg ormask = ((uint32_t)RADEON_BIOS8(offset)) << shift; 1990209ff23fSmrg offset++; 1991209ff23fSmrg 1992209ff23fSmrg ErrorF("PLL_MASK_BYTE 0x%x 0x%x 0x%x 0x%x\n", 1993209ff23fSmrg index, shift, (unsigned)andmask, (unsigned)ormask); 1994209ff23fSmrg val = INPLL(pScrn, index); 1995209ff23fSmrg val = (val & andmask) | ormask; 1996209ff23fSmrg OUTPLL(pScrn, index, val); 1997209ff23fSmrg break; 1998209ff23fSmrg 1999209ff23fSmrg case RADEON_PLL_FLAG_WRITE: 2000209ff23fSmrg val = RADEON_BIOS32(offset); 2001209ff23fSmrg ErrorF("PLL_WRITE 0x%x 0x%x\n", index, (unsigned)val); 2002209ff23fSmrg OUTPLL(pScrn, index, val); 2003209ff23fSmrg offset += 4; 2004209ff23fSmrg break; 2005209ff23fSmrg } 2006209ff23fSmrg } 2007209ff23fSmrg} 2008209ff23fSmrg 2009209ff23fSmrgBool 2010209ff23fSmrgRADEONPostCardFromBIOSTables(ScrnInfoPtr pScrn) 2011209ff23fSmrg{ 2012209ff23fSmrg RADEONInfoPtr info = RADEONPTR (pScrn); 2013209ff23fSmrg 2014209ff23fSmrg if (!info->VBIOS) { 2015209ff23fSmrg return FALSE; 2016209ff23fSmrg } else { 2017209ff23fSmrg if (info->IsAtomBios) { 2018209ff23fSmrg return FALSE; 2019209ff23fSmrg } else { 2020209ff23fSmrg if (info->BiosTable.rr1_offset) { 2021209ff23fSmrg ErrorF("rr1 restore, 0x%x\n", info->BiosTable.rr1_offset); 2022209ff23fSmrg RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr1_offset); 2023209ff23fSmrg } 2024209ff23fSmrg if (info->BiosTable.revision < 0x09) { 2025209ff23fSmrg if (info->BiosTable.pll_offset) { 2026209ff23fSmrg ErrorF("pll restore, 0x%x\n", info->BiosTable.pll_offset); 2027209ff23fSmrg RADEONRestoreBIOSPllBlock(pScrn, info->BiosTable.pll_offset); 2028209ff23fSmrg } 2029209ff23fSmrg if (info->BiosTable.rr2_offset) { 2030209ff23fSmrg ErrorF("rr2 restore, 0x%x\n", info->BiosTable.rr2_offset); 2031209ff23fSmrg RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr2_offset); 2032209ff23fSmrg } 2033209ff23fSmrg if (info->BiosTable.rr4_offset) { 2034209ff23fSmrg ErrorF("rr4 restore, 0x%x\n", info->BiosTable.rr4_offset); 2035209ff23fSmrg RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr4_offset); 2036209ff23fSmrg } 2037209ff23fSmrg if (info->BiosTable.mem_reset_offset) { 2038209ff23fSmrg ErrorF("mem reset restore, 0x%x\n", info->BiosTable.mem_reset_offset); 2039209ff23fSmrg RADEONRestoreBIOSMemBlock(pScrn, info->BiosTable.mem_reset_offset); 2040209ff23fSmrg } 2041209ff23fSmrg if (info->BiosTable.rr3_offset) { 2042209ff23fSmrg ErrorF("rr3 restore, 0x%x\n", info->BiosTable.rr3_offset); 2043209ff23fSmrg RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr3_offset); 2044209ff23fSmrg } 2045209ff23fSmrg if (info->BiosTable.dyn_clk_offset) { 2046209ff23fSmrg ErrorF("dyn_clk restore, 0x%x\n", info->BiosTable.dyn_clk_offset); 2047209ff23fSmrg RADEONRestoreBIOSPllBlock(pScrn, info->BiosTable.dyn_clk_offset); 2048209ff23fSmrg } 2049209ff23fSmrg } 2050209ff23fSmrg } 2051209ff23fSmrg } 2052209ff23fSmrg return TRUE; 2053209ff23fSmrg} 2054