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