diff options
author | George Sapountzis <gsap7@yahoo.gr> | 2007-08-28 16:01:12 +0300 |
---|---|---|
committer | George Sapountzis <gsap7@yahoo.gr> | 2007-08-28 16:01:12 +0300 |
commit | 7b38d9a1209f87255e5bb0aefe46a363ce4fb6ef (patch) | |
tree | 981bce7b10ffe6dc3940cada74d558213208b51b /src | |
parent | 2e3d43af1e5077cc61dd8668551a6291368d9ed2 (diff) | |
parent | 673f799729824f4439dd5f681f75dd5aab50947f (diff) |
Merge branch 'master' into pci-rework
Conflicts:
src/ati.c
Diffstat (limited to 'src')
52 files changed, 9166 insertions, 8807 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 2528d2a7..dd7007e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,36 +51,37 @@ ati_drv_la_LTLIBRARIES = ati_drv.la ati_drv_la_LDFLAGS = -module -avoid-version ati_drv_ladir = @moduledir@/drivers ati_drv_la_SOURCES = \ - ati.c atichip.c atimodule.c atimach64probe.c \ - radeon_probe.c r128_probe.c + ati.c atimodule.c atimisc_drv_la_LTLIBRARIES = atimisc_drv.la atimisc_drv_la_LDFLAGS = -module -avoid-version atimisc_drv_ladir = @moduledir@/drivers atimisc_drv_la_SOURCES = \ - atibus.c atiprobe.c atividmem.c \ + atibus.c atichip.c atiprobe.c atividmem.c \ atiadjust.c atiaudio.c aticlock.c aticonfig.c aticonsole.c \ - atidac.c atidecoder.c atidsp.c atifillin.c atii2c.c \ + atidac.c atidecoder.c atidsp.c atii2c.c \ atilock.c atimach64.c atimach64accel.c atimach64cursor.c \ atimach64i2c.c atimach64io.c atimach64xv.c atimode.c atipreinit.c \ atiprint.c atirgb514.c atiscreen.c atituner.c atiutil.c ativalid.c \ - atiload.c atimisc.c $(ATIMISC_DRI_SRCS) $(ATIMISC_DGA_SOURCES) \ - $(ATIMISC_CPIO_SOURCES) $(ATIMISC_EXA_SOURCES) + atiload.c atimisc.c atimach64probe.c $(ATIMISC_CPIO_SOURCES) \ + $(ATIMISC_DGA_SOURCES) $(ATIMISC_DRI_SRCS) $(ATIMISC_EXA_SOURCES) r128_drv_la_LTLIBRARIES = r128_drv.la r128_drv_la_LDFLAGS = -module -avoid-version r128_drv_ladir = @moduledir@/drivers r128_drv_la_SOURCES = \ r128_accel.c r128_cursor.c r128_dga.c r128_driver.c \ - r128_video.c r128_misc.c $(R128_DRI_SRCS) + r128_video.c r128_misc.c r128_probe.c $(R128_DRI_SRCS) radeon_drv_la_LTLIBRARIES = radeon_drv.la radeon_drv_la_LDFLAGS = -module -avoid-version radeon_drv_ladir = @moduledir@/drivers radeon_drv_la_SOURCES = \ - radeon_accel.c radeon_mergedfb.c radeon_cursor.c radeon_dga.c \ + radeon_accel.c radeon_cursor.c radeon_dga.c \ radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \ - radeon_vip.c radeon_misc.c radeon_display.c radeon_modes.c $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) + radeon_vip.c radeon_misc.c radeon_probe.c radeon_display.c \ + radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \ + $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) theatre_detect_drv_la_LTLIBRARIES = theatre_detect_drv.la theatre_detect_drv_la_LDFLAGS = -module -avoid-version @@ -123,7 +124,6 @@ EXTRA_DIST = \ atidri.h \ atidripriv.h \ atidsp.h \ - atifillin.h \ ati.h \ atii2c.h \ atiload.h \ @@ -176,12 +176,12 @@ EXTRA_DIST = \ radeon_exa_funcs.c \ radeon.h \ radeon_macros.h \ - radeon_mergedfb.h \ radeon_probe.h \ radeon_reg.h \ radeon_sarea.h \ radeon_version.h \ radeon_video.h \ + radeon_tv.h \ theatre200.h \ theatre_detect.h \ theatre.h \ @@ -60,14 +60,12 @@ #include "atipcirename.h" #include "ati.h" -#include "atichip.h" +#include "atimodule.h" #include "ativersion.h" #include "atimach64probe.h" #include "radeon_probe.h" -#include "radeon_version.h" #include "r128_probe.h" -#include "r128_version.h" /* * ATIIdentify -- @@ -80,10 +78,13 @@ ATIIdentify int flags ) { + /* + * Only print chip families here, chip lists are printed when a subdriver + * is loaded. + */ xf86Msg(X_INFO, "%s: %s\n", ATI_NAME, - "ATI driver (version " ATI_VERSION_NAME ") for chipset: mach64"); - R128Identify(flags); - RADEONIdentify(flags); + "ATI driver wrapper (version " ATI_VERSION_NAME ") for chipsets: " + "mach64, rage128, radeon"); } /* @@ -99,61 +100,100 @@ ATIProbe int flags ) { - pciVideoPtr pVideo, *xf86PciVideoInfo = xf86GetPciVideoInfo(); - Bool ProbeSuccess = FALSE; + pciVideoPtr pVideo; + pciVideoPtr *xf86PciVideoInfo; Bool DoMach64 = FALSE; Bool DoRage128 = FALSE, DoRadeon = FALSE; - int i; ATIChipType Chip; - if (!(flags & PROBE_DETECT)) + xf86PciVideoInfo = xf86GetPciVideoInfo(); + + if (xf86PciVideoInfo == NULL) + return FALSE; + + while ((pVideo = *xf86PciVideoInfo++) != NULL) { - if (xf86MatchDevice(ATI_NAME, NULL) > 0) + if ((PCI_DEV_VENDOR_ID(pVideo) != PCI_VENDOR_ATI) || + (PCI_DEV_DEVICE_ID(pVideo) == PCI_CHIP_MACH32)) + continue; + + /* Check for Rage128's, Radeon's and later adapters */ + Chip = ATIChipID(PCI_DEV_DEVICE_ID(pVideo), PCI_DEV_REVISION(pVideo)); + if (Chip <= ATI_CHIP_Mach64) DoMach64 = TRUE; - if (xf86MatchDevice(R128_NAME, NULL) > 0) + else if (Chip <= ATI_CHIP_Rage128) DoRage128 = TRUE; - if (xf86MatchDevice(RADEON_NAME, NULL) > 0) + else if (Chip <= ATI_CHIP_Radeon) DoRadeon = TRUE; } - if (xf86PciVideoInfo) + /* Call Radeon driver probe */ + if (DoRadeon) { - for (i = 0; (pVideo = xf86PciVideoInfo[i++]); ) + pointer radeon = xf86LoadDrvSubModule(pDriver, "radeon"); + + if (!radeon) { - if ((PCI_DEV_VENDOR_ID(pVideo) != PCI_VENDOR_ATI) || - (PCI_DEV_DEVICE_ID(pVideo) == PCI_CHIP_MACH32)) - continue; + xf86Msg(X_ERROR, + ATI_NAME ": Failed to load \"radeon\" module.\n"); + return FALSE; + } - /* Check for Rage128's, Radeon's and later adapters */ - Chip = ATIChipID(PCI_DEV_DEVICE_ID(pVideo), PCI_DEV_REVISION(pVideo)); + xf86LoaderReqSymLists(RADEONSymbols, NULL); - if (Chip > ATI_CHIP_Mach64) - { - if (Chip <= ATI_CHIP_Rage128) - DoRage128 = TRUE; - else if (Chip <= ATI_CHIP_Radeon) - DoRadeon = TRUE; + RADEONIdentify(flags); - continue; - } + if (RADEONProbe(pDriver, flags)) + return TRUE; - DoMach64 = TRUE; + xf86UnloadSubModule(radeon); + } + + /* Call Rage 128 driver probe */ + if (DoRage128) + { + pointer r128 = xf86LoadDrvSubModule(pDriver, "r128"); + + if (!r128) + { + xf86Msg(X_ERROR, + ATI_NAME ": Failed to load \"r128\" module.\n"); + return FALSE; } + + xf86LoaderReqSymLists(R128Symbols, NULL); + + R128Identify(flags); + + if (R128Probe(pDriver, flags)) + return TRUE; + + xf86UnloadSubModule(r128); } /* Call Mach64 driver probe */ - if (DoMach64 && Mach64Probe(pDriver, flags)) - ProbeSuccess = TRUE; + if (DoMach64) + { + pointer atimisc = xf86LoadDrvSubModule(pDriver, "atimisc"); - /* Call Rage 128 driver probe */ - if (DoRage128 && R128Probe(pDriver, flags)) - ProbeSuccess = TRUE; + if (!atimisc) + { + xf86Msg(X_ERROR, + ATI_NAME ": Failed to load \"atimisc\" module.\n"); + return FALSE; + } - /* Call Radeon driver probe */ - if (DoRadeon && RADEONProbe(pDriver, flags)) - ProbeSuccess = TRUE; + xf86LoaderReqSymLists(ATISymbols, NULL); + + Mach64Identify(flags); + + if (Mach64Probe(pDriver, flags)) + return TRUE; - return ProbeSuccess; + xf86UnloadSubModule(atimisc); + } + + return FALSE; } /* @@ -161,22 +201,27 @@ ATIProbe * * Return recognised options that are intended for public consumption. */ -const OptionInfoRec * +static const OptionInfoRec * ATIAvailableOptions ( int ChipId, int BusId ) { - const OptionInfoRec *pOptions; + CARD16 ChipType = ChipId & 0xffff; + ATIChipType Chip; - if ((pOptions = R128AvailableOptions(ChipId, BusId))) - return pOptions; + /* Probe should have loaded the appropriate subdriver by this point */ - if ((pOptions = RADEONAvailableOptions(ChipId, BusId))) - return pOptions; + Chip = ATIChipID(ChipType, 0x0); /* chip revision is don't care */ + if (Chip <= ATI_CHIP_Mach64) + return Mach64AvailableOptions(ChipId, BusId); + else if (Chip <= ATI_CHIP_Rage128) + return R128AvailableOptions(ChipId, BusId); + else if (Chip <= ATI_CHIP_Radeon) + return RADEONAvailableOptions(ChipId, BusId); - return Mach64AvailableOptions(ChipId, BusId); + return NULL; } /* The root of all evil... */ @@ -190,3 +235,469 @@ _X_EXPORT DriverRec ATI = NULL, 0 }; + +/* + * Chip-related definitions. + */ +const char *ATIChipNames[] = +{ + "Unknown", + "ATI 88800GX-C", + "ATI 88800GX-D", + "ATI 88800GX-E", + "ATI 88800GX-F", + "ATI 88800GX", + "ATI 88800CX", + "ATI 264CT", + "ATI 264ET", + "ATI 264VT", + "ATI 3D Rage", + "ATI 264VT-B", + "ATI 3D Rage II", + "ATI 264VT3", + "ATI 3D Rage II+DVD", + "ATI 3D Rage LT", + "ATI 264VT4", + "ATI 3D Rage IIc", + "ATI 3D Rage Pro", + "ATI 3D Rage LT Pro", + "ATI 3D Rage XL or XC", + "ATI 3D Rage Mobility", + "ATI unknown Mach64", + "ATI Rage 128 GL", + "ATI Rage 128 VR", + "ATI Rage 128 Pro GL", + "ATI Rage 128 Pro VR", + "ATI Rage 128 Pro ULTRA", + "ATI Rage 128 Mobility M3", + "ATI Rage 128 Mobility M4", + "ATI unknown Rage 128" + "ATI Radeon 7200", + "ATI Radeon 7000 (VE)", + "ATI Radeon Mobility M6", + "ATI Radeon IGP320", + "ATI Radeon IGP330/340/350", + "ATI Radeon 7000 IGP", + "ATI Radeon 7500", + "ATI Radeon Mobility M7", + "ATI Radeon 8500/9100", + "ATI Radeon 9000", + "ATI Radeon Mobility M9", + "ATI Radeon 9100 IGP", + "ATI Radeon 9200 IGP", + "ATI Radeon 9200", + "ATI Radeon Mobility M9+", + "ATI Radeon 9700/9500", + "ATI Radeon 9600/9550", + "ATI Radeon 9800", + "ATI Radeon 9800XT", + "ATI Radeon X300/X550/M22", + "ATI Radeon X600/X550/M24", + "ATI Radeon X800/M18 AGP", + "ATI Radeon X800/M28 PCIE", + "ATI Radeon X800XL PCIE", + "ATI Radeon X850 PCIE", + "ATI Radeon X850 AGP", + "ATI Radeon X700", + "ATI Xpress 200" + "ATI unknown Radeon", + "ATI Rage HDTV" +}; + +#include "atichip.h" + +/* + * ATIChipID -- + * + * This returns the ATI_CHIP_* value (generally) associated with a particular + * ChipID/ChipRev combination. + */ +ATIChipType +ATIChipID +( + const CARD16 ChipID, + const CARD8 ChipRev +) +{ + switch (ChipID) + { + case OldChipID('G', 'X'): case NewChipID('G', 'X'): + switch (ChipRev) + { + case 0x00U: + return ATI_CHIP_88800GXC; + + case 0x01U: + return ATI_CHIP_88800GXD; + + case 0x02U: + return ATI_CHIP_88800GXE; + + case 0x03U: + return ATI_CHIP_88800GXF; + + default: + return ATI_CHIP_88800GX; + } + + case OldChipID('C', 'X'): case NewChipID('C', 'X'): + return ATI_CHIP_88800CX; + + case OldChipID('C', 'T'): case NewChipID('C', 'T'): + return ATI_CHIP_264CT; + + case OldChipID('E', 'T'): case NewChipID('E', 'T'): + return ATI_CHIP_264ET; + + case OldChipID('V', 'T'): case NewChipID('V', 'T'): + /* For simplicity, ignore ChipID discrepancy that can occur here */ + if (!(ChipRev & GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV))) + return ATI_CHIP_264VT; + return ATI_CHIP_264VTB; + + case OldChipID('G', 'T'): case NewChipID('G', 'T'): + if (!(ChipRev & GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV))) + return ATI_CHIP_264GT; + return ATI_CHIP_264GTB; + + case OldChipID('V', 'U'): case NewChipID('V', 'U'): + return ATI_CHIP_264VT3; + + case OldChipID('G', 'U'): case NewChipID('G', 'U'): + return ATI_CHIP_264GTDVD; + + case OldChipID('L', 'G'): case NewChipID('L', 'G'): + return ATI_CHIP_264LT; + + case OldChipID('V', 'V'): case NewChipID('V', 'V'): + return ATI_CHIP_264VT4; + + case OldChipID('G', 'V'): case NewChipID('G', 'V'): + case OldChipID('G', 'W'): case NewChipID('G', 'W'): + case OldChipID('G', 'Y'): case NewChipID('G', 'Y'): + case OldChipID('G', 'Z'): case NewChipID('G', 'Z'): + return ATI_CHIP_264GT2C; + + case OldChipID('G', 'B'): case NewChipID('G', 'B'): + case OldChipID('G', 'D'): case NewChipID('G', 'D'): + case OldChipID('G', 'I'): case NewChipID('G', 'I'): + case OldChipID('G', 'P'): case NewChipID('G', 'P'): + case OldChipID('G', 'Q'): case NewChipID('G', 'Q'): + return ATI_CHIP_264GTPRO; + + case OldChipID('L', 'B'): case NewChipID('L', 'B'): + case OldChipID('L', 'D'): case NewChipID('L', 'D'): + case OldChipID('L', 'I'): case NewChipID('L', 'I'): + case OldChipID('L', 'P'): case NewChipID('L', 'P'): + case OldChipID('L', 'Q'): case NewChipID('L', 'Q'): + return ATI_CHIP_264LTPRO; + + case OldChipID('G', 'L'): case NewChipID('G', 'L'): + case OldChipID('G', 'M'): case NewChipID('G', 'M'): + case OldChipID('G', 'N'): case NewChipID('G', 'N'): + case OldChipID('G', 'O'): case NewChipID('G', 'O'): + case OldChipID('G', 'R'): case NewChipID('G', 'R'): + case OldChipID('G', 'S'): case NewChipID('G', 'S'): + return ATI_CHIP_264XL; + + case OldChipID('L', 'M'): case NewChipID('L', 'M'): + case OldChipID('L', 'N'): case NewChipID('L', 'N'): + case OldChipID('L', 'R'): case NewChipID('L', 'R'): + case OldChipID('L', 'S'): case NewChipID('L', 'S'): + return ATI_CHIP_MOBILITY; + + case NewChipID('R', 'E'): + case NewChipID('R', 'F'): + case NewChipID('R', 'G'): + case NewChipID('S', 'K'): + case NewChipID('S', 'L'): + case NewChipID('S', 'M'): + /* "SN" is listed as ATI_CHIP_RAGE128_4X in ATI docs */ + case NewChipID('S', 'N'): + return ATI_CHIP_RAGE128GL; + + case NewChipID('R', 'K'): + case NewChipID('R', 'L'): + /* + * ATI documentation lists SE/SF/SG under both ATI_CHIP_RAGE128VR + * and ATI_CHIP_RAGE128_4X, and lists SH/SK/SL under Rage 128 4X only. + * I'm stuffing them here for now until this can be clarified as ATI + * documentation doesn't mention their details. <mharris@redhat.com> + */ + case NewChipID('S', 'E'): + case NewChipID('S', 'F'): + case NewChipID('S', 'G'): + case NewChipID('S', 'H'): + return ATI_CHIP_RAGE128VR; + + /* case NewChipID('S', 'H'): */ + /* case NewChipID('S', 'K'): */ + /* case NewChipID('S', 'L'): */ + /* case NewChipID('S', 'N'): */ + /* return ATI_CHIP_RAGE128_4X; */ + + case NewChipID('P', 'A'): + case NewChipID('P', 'B'): + case NewChipID('P', 'C'): + case NewChipID('P', 'D'): + case NewChipID('P', 'E'): + case NewChipID('P', 'F'): + return ATI_CHIP_RAGE128PROGL; + + case NewChipID('P', 'G'): + case NewChipID('P', 'H'): + case NewChipID('P', 'I'): + case NewChipID('P', 'J'): + case NewChipID('P', 'K'): + case NewChipID('P', 'L'): + case NewChipID('P', 'M'): + case NewChipID('P', 'N'): + case NewChipID('P', 'O'): + case NewChipID('P', 'P'): + case NewChipID('P', 'Q'): + case NewChipID('P', 'R'): + case NewChipID('P', 'S'): + case NewChipID('P', 'T'): + case NewChipID('P', 'U'): + case NewChipID('P', 'V'): + case NewChipID('P', 'W'): + case NewChipID('P', 'X'): + return ATI_CHIP_RAGE128PROVR; + + case NewChipID('T', 'F'): + case NewChipID('T', 'L'): + case NewChipID('T', 'R'): + case NewChipID('T', 'S'): + case NewChipID('T', 'T'): + case NewChipID('T', 'U'): + return ATI_CHIP_RAGE128PROULTRA; + + case NewChipID('L', 'E'): + case NewChipID('L', 'F'): + /* + * "LK" and "LL" are not in any ATI documentation I can find + * - mharris + */ + case NewChipID('L', 'K'): + case NewChipID('L', 'L'): + return ATI_CHIP_RAGE128MOBILITY3; + + case NewChipID('M', 'F'): + case NewChipID('M', 'L'): + return ATI_CHIP_RAGE128MOBILITY4; + + case NewChipID('Q', 'D'): + case NewChipID('Q', 'E'): + case NewChipID('Q', 'F'): + case NewChipID('Q', 'G'): + return ATI_CHIP_RADEON; + + case NewChipID('Q', 'Y'): + case NewChipID('Q', 'Z'): + case NewChipID('Q', '^'): + return ATI_CHIP_RADEONVE; + + case NewChipID('L', 'Y'): + case NewChipID('L', 'Z'): + return ATI_CHIP_RADEONMOBILITY6; + + case NewChipID('A', '6'): + case NewChipID('C', '6'): + return ATI_CHIP_RS100; + + case NewChipID('A', '7'): + case NewChipID('C', '7'): + return ATI_CHIP_RS200; + + case NewChipID('D', '7'): + case NewChipID('B', '7'): + return ATI_CHIP_RS250; + + case NewChipID('L', 'W'): + case NewChipID('L', 'X'): + return ATI_CHIP_RADEONMOBILITY7; + + case NewChipID('Q', 'H'): + case NewChipID('Q', 'I'): + case NewChipID('Q', 'J'): + case NewChipID('Q', 'K'): + case NewChipID('Q', 'L'): + case NewChipID('Q', 'M'): + case NewChipID('Q', 'N'): + case NewChipID('Q', 'O'): + case NewChipID('Q', 'h'): + case NewChipID('Q', 'i'): + case NewChipID('Q', 'j'): + case NewChipID('Q', 'k'): + case NewChipID('Q', 'l'): + case NewChipID('B', 'B'): + return ATI_CHIP_R200; + + case NewChipID('Q', 'W'): + case NewChipID('Q', 'X'): + return ATI_CHIP_RV200; + + case NewChipID('I', 'f'): + case NewChipID('I', 'g'): + return ATI_CHIP_RV250; + + case NewChipID('L', 'd'): + case NewChipID('L', 'f'): + case NewChipID('L', 'g'): + return ATI_CHIP_RADEONMOBILITY9; + + case NewChipID('X', '4'): + case NewChipID('X', '5'): + return ATI_CHIP_RS300; + + case NewChipID('x', '4'): + case NewChipID('x', '5'): + return ATI_CHIP_RS350; + + case NewChipID('Y', '\''): + case NewChipID('Y', 'a'): + case NewChipID('Y', 'b'): + case NewChipID('Y', 'd'): + case NewChipID('Y', 'e'): + return ATI_CHIP_RV280; + + case NewChipID('\\', 'a'): + case NewChipID('\\', 'c'): + return ATI_CHIP_RADEONMOBILITY9PLUS; + + case NewChipID('A', 'D'): + case NewChipID('A', 'E'): + case NewChipID('A', 'F'): + case NewChipID('A', 'G'): + case NewChipID('N', 'D'): + case NewChipID('N', 'E'): + case NewChipID('N', 'F'): + case NewChipID('N', 'G'): + return ATI_CHIP_R300; + + case NewChipID('A', 'H'): + case NewChipID('A', 'I'): + case NewChipID('A', 'J'): + case NewChipID('A', 'K'): + case NewChipID('N', 'H'): + case NewChipID('N', 'I'): + case NewChipID('N', 'K'): + return ATI_CHIP_R350; + + case NewChipID('A', 'P'): + case NewChipID('A', 'Q'): + case NewChipID('A', 'R'): + case NewChipID('A', 'S'): + case NewChipID('A', 'T'): + case NewChipID('A', 'U'): + case NewChipID('A', 'V'): + case NewChipID('N', 'P'): + case NewChipID('N', 'Q'): + case NewChipID('N', 'R'): + case NewChipID('N', 'S'): + case NewChipID('N', 'T'): + case NewChipID('N', 'V'): + return ATI_CHIP_RV350; + + case NewChipID('N', 'J'): + return ATI_CHIP_R360; + + case NewChipID('[', '\''): + case NewChipID('[', 'b'): + case NewChipID('[', 'c'): + case NewChipID('[', 'd'): + case NewChipID('[', 'e'): + case NewChipID('T', '\''): + case NewChipID('T', 'b'): + case NewChipID('T', 'd'): + return ATI_CHIP_RV370; + + case NewChipID('>', 'P'): + case NewChipID('>', 'T'): + case NewChipID('1', 'P'): + case NewChipID('1', 'R'): + case NewChipID('1', 'T'): + return ATI_CHIP_RV380; + + case NewChipID('J', 'H'): + case NewChipID('J', 'I'): + case NewChipID('J', 'J'): + case NewChipID('J', 'K'): + case NewChipID('J', 'L'): + case NewChipID('J', 'M'): + case NewChipID('J', 'N'): + case NewChipID('J', 'O'): + case NewChipID('J', 'P'): + case NewChipID('J', 'T'): + return ATI_CHIP_R420; + + case NewChipID('U', 'H'): + case NewChipID('U', 'I'): + case NewChipID('U', 'J'): + case NewChipID('U', 'K'): + case NewChipID('U', 'P'): + case NewChipID('U', 'Q'): + case NewChipID('U', 'R'): + case NewChipID('U', 'T'): + case NewChipID(']', 'W'): + /* those are m28, not 100% certain they are r423 could + be r480 but not r430 as their pci id names indicate... */ + case NewChipID(']', 'H'): + case NewChipID(']', 'I'): + case NewChipID(']', 'J'): + return ATI_CHIP_R423; + + case NewChipID('U', 'L'): + case NewChipID('U', 'M'): + case NewChipID('U', 'N'): + case NewChipID('U', 'O'): + return ATI_CHIP_R430; + + case NewChipID(']', 'L'): + case NewChipID(']', 'M'): + case NewChipID(']', 'N'): + case NewChipID(']', 'O'): + case NewChipID(']', 'P'): + case NewChipID(']', 'R'): + return ATI_CHIP_R480; + + case NewChipID('K', 'I'): + case NewChipID('K', 'J'): + case NewChipID('K', 'K'): + case NewChipID('K', 'L'): + return ATI_CHIP_R481; + + case NewChipID('^', 'H'): + case NewChipID('^', 'J'): + case NewChipID('^', 'K'): + case NewChipID('^', 'L'): + case NewChipID('^', 'M'): + case NewChipID('^', 'O'): + case NewChipID('V', 'J'): + case NewChipID('V', 'K'): + case NewChipID('V', 'O'): + case NewChipID('V', 'R'): + case NewChipID('V', 'S'): + return ATI_CHIP_RV410; + + case NewChipID('Z', 'A'): + case NewChipID('Z', 'B'): + case NewChipID('Z', 'a'): + case NewChipID('Z', 'b'): + case NewChipID('Y', 'T'): + case NewChipID('Y', 'U'): + case NewChipID('Y', 't'): + case NewChipID('Y', 'u'): + return ATI_CHIP_RS400; + + case NewChipID('H', 'D'): + return ATI_CHIP_HDTV; + + default: + /* + * Treat anything else as an unknown Radeon. Please keep the above + * up-to-date however, as it serves as a central chip list. + */ + return ATI_CHIP_Radeon; + } +} @@ -33,4 +33,76 @@ extern DriverRec ATI; +/* + * Chip-related definitions. + */ +typedef enum +{ + ATI_CHIP_NONE = 0, + ATI_CHIP_88800GXC, /* Mach64 */ + ATI_CHIP_88800GXD, /* Mach64 */ + ATI_CHIP_88800GXE, /* Mach64 */ + ATI_CHIP_88800GXF, /* Mach64 */ + ATI_CHIP_88800GX, /* Mach64 */ + ATI_CHIP_88800CX, /* Mach64 */ + ATI_CHIP_264CT, /* Mach64 */ + ATI_CHIP_264ET, /* Mach64 */ + ATI_CHIP_264VT, /* Mach64 */ + ATI_CHIP_264GT, /* Mach64 */ + ATI_CHIP_264VTB, /* Mach64 */ + ATI_CHIP_264GTB, /* Mach64 */ + ATI_CHIP_264VT3, /* Mach64 */ + ATI_CHIP_264GTDVD, /* Mach64 */ + ATI_CHIP_264LT, /* Mach64 */ + ATI_CHIP_264VT4, /* Mach64 */ + ATI_CHIP_264GT2C, /* Mach64 */ + ATI_CHIP_264GTPRO, /* Mach64 */ + ATI_CHIP_264LTPRO, /* Mach64 */ + ATI_CHIP_264XL, /* Mach64 */ + ATI_CHIP_MOBILITY, /* Mach64 */ + ATI_CHIP_Mach64, /* Last among Mach64's */ + ATI_CHIP_RAGE128GL, /* Rage128 */ + ATI_CHIP_RAGE128VR, /* Rage128 */ + ATI_CHIP_RAGE128PROGL, /* Rage128 */ + ATI_CHIP_RAGE128PROVR, /* Rage128 */ + ATI_CHIP_RAGE128PROULTRA, /* Rage128 */ + ATI_CHIP_RAGE128MOBILITY3, /* Rage128 */ + ATI_CHIP_RAGE128MOBILITY4, /* Rage128 */ + ATI_CHIP_Rage128, /* Last among Rage128's */ + ATI_CHIP_RADEON, /* Radeon */ + ATI_CHIP_RADEONVE, /* Radeon VE */ + ATI_CHIP_RADEONMOBILITY6, /* Radeon M6 */ + ATI_CHIP_RS100, /* IGP320 */ + ATI_CHIP_RS200, /* IGP340 */ + ATI_CHIP_RS250, /* Radoen 7000 IGP */ + ATI_CHIP_RV200, /* RV200 */ + ATI_CHIP_RADEONMOBILITY7, /* Radeon M7 */ + ATI_CHIP_R200, /* R200 */ + ATI_CHIP_RV250, /* RV250 */ + ATI_CHIP_RADEONMOBILITY9, /* Radeon M9 */ + ATI_CHIP_RS300, /* Radoen 9100 IGP */ + ATI_CHIP_RS350, /* Radoen 9200 IGP */ + ATI_CHIP_RV280, /* RV250 */ + ATI_CHIP_RADEONMOBILITY9PLUS, /* Radeon M9+ */ + ATI_CHIP_R300, /* R300 */ + ATI_CHIP_RV350, /* RV350/M10/M11 */ + ATI_CHIP_R350, /* R350 */ + ATI_CHIP_R360, /* R360 */ + ATI_CHIP_RV370, /* RV370/M22 */ + ATI_CHIP_RV380, /* RV380/M24 */ + ATI_CHIP_R420, /* R420/M18 */ + ATI_CHIP_R423, /* R423/M28? */ + ATI_CHIP_R430, /* R430 */ + ATI_CHIP_R480, /* R480/M28? */ + ATI_CHIP_R481, /* R481 */ + ATI_CHIP_RV410, /* RV410, M26 */ + ATI_CHIP_RS400, /* RS400, RS410, RS480, RS482, ... */ + ATI_CHIP_Radeon, /* Last among Radeon's */ + ATI_CHIP_HDTV /* HDTV */ +} ATIChipType; + +extern const char *ATIChipNames[]; + +extern ATIChipType ATIChipID(const CARD16, const CARD8); + #endif /* ___ATI_H___ */ diff --git a/src/atiadjust.c b/src/atiadjust.c index f01fee69..267186f4 100644 --- a/src/atiadjust.c +++ b/src/atiadjust.c @@ -82,7 +82,7 @@ ATIAdjustPreInit * displayed location in video memory. This is used to implement the virtual * window. */ -_X_EXPORT void +void ATIAdjustFrame ( int scrnIndex, diff --git a/src/atichip.c b/src/atichip.c index ddc7e0a7..5f8a2216 100644 --- a/src/atichip.c +++ b/src/atichip.c @@ -30,74 +30,6 @@ #include "atimach64io.h" #include "ativersion.h" -/* - * Chip-related definitions. - */ -const char *ATIChipNames[] = -{ - "Unknown", - "ATI 88800GX-C", - "ATI 88800GX-D", - "ATI 88800GX-E", - "ATI 88800GX-F", - "ATI 88800GX", - "ATI 88800CX", - "ATI 264CT", - "ATI 264ET", - "ATI 264VT", - "ATI 3D Rage", - "ATI 264VT-B", - "ATI 3D Rage II", - "ATI 264VT3", - "ATI 3D Rage II+DVD", - "ATI 3D Rage LT", - "ATI 264VT4", - "ATI 3D Rage IIc", - "ATI 3D Rage Pro", - "ATI 3D Rage LT Pro", - "ATI 3D Rage XL or XC", - "ATI 3D Rage Mobility", - "ATI unknown Mach64", - "ATI Rage 128 GL", - "ATI Rage 128 VR", - "ATI Rage 128 Pro GL", - "ATI Rage 128 Pro VR", - "ATI Rage 128 Pro ULTRA", - "ATI Rage 128 Mobility M3", - "ATI Rage 128 Mobility M4", - "ATI unknown Rage 128" - "ATI Radeon 7200", - "ATI Radeon 7000 (VE)", - "ATI Radeon Mobility M6", - "ATI Radeon IGP320", - "ATI Radeon IGP330/340/350", - "ATI Radeon 7000 IGP", - "ATI Radeon 7500", - "ATI Radeon Mobility M7", - "ATI Radeon 8500/9100", - "ATI Radeon 9000", - "ATI Radeon Mobility M9", - "ATI Radeon 9100 IGP", - "ATI Radeon 9200 IGP", - "ATI Radeon 9200", - "ATI Radeon Mobility M9+", - "ATI Radeon 9700/9500", - "ATI Radeon 9600/9550", - "ATI Radeon 9800", - "ATI Radeon 9800XT", - "ATI Radeon X300/X550/M22", - "ATI Radeon X600/X550/M24", - "ATI Radeon X800/M18 AGP", - "ATI Radeon X800/M28 PCIE", - "ATI Radeon X800XL PCIE", - "ATI Radeon X850 PCIE", - "ATI Radeon X850 AGP", - "ATI Radeon X700", - "ATI Xpress 200" - "ATI unknown Radeon", - "ATI Rage HDTV" -}; - const char *ATIFoundryNames[] = { "SGS", "NEC", "KCS", "UMC", "TSMC", "5", "6", "UMC" }; @@ -115,18 +47,18 @@ ATIMach64ChipID ) { pATI->config_chip_id = inr(CONFIG_CHIP_ID); - pATI->ChipType = GetBits(pATI->config_chip_id, 0xFFFFU); + pATI->ChipType = GetBits(pATI->config_chip_id, CFG_CHIP_TYPE); pATI->ChipClass = GetBits(pATI->config_chip_id, CFG_CHIP_CLASS); - pATI->ChipRevision = GetBits(pATI->config_chip_id, CFG_CHIP_REV); + pATI->ChipRev = GetBits(pATI->config_chip_id, CFG_CHIP_REV); pATI->ChipVersion = GetBits(pATI->config_chip_id, CFG_CHIP_VERSION); pATI->ChipFoundry = GetBits(pATI->config_chip_id, CFG_CHIP_FOUNDRY); - pATI->ChipRev = pATI->ChipRevision; + pATI->ChipRevision = GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); switch (pATI->ChipType) { case OldChipID('G', 'X'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'X'): - switch (pATI->ChipRevision) + switch (pATI->ChipRev) { case 0x00U: pATI->Chip = ATI_CHIP_88800GXC; @@ -159,8 +91,6 @@ ATIMach64ChipID case OldChipID('C', 'T'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('C', 'T'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264CT; pATI->BusType = ATI_BUS_PCI; break; @@ -168,8 +98,6 @@ ATIMach64ChipID case OldChipID('E', 'T'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('E', 'T'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264ET; pATI->BusType = ATI_BUS_PCI; break; @@ -177,8 +105,6 @@ ATIMach64ChipID case OldChipID('V', 'T'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('V', 'T'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264VT; pATI->BusType = ATI_BUS_PCI; /* Some early GT's are detected as VT's */ @@ -199,8 +125,6 @@ ATIMach64ChipID case OldChipID('G', 'T'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'T'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->BusType = ATI_BUS_PCI; if (!pATI->ChipVersion) pATI->Chip = ATI_CHIP_264GT; @@ -211,8 +135,6 @@ ATIMach64ChipID case OldChipID('V', 'U'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('V', 'U'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264VT3; pATI->BusType = ATI_BUS_PCI; break; @@ -220,8 +142,6 @@ ATIMach64ChipID case OldChipID('G', 'U'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'U'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264GTDVD; pATI->BusType = ATI_BUS_PCI; break; @@ -229,8 +149,6 @@ ATIMach64ChipID case OldChipID('L', 'G'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('L', 'G'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264LT; pATI->BusType = ATI_BUS_PCI; break; @@ -238,8 +156,6 @@ ATIMach64ChipID case OldChipID('V', 'V'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('V', 'V'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264VT4; pATI->BusType = ATI_BUS_PCI; break; @@ -249,8 +165,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'V'): case NewChipID('G', 'Y'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264GT2C; pATI->BusType = ATI_BUS_PCI; break; @@ -260,8 +174,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'W'): case NewChipID('G', 'Z'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264GT2C; pATI->BusType = ATI_BUS_AGP; break; @@ -273,8 +185,6 @@ ATIMach64ChipID case NewChipID('G', 'I'): case NewChipID('G', 'P'): case NewChipID('G', 'Q'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264GTPRO; pATI->BusType = ATI_BUS_PCI; break; @@ -284,8 +194,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'B'): case NewChipID('G', 'D'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264GTPRO; pATI->BusType = ATI_BUS_AGP; break; @@ -297,8 +205,6 @@ ATIMach64ChipID case NewChipID('L', 'I'): case NewChipID('L', 'P'): case NewChipID('L', 'Q'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264LTPRO; pATI->BusType = ATI_BUS_PCI; pATI->LCDVBlendFIFOSize = 800; @@ -309,8 +215,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('L', 'B'): case NewChipID('L', 'D'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264LTPRO; pATI->BusType = ATI_BUS_AGP; pATI->LCDVBlendFIFOSize = 800; @@ -325,8 +229,6 @@ ATIMach64ChipID case NewChipID('G', 'O'): case NewChipID('G', 'R'): case NewChipID('G', 'S'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264XL; pATI->BusType = ATI_BUS_PCI; pATI->LCDVBlendFIFOSize = 1024; @@ -337,8 +239,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'M'): case NewChipID('G', 'N'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264XL; pATI->BusType = ATI_BUS_AGP; pATI->LCDVBlendFIFOSize = 1024; @@ -349,8 +249,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('L', 'R'): case NewChipID('L', 'S'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_MOBILITY; pATI->BusType = ATI_BUS_PCI; pATI->LCDVBlendFIFOSize = 1024; @@ -361,8 +259,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('L', 'M'): case NewChipID('L', 'N'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_MOBILITY; pATI->BusType = ATI_BUS_AGP; pATI->LCDVBlendFIFOSize = 1024; @@ -373,399 +269,3 @@ ATIMach64ChipID break; } } - -/* - * ATIChipID -- - * - * This returns the ATI_CHIP_* value (generally) associated with a particular - * ChipID/ChipRev combination. - */ -ATIChipType -ATIChipID -( - const CARD16 ChipID, - const CARD8 ChipRev -) -{ - switch (ChipID) - { - case OldChipID('G', 'X'): case NewChipID('G', 'X'): - switch (ChipRev) - { - case 0x00U: - return ATI_CHIP_88800GXC; - - case 0x01U: - return ATI_CHIP_88800GXD; - - case 0x02U: - return ATI_CHIP_88800GXE; - - case 0x03U: - return ATI_CHIP_88800GXF; - - default: - return ATI_CHIP_88800GX; - } - - case OldChipID('C', 'X'): case NewChipID('C', 'X'): - return ATI_CHIP_88800CX; - - case OldChipID('C', 'T'): case NewChipID('C', 'T'): - return ATI_CHIP_264CT; - - case OldChipID('E', 'T'): case NewChipID('E', 'T'): - return ATI_CHIP_264ET; - - case OldChipID('V', 'T'): case NewChipID('V', 'T'): - /* For simplicity, ignore ChipID discrepancy that can occur here */ - if (!(ChipRev & GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV))) - return ATI_CHIP_264VT; - return ATI_CHIP_264VTB; - - case OldChipID('G', 'T'): case NewChipID('G', 'T'): - if (!(ChipRev & GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV))) - return ATI_CHIP_264GT; - return ATI_CHIP_264GTB; - - case OldChipID('V', 'U'): case NewChipID('V', 'U'): - return ATI_CHIP_264VT3; - - case OldChipID('G', 'U'): case NewChipID('G', 'U'): - return ATI_CHIP_264GTDVD; - - case OldChipID('L', 'G'): case NewChipID('L', 'G'): - return ATI_CHIP_264LT; - - case OldChipID('V', 'V'): case NewChipID('V', 'V'): - return ATI_CHIP_264VT4; - - case OldChipID('G', 'V'): case NewChipID('G', 'V'): - case OldChipID('G', 'W'): case NewChipID('G', 'W'): - case OldChipID('G', 'Y'): case NewChipID('G', 'Y'): - case OldChipID('G', 'Z'): case NewChipID('G', 'Z'): - return ATI_CHIP_264GT2C; - - case OldChipID('G', 'B'): case NewChipID('G', 'B'): - case OldChipID('G', 'D'): case NewChipID('G', 'D'): - case OldChipID('G', 'I'): case NewChipID('G', 'I'): - case OldChipID('G', 'P'): case NewChipID('G', 'P'): - case OldChipID('G', 'Q'): case NewChipID('G', 'Q'): - return ATI_CHIP_264GTPRO; - - case OldChipID('L', 'B'): case NewChipID('L', 'B'): - case OldChipID('L', 'D'): case NewChipID('L', 'D'): - case OldChipID('L', 'I'): case NewChipID('L', 'I'): - case OldChipID('L', 'P'): case NewChipID('L', 'P'): - case OldChipID('L', 'Q'): case NewChipID('L', 'Q'): - return ATI_CHIP_264LTPRO; - - case OldChipID('G', 'L'): case NewChipID('G', 'L'): - case OldChipID('G', 'M'): case NewChipID('G', 'M'): - case OldChipID('G', 'N'): case NewChipID('G', 'N'): - case OldChipID('G', 'O'): case NewChipID('G', 'O'): - case OldChipID('G', 'R'): case NewChipID('G', 'R'): - case OldChipID('G', 'S'): case NewChipID('G', 'S'): - return ATI_CHIP_264XL; - - case OldChipID('L', 'M'): case NewChipID('L', 'M'): - case OldChipID('L', 'N'): case NewChipID('L', 'N'): - case OldChipID('L', 'R'): case NewChipID('L', 'R'): - case OldChipID('L', 'S'): case NewChipID('L', 'S'): - return ATI_CHIP_MOBILITY; - - case NewChipID('R', 'E'): - case NewChipID('R', 'F'): - case NewChipID('R', 'G'): - case NewChipID('S', 'K'): - case NewChipID('S', 'L'): - case NewChipID('S', 'M'): - /* "SN" is listed as ATI_CHIP_RAGE128_4X in ATI docs */ - case NewChipID('S', 'N'): - return ATI_CHIP_RAGE128GL; - - case NewChipID('R', 'K'): - case NewChipID('R', 'L'): - /* - * ATI documentation lists SE/SF/SG under both ATI_CHIP_RAGE128VR - * and ATI_CHIP_RAGE128_4X, and lists SH/SK/SL under Rage 128 4X only. - * I'm stuffing them here for now until this can be clarified as ATI - * documentation doesn't mention their details. <mharris@redhat.com> - */ - case NewChipID('S', 'E'): - case NewChipID('S', 'F'): - case NewChipID('S', 'G'): - case NewChipID('S', 'H'): - return ATI_CHIP_RAGE128VR; - - /* case NewChipID('S', 'H'): */ - /* case NewChipID('S', 'K'): */ - /* case NewChipID('S', 'L'): */ - /* case NewChipID('S', 'N'): */ - /* return ATI_CHIP_RAGE128_4X; */ - - case NewChipID('P', 'A'): - case NewChipID('P', 'B'): - case NewChipID('P', 'C'): - case NewChipID('P', 'D'): - case NewChipID('P', 'E'): - case NewChipID('P', 'F'): - return ATI_CHIP_RAGE128PROGL; - - case NewChipID('P', 'G'): - case NewChipID('P', 'H'): - case NewChipID('P', 'I'): - case NewChipID('P', 'J'): - case NewChipID('P', 'K'): - case NewChipID('P', 'L'): - case NewChipID('P', 'M'): - case NewChipID('P', 'N'): - case NewChipID('P', 'O'): - case NewChipID('P', 'P'): - case NewChipID('P', 'Q'): - case NewChipID('P', 'R'): - case NewChipID('P', 'S'): - case NewChipID('P', 'T'): - case NewChipID('P', 'U'): - case NewChipID('P', 'V'): - case NewChipID('P', 'W'): - case NewChipID('P', 'X'): - return ATI_CHIP_RAGE128PROVR; - - case NewChipID('T', 'F'): - case NewChipID('T', 'L'): - case NewChipID('T', 'R'): - case NewChipID('T', 'S'): - case NewChipID('T', 'T'): - case NewChipID('T', 'U'): - return ATI_CHIP_RAGE128PROULTRA; - - case NewChipID('L', 'E'): - case NewChipID('L', 'F'): - /* - * "LK" and "LL" are not in any ATI documentation I can find - * - mharris - */ - case NewChipID('L', 'K'): - case NewChipID('L', 'L'): - return ATI_CHIP_RAGE128MOBILITY3; - - case NewChipID('M', 'F'): - case NewChipID('M', 'L'): - return ATI_CHIP_RAGE128MOBILITY4; - - case NewChipID('Q', 'D'): - case NewChipID('Q', 'E'): - case NewChipID('Q', 'F'): - case NewChipID('Q', 'G'): - return ATI_CHIP_RADEON; - - case NewChipID('Q', 'Y'): - case NewChipID('Q', 'Z'): - case NewChipID('Q', '^'): - return ATI_CHIP_RADEONVE; - - case NewChipID('L', 'Y'): - case NewChipID('L', 'Z'): - return ATI_CHIP_RADEONMOBILITY6; - - case NewChipID('A', '6'): - case NewChipID('C', '6'): - return ATI_CHIP_RS100; - - case NewChipID('A', '7'): - case NewChipID('C', '7'): - return ATI_CHIP_RS200; - - case NewChipID('D', '7'): - case NewChipID('B', '7'): - return ATI_CHIP_RS250; - - case NewChipID('L', 'W'): - case NewChipID('L', 'X'): - return ATI_CHIP_RADEONMOBILITY7; - - case NewChipID('Q', 'H'): - case NewChipID('Q', 'I'): - case NewChipID('Q', 'J'): - case NewChipID('Q', 'K'): - case NewChipID('Q', 'L'): - case NewChipID('Q', 'M'): - case NewChipID('Q', 'N'): - case NewChipID('Q', 'O'): - case NewChipID('Q', 'h'): - case NewChipID('Q', 'i'): - case NewChipID('Q', 'j'): - case NewChipID('Q', 'k'): - case NewChipID('Q', 'l'): - case NewChipID('B', 'B'): - return ATI_CHIP_R200; - - case NewChipID('Q', 'W'): - case NewChipID('Q', 'X'): - return ATI_CHIP_RV200; - - case NewChipID('I', 'f'): - case NewChipID('I', 'g'): - return ATI_CHIP_RV250; - - case NewChipID('L', 'd'): - case NewChipID('L', 'f'): - case NewChipID('L', 'g'): - return ATI_CHIP_RADEONMOBILITY9; - - case NewChipID('X', '4'): - case NewChipID('X', '5'): - return ATI_CHIP_RS300; - - case NewChipID('x', '4'): - case NewChipID('x', '5'): - return ATI_CHIP_RS350; - - case NewChipID('Y', '\''): - case NewChipID('Y', 'a'): - case NewChipID('Y', 'b'): - case NewChipID('Y', 'd'): - case NewChipID('Y', 'e'): - return ATI_CHIP_RV280; - - case NewChipID('\\', 'a'): - case NewChipID('\\', 'c'): - return ATI_CHIP_RADEONMOBILITY9PLUS; - - case NewChipID('A', 'D'): - case NewChipID('A', 'E'): - case NewChipID('A', 'F'): - case NewChipID('A', 'G'): - case NewChipID('N', 'D'): - case NewChipID('N', 'E'): - case NewChipID('N', 'F'): - case NewChipID('N', 'G'): - return ATI_CHIP_R300; - - case NewChipID('A', 'H'): - case NewChipID('A', 'I'): - case NewChipID('A', 'J'): - case NewChipID('A', 'K'): - case NewChipID('N', 'H'): - case NewChipID('N', 'I'): - case NewChipID('N', 'K'): - return ATI_CHIP_R350; - - case NewChipID('A', 'P'): - case NewChipID('A', 'Q'): - case NewChipID('A', 'R'): - case NewChipID('A', 'S'): - case NewChipID('A', 'T'): - case NewChipID('A', 'U'): - case NewChipID('A', 'V'): - case NewChipID('N', 'P'): - case NewChipID('N', 'Q'): - case NewChipID('N', 'R'): - case NewChipID('N', 'S'): - case NewChipID('N', 'T'): - case NewChipID('N', 'V'): - return ATI_CHIP_RV350; - - case NewChipID('N', 'J'): - return ATI_CHIP_R360; - - case NewChipID('[', '\''): - case NewChipID('[', 'b'): - case NewChipID('[', 'c'): - case NewChipID('[', 'd'): - case NewChipID('[', 'e'): - case NewChipID('T', '\''): - case NewChipID('T', 'b'): - case NewChipID('T', 'd'): - return ATI_CHIP_RV370; - - case NewChipID('>', 'P'): - case NewChipID('>', 'T'): - case NewChipID('1', 'P'): - case NewChipID('1', 'R'): - case NewChipID('1', 'T'): - return ATI_CHIP_RV380; - - case NewChipID('J', 'H'): - case NewChipID('J', 'I'): - case NewChipID('J', 'J'): - case NewChipID('J', 'K'): - case NewChipID('J', 'L'): - case NewChipID('J', 'M'): - case NewChipID('J', 'N'): - case NewChipID('J', 'O'): - case NewChipID('J', 'P'): - case NewChipID('J', 'T'): - return ATI_CHIP_R420; - - case NewChipID('U', 'H'): - case NewChipID('U', 'I'): - case NewChipID('U', 'J'): - case NewChipID('U', 'K'): - case NewChipID('U', 'P'): - case NewChipID('U', 'Q'): - case NewChipID('U', 'R'): - case NewChipID('U', 'T'): - case NewChipID(']', 'W'): - /* those are m28, not 100% certain they are r423 could - be r480 but not r430 as their pci id names indicate... */ - case NewChipID(']', 'H'): - case NewChipID(']', 'I'): - case NewChipID(']', 'J'): - return ATI_CHIP_R423; - - case NewChipID('U', 'L'): - case NewChipID('U', 'M'): - case NewChipID('U', 'N'): - case NewChipID('U', 'O'): - return ATI_CHIP_R430; - - case NewChipID(']', 'L'): - case NewChipID(']', 'M'): - case NewChipID(']', 'N'): - case NewChipID(']', 'O'): - case NewChipID(']', 'P'): - case NewChipID(']', 'R'): - return ATI_CHIP_R480; - - case NewChipID('K', 'I'): - case NewChipID('K', 'J'): - case NewChipID('K', 'K'): - case NewChipID('K', 'L'): - return ATI_CHIP_R481; - - case NewChipID('^', 'H'): - case NewChipID('^', 'J'): - case NewChipID('^', 'K'): - case NewChipID('^', 'L'): - case NewChipID('^', 'M'): - case NewChipID('^', 'O'): - case NewChipID('V', 'J'): - case NewChipID('V', 'K'): - case NewChipID('V', 'O'): - case NewChipID('V', 'R'): - case NewChipID('V', 'S'): - return ATI_CHIP_RV410; - - case NewChipID('Z', 'A'): - case NewChipID('Z', 'B'): - case NewChipID('Z', 'a'): - case NewChipID('Z', 'b'): - case NewChipID('Y', 'T'): - case NewChipID('Y', 'U'): - case NewChipID('Y', 't'): - case NewChipID('Y', 'u'): - return ATI_CHIP_RS400; - - case NewChipID('H', 'D'): - return ATI_CHIP_HDTV; - - default: - /* - * Treat anything else as an unknown Radeon. Please keep the above - * up-to-date however, as it serves as a central chip list. - */ - return ATI_CHIP_Radeon; - } -} diff --git a/src/atichip.h b/src/atichip.h index 733c7b1f..44cd1888 100644 --- a/src/atichip.h +++ b/src/atichip.h @@ -29,76 +29,6 @@ #include <X11/Xmd.h> /* - * Chip-related definitions. - */ -typedef enum -{ - ATI_CHIP_NONE = 0, - ATI_CHIP_88800GXC, /* Mach64 */ - ATI_CHIP_88800GXD, /* Mach64 */ - ATI_CHIP_88800GXE, /* Mach64 */ - ATI_CHIP_88800GXF, /* Mach64 */ - ATI_CHIP_88800GX, /* Mach64 */ - ATI_CHIP_88800CX, /* Mach64 */ - ATI_CHIP_264CT, /* Mach64 */ - ATI_CHIP_264ET, /* Mach64 */ - ATI_CHIP_264VT, /* Mach64 */ - ATI_CHIP_264GT, /* Mach64 */ - ATI_CHIP_264VTB, /* Mach64 */ - ATI_CHIP_264GTB, /* Mach64 */ - ATI_CHIP_264VT3, /* Mach64 */ - ATI_CHIP_264GTDVD, /* Mach64 */ - ATI_CHIP_264LT, /* Mach64 */ - ATI_CHIP_264VT4, /* Mach64 */ - ATI_CHIP_264GT2C, /* Mach64 */ - ATI_CHIP_264GTPRO, /* Mach64 */ - ATI_CHIP_264LTPRO, /* Mach64 */ - ATI_CHIP_264XL, /* Mach64 */ - ATI_CHIP_MOBILITY, /* Mach64 */ - ATI_CHIP_Mach64, /* Last among Mach64's */ - ATI_CHIP_RAGE128GL, /* Rage128 */ - ATI_CHIP_RAGE128VR, /* Rage128 */ - ATI_CHIP_RAGE128PROGL, /* Rage128 */ - ATI_CHIP_RAGE128PROVR, /* Rage128 */ - ATI_CHIP_RAGE128PROULTRA, /* Rage128 */ - ATI_CHIP_RAGE128MOBILITY3, /* Rage128 */ - ATI_CHIP_RAGE128MOBILITY4, /* Rage128 */ - ATI_CHIP_Rage128, /* Last among Rage128's */ - ATI_CHIP_RADEON, /* Radeon */ - ATI_CHIP_RADEONVE, /* Radeon VE */ - ATI_CHIP_RADEONMOBILITY6, /* Radeon M6 */ - ATI_CHIP_RS100, /* IGP320 */ - ATI_CHIP_RS200, /* IGP340 */ - ATI_CHIP_RS250, /* Radoen 7000 IGP */ - ATI_CHIP_RV200, /* RV200 */ - ATI_CHIP_RADEONMOBILITY7, /* Radeon M7 */ - ATI_CHIP_R200, /* R200 */ - ATI_CHIP_RV250, /* RV250 */ - ATI_CHIP_RADEONMOBILITY9, /* Radeon M9 */ - ATI_CHIP_RS300, /* Radoen 9100 IGP */ - ATI_CHIP_RS350, /* Radoen 9200 IGP */ - ATI_CHIP_RV280, /* RV250 */ - ATI_CHIP_RADEONMOBILITY9PLUS, /* Radeon M9+ */ - ATI_CHIP_R300, /* R300 */ - ATI_CHIP_RV350, /* RV350/M10/M11 */ - ATI_CHIP_R350, /* R350 */ - ATI_CHIP_R360, /* R360 */ - ATI_CHIP_RV370, /* RV370/M22 */ - ATI_CHIP_RV380, /* RV380/M24 */ - ATI_CHIP_R420, /* R420/M18 */ - ATI_CHIP_R423, /* R423/M28? */ - ATI_CHIP_R430, /* R430 */ - ATI_CHIP_R480, /* R480/M28? */ - ATI_CHIP_R481, /* R481 */ - ATI_CHIP_RV410, /* RV410, M26 */ - ATI_CHIP_RS400, /* RS400, RS410, RS480, RS482, ... */ - ATI_CHIP_Radeon, /* Last among Radeon's */ - ATI_CHIP_HDTV /* HDTV */ -} ATIChipType; - -extern const char *ATIChipNames[]; - -/* * Foundry codes for 264xT's. */ typedef enum @@ -116,7 +46,6 @@ typedef enum extern const char *ATIFoundryNames[]; extern void ATIMach64ChipID(ATIPtr, const CARD16); -extern ATIChipType ATIChipID(const CARD16, const CARD8); #define OldChipID(_1, _0) \ (SetBits(_0 - 'A', CHIP_CODE_0) | SetBits(_1 - 'A', CHIP_CODE_1)) diff --git a/src/aticonfig.c b/src/aticonfig.c index a4ceddfc..1e119e00 100644 --- a/src/aticonfig.c +++ b/src/aticonfig.c @@ -234,7 +234,7 @@ static const OptionInfoRec ATIPublicOptions[] = static const unsigned long ATIPublicOptionSize = SizeOf(ATIPublicOptions); -_X_EXPORT const OptionInfoRec * +const OptionInfoRec * ATIOptionsWeak(void) { return ATIPublicOptions; } /* diff --git a/src/aticonsole.c b/src/aticonsole.c index 6d0c662a..bd5ec9c5 100644 --- a/src/aticonsole.c +++ b/src/aticonsole.c @@ -628,7 +628,7 @@ ATILeaveGraphics * * This function switches to another graphics video state. */ -_X_EXPORT Bool +Bool ATISwitchMode ( int iScreen, @@ -681,7 +681,7 @@ ATISwitchMode * * This function sets the server's virtual console to a graphics video state. */ -_X_EXPORT Bool +Bool ATIEnterVT ( int iScreen, @@ -751,7 +751,7 @@ ATIEnterVT * This function restores the server's virtual console to its state on server * entry. */ -_X_EXPORT void +void ATILeaveVT ( int iScreen, @@ -780,7 +780,7 @@ ATILeaveVT * * This function frees all driver data related to a screen. */ -_X_EXPORT void +void ATIFreeScreen ( int iScreen, diff --git a/src/atidri.c b/src/atidri.c index d017040c..bc862a89 100644 --- a/src/atidri.c +++ b/src/atidri.c @@ -1194,13 +1194,13 @@ Bool ATIDRIScreenInit( ScreenPtr pScreen ) /* Check the DRI version */ DRIQueryVersion( &major, &minor, &patch ); - if ( major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION ) { + if ( major != DRIINFO_MAJOR_VERSION || minor < 0 ) { xf86DrvMsg( pScreen->myNum, X_ERROR, "[dri] ATIDRIScreenInit failed because of a version mismatch.\n" "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n" "[dri] Disabling the DRI.\n", major, minor, patch, - DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION ); + DRIINFO_MAJOR_VERSION, 0 ); return FALSE; } @@ -1266,9 +1266,10 @@ Bool ATIDRIScreenInit( ScreenPtr pScreen ) ErrorF( "[dri] Data does not fit in SAREA\n" ); return FALSE; } - xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, "[drm] SAREA %d+%d: %d\n", - sizeof(XF86DRISAREARec), sizeof(ATISAREAPrivRec), - sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec) ); + xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, "[drm] SAREA %u+%u: %u\n", + (unsigned)sizeof(XF86DRISAREARec), + (unsigned)sizeof(ATISAREAPrivRec), + (unsigned)(sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec)) ); pDRIInfo->SAREASize = SAREA_MAX; pATIDRI = (ATIDRIPtr) xnfcalloc( sizeof(ATIDRIRec), 1 ); diff --git a/src/atifillin.c b/src/atifillin.c deleted file mode 100644 index dcbcb3c8..00000000 --- a/src/atifillin.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2004 Adam Jackson. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * atifillin.c: fill in a ScrnInfoPtr with the relevant information for - * atimisc. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "atifillin.h" - -_X_EXPORT void ATIFillInScreenInfo(ScrnInfoPtr pScreenInfo) -{ - pScreenInfo->driverVersion = ATI_VERSION_CURRENT; - pScreenInfo->driverName = ATI_DRIVER_NAME; - pScreenInfo->name = ATI_NAME; - pScreenInfo->PreInit = ATIPreInit; - pScreenInfo->ScreenInit = ATIScreenInit; - pScreenInfo->SwitchMode = ATISwitchMode; - pScreenInfo->AdjustFrame = ATIAdjustFrame; - pScreenInfo->EnterVT = ATIEnterVT; - pScreenInfo->LeaveVT = ATILeaveVT; - pScreenInfo->FreeScreen = ATIFreeScreen; - pScreenInfo->ValidMode = ATIValidMode; -} diff --git a/src/atifillin.h b/src/atifillin.h deleted file mode 100644 index 7d5e54da..00000000 --- a/src/atifillin.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2004 Adam Jackson. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * atifillin.h: header for atifillin.c. - */ - -#ifndef ATI_FILLIN_H -#define ATI_FILLIN_H - -/* include headers corresponding to fields touched by ATIFillInScreenInfo() */ - -#include "ativersion.h" -#include "atipreinit.h" -#include "atiscreen.h" -#include "aticonsole.h" -#include "atiadjust.h" -#include "ativalid.h" - -extern void ATIFillInScreenInfo(ScrnInfoPtr); - -#endif diff --git a/src/atimach64probe.c b/src/atimach64probe.c index 47340a56..c5330cc7 100644 --- a/src/atimach64probe.c +++ b/src/atimach64probe.c @@ -26,14 +26,19 @@ #include "ati.h" #include "atichip.h" -#include "atifillin.h" -#include "atimodule.h" #include "atimach64io.h" #include "atimach64probe.h" #include "atioption.h" #include "ativersion.h" -static SymTabRec +/* include headers corresponding to ScrnInfoPtr fields */ +#include "atipreinit.h" +#include "atiscreen.h" +#include "aticonsole.h" +#include "atiadjust.h" +#include "ativalid.h" + +SymTabRec Mach64Chipsets[] = { {ATI_CHIP_88800GXC, "ATI 88800GX-C"}, {ATI_CHIP_88800GXD, "ATI 88800GX-D"}, @@ -101,7 +106,7 @@ Mach64PciChipsets[] = { {-1, -1, RES_UNDEFINED} }; -const OptionInfoRec * +_X_EXPORT const OptionInfoRec * Mach64AvailableOptions(int chipid, int busid) { /* @@ -112,24 +117,39 @@ Mach64AvailableOptions(int chipid, int busid) } /* + * Mach64Identify -- + * + * Print the driver's list of chipset names. + */ +_X_EXPORT void +Mach64Identify +( + int flags +) +{ + xf86Msg(X_INFO, "%s: %s\n", ATI_NAME, + "Driver for ATI Mach64 chipsets"); +} + +/* * Mach64Probe -- * * This function is called once, at the start of the first server generation to * do a minimal probe for supported hardware. */ -Bool +_X_EXPORT Bool Mach64Probe(DriverPtr pDriver, int flags) { - GDevPtr *devSections; - int *usedChips; - int numDevSections; - int numUsed; - Bool ProbeSuccess = FALSE; + GDevPtr *devSections; + int *usedChips; + int numDevSections; + int numUsed; + Bool ProbeSuccess = FALSE; - if ((numDevSections = xf86MatchDevice(ATI_DRIVER_NAME, &devSections)) <= 0) + if (xf86GetPciVideoInfo() == NULL) return FALSE; - if (xf86GetPciVideoInfo() == NULL) + if ((numDevSections = xf86MatchDevice(ATI_DRIVER_NAME, &devSections)) <= 0) return FALSE; numUsed = xf86MatchPciInstances(ATI_DRIVER_NAME, PCI_VENDOR_ATI, @@ -148,8 +168,6 @@ Mach64Probe(DriverPtr pDriver, int flags) for (i = 0; i < numUsed; i++) { ScrnInfoPtr pScrn; - EntityInfoPtr pEnt; - pciVideoPtr pVideo; pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i], Mach64PciChipsets, 0, 0, 0, 0, NULL); @@ -157,30 +175,24 @@ Mach64Probe(DriverPtr pDriver, int flags) if (!pScrn) continue; - pEnt = xf86GetEntityInfo(usedChips[i]); - pVideo = xf86GetPciInfoForEntity(usedChips[i]); - -#ifdef XFree86LOADER - - if (!xf86LoadSubModule(pScrn, "atimisc")) - { - xf86Msg(X_ERROR, - ATI_NAME ": Failed to load \"atimisc\" module.\n"); - xf86DeleteScreen(pScrn->scrnIndex, 0); - continue; - } - - xf86LoaderReqSymLists(ATISymbols, NULL); - -#endif - - ATIFillInScreenInfo(pScrn); - - pScrn->Probe = Mach64Probe; + pScrn->driverVersion = ATI_VERSION_CURRENT; + pScrn->driverName = ATI_DRIVER_NAME; + pScrn->name = ATI_NAME; + pScrn->Probe = Mach64Probe; + pScrn->PreInit = ATIPreInit; + pScrn->ScreenInit = ATIScreenInit; + pScrn->SwitchMode = ATISwitchMode; + pScrn->AdjustFrame = ATIAdjustFrame; + pScrn->EnterVT = ATIEnterVT; + pScrn->LeaveVT = ATILeaveVT; + pScrn->FreeScreen = ATIFreeScreen; + pScrn->ValidMode = ATIValidMode; ProbeSuccess = TRUE; } } + xfree(usedChips); + return ProbeSuccess; } diff --git a/src/atimach64probe.h b/src/atimach64probe.h index 4e474ca3..65ced985 100644 --- a/src/atimach64probe.h +++ b/src/atimach64probe.h @@ -25,7 +25,10 @@ #include "xf86str.h" +extern SymTabRec Mach64Chipsets[]; + extern const OptionInfoRec * Mach64AvailableOptions(int, int); +extern void Mach64Identify(int); extern Bool Mach64Probe(DriverPtr, int); #endif /* ___ATIMACH64PROBE_H___ */ diff --git a/src/atimach64xv.c b/src/atimach64xv.c index 997fa699..67bececf 100644 --- a/src/atimach64xv.c +++ b/src/atimach64xv.c @@ -979,6 +979,9 @@ ATIMach64PutImage if (pATI->ActiveSurface) return Success; + if (DstH < 16) + return Success; + if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID, SrcX, SrcY, SrcW, SrcH, DstX, DstY, &DstW, &DstH, diff --git a/src/atimodule.c b/src/atimodule.c index 05456e7c..6aa9a2e7 100644 --- a/src/atimodule.c +++ b/src/atimodule.c @@ -34,47 +34,25 @@ const char *ATISymbols[] = { - "ATIPreInit", - "ATIScreenInit", - "ATISwitchMode", - "ATIAdjustFrame", - "ATIEnterVT", - "ATILeaveVT", - "ATIFreeScreen", - "ATIValidMode", - "ATIOptionsWeak", - "ATIFillInScreenInfo", + "Mach64Identify", + "Mach64Probe", + "Mach64AvailableOptions", NULL }; const char *R128Symbols[] = { - "R128PreInit", - "R128ScreenInit", - "R128SwitchMode", - "R128AdjustFrame", - "R128EnterVT", - "R128LeaveVT", - "R128FreeScreen", - "R128ValidMode", - "R128OptionsWeak", - "R128FillInScreenInfo", + "R128Identify", + "R128Probe", + "R128AvailableOptions", NULL }; const char *RADEONSymbols[] = { - "RADEONPreInit", - "RADEONScreenInit", - "RADEONSwitchMode", - "RADEONAdjustFrame", - "RADEONEnterVT", - "RADEONLeaveVT", - "RADEONFreeScreen", - "RADEONValidMode", - "RADEONOptionsWeak", - "RADEONHandleMessage", - "RADEONFillInScreenInfo", + "RADEONIdentify", + "RADEONProbe", + "RADEONAvailableOptions", NULL }; diff --git a/src/atipreinit.c b/src/atipreinit.c index 018f2fb1..8114f512 100644 --- a/src/atipreinit.c +++ b/src/atipreinit.c @@ -41,6 +41,7 @@ #include "atimach64.h" #include "atimach64accel.h" #include "atimach64io.h" +#include "atimach64probe.h" #include "atimode.h" #include "atioption.h" #include "atipreinit.h" @@ -128,7 +129,7 @@ ATIPrintNoiseIfRequested * This function is only called once per screen at the start of the first * server generation. */ -_X_EXPORT Bool +Bool ATIPreInit ( ScrnInfoPtr pScreenInfo, @@ -955,7 +956,8 @@ ATIPreInit /* Report what was found */ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, - "%s graphics controller detected.\n", ATIChipNames[pATI->Chip]); + "%s graphics controller detected.\n", + xf86TokenToString(Mach64Chipsets, pATI->Chip)); { Message = Buffer + snprintf(Buffer, SizeOf(Buffer), "Chip type %04X", diff --git a/src/atiprobe.c b/src/atiprobe.c index b82ea5f8..cddcc613 100644 --- a/src/atiprobe.c +++ b/src/atiprobe.c @@ -31,7 +31,6 @@ #include "atibus.h" #include "atichip.h" #include "atimach64io.h" -#include "atimodule.h" #include "atiprobe.h" #include "ativersion.h" #include "atividmem.h" diff --git a/src/atiscreen.c b/src/atiscreen.c index 58b0bdaa..bc579347 100644 --- a/src/atiscreen.c +++ b/src/atiscreen.c @@ -349,7 +349,7 @@ ATIMach64SetupMemXAA * * This function is called by DIX to initialise the screen. */ -_X_EXPORT Bool +Bool ATIScreenInit ( int iScreen, diff --git a/src/ativalid.c b/src/ativalid.c index 8a92e82e..51cf5ae8 100644 --- a/src/ativalid.c +++ b/src/ativalid.c @@ -35,7 +35,7 @@ * * This checks for hardware-related limits on mode timings. */ -_X_EXPORT ModeStatus +ModeStatus ATIValidMode ( int iScreen, diff --git a/src/local_xf86Rename.h b/src/local_xf86Rename.h new file mode 100644 index 00000000..51021709 --- /dev/null +++ b/src/local_xf86Rename.h @@ -0,0 +1,23 @@ +/* + * Copyright © 2006 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#define XF86NAME(x) radeon_##x diff --git a/src/r128_dri.c b/src/r128_dri.c index 21a13c17..fc91421d 100644 --- a/src/r128_dri.c +++ b/src/r128_dri.c @@ -988,13 +988,13 @@ Bool R128DRIScreenInit(ScreenPtr pScreen) /* Check the DRI version */ DRIQueryVersion(&major, &minor, &patch); - if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { + if (major != DRIINFO_MAJOR_VERSION || minor < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] R128DRIScreenInit failed because of a version mismatch.\n" "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n" "[dri] Disabling the DRI.\n", major, minor, patch, - DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); + DRIINFO_MAJOR_VERSION, 0); return FALSE; } diff --git a/src/r128_driver.c b/src/r128_driver.c index 81c9015c..6e26a6ef 100644 --- a/src/r128_driver.c +++ b/src/r128_driver.c @@ -182,7 +182,7 @@ static const OptionInfoRec R128Options[] = { { -1, NULL, OPTV_NONE, {0}, FALSE } }; -_X_EXPORT const OptionInfoRec *R128OptionsWeak(void) { return R128Options; } +const OptionInfoRec *R128OptionsWeak(void) { return R128Options; } R128RAMRec R128RAM[] = { /* Memory Specifications From RAGE 128 Software Development @@ -2044,7 +2044,7 @@ R128ProbeDDC(ScrnInfoPtr pScrn, int indx) } /* R128PreInit is called once at server startup. */ -_X_EXPORT Bool R128PreInit(ScrnInfoPtr pScrn, int flags) +Bool R128PreInit(ScrnInfoPtr pScrn, int flags) { R128InfoPtr info; xf86Int10InfoPtr pInt10 = NULL; @@ -2334,7 +2334,7 @@ R128BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) } /* Called at the start of each server generation. */ -_X_EXPORT Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, +Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -4238,7 +4238,7 @@ static Bool R128SaveScreen(ScreenPtr pScreen, int mode) * The workaround is to switch the mode, then switch to another VT, then * switch back. --AGD */ -_X_EXPORT Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); @@ -4251,12 +4251,15 @@ _X_EXPORT Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } /* Used to disallow modes that are not supported by the hardware. */ -_X_EXPORT ModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode, +ModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); + if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT) + return MODE_OK; + if(info->isDFP) { if(info->PanelXRes < mode->CrtcHDisplay || info->PanelYRes < mode->CrtcVDisplay) @@ -4327,7 +4330,7 @@ _X_EXPORT ModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode, /* Adjust viewport into virtual desktop such that (0,0) in viewport space is (x,y) in virtual space. */ -_X_EXPORT void R128AdjustFrame(int scrnIndex, int x, int y, int flags) +void R128AdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); @@ -4363,7 +4366,7 @@ _X_EXPORT void R128AdjustFrame(int scrnIndex, int x, int y, int flags) /* Called when VT switching back to the X server. Reinitialize the video mode. */ -_X_EXPORT Bool R128EnterVT(int scrnIndex, int flags) +Bool R128EnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); @@ -4396,7 +4399,7 @@ _X_EXPORT Bool R128EnterVT(int scrnIndex, int flags) /* Called when VT switching away from the X server. Restore the original text mode. */ -_X_EXPORT void R128LeaveVT(int scrnIndex, int flags) +void R128LeaveVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); @@ -4466,7 +4469,7 @@ static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen) return (*pScreen->CloseScreen)(scrnIndex, pScreen); } -_X_EXPORT void R128FreeScreen(int scrnIndex, int flags) +void R128FreeScreen(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); @@ -4605,18 +4608,3 @@ static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on) return 0; } - -_X_EXPORT void R128FillInScreenInfo(ScrnInfoPtr pScrn) -{ - pScrn->driverVersion = R128_VERSION_CURRENT; - pScrn->driverName = R128_DRIVER_NAME; - pScrn->name = R128_NAME; - pScrn->PreInit = R128PreInit; - pScrn->ScreenInit = R128ScreenInit; - pScrn->SwitchMode = R128SwitchMode; - pScrn->AdjustFrame = R128AdjustFrame; - pScrn->EnterVT = R128EnterVT; - pScrn->LeaveVT = R128LeaveVT; - pScrn->FreeScreen = R128FreeScreen; - pScrn->ValidMode = R128ValidMode; -} diff --git a/src/r128_probe.c b/src/r128_probe.c index 96e78974..81ff663a 100644 --- a/src/r128_probe.c +++ b/src/r128_probe.c @@ -41,7 +41,6 @@ * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge. */ -#include "atimodule.h" #include "ativersion.h" #include "r128_probe.h" @@ -107,7 +106,7 @@ PciChipsets R128PciChipsets[] = { int gR128EntityIndex = -1; /* Return the options for supported chipset 'n'; NULL otherwise */ -const OptionInfoRec * +_X_EXPORT const OptionInfoRec * R128AvailableOptions(int chipid, int busid) { int i; @@ -126,7 +125,7 @@ R128AvailableOptions(int chipid, int busid) } /* Return the string name for supported chipset 'n'; NULL otherwise. */ -void +_X_EXPORT void R128Identify(int flags) { xf86PrintChipsets(R128_NAME, @@ -135,7 +134,7 @@ R128Identify(int flags) } /* Return TRUE if chipset is present; FALSE otherwise. */ -Bool +_X_EXPORT Bool R128Probe(DriverPtr drv, int flags) { int numUsed; @@ -194,22 +193,18 @@ R128Probe(DriverPtr drv, int flags) if((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], R128PciChipsets, 0, 0, 0, 0, 0))) { - -#ifdef XFree86LOADER - - if (!xf86LoadSubModule(pScrn, "r128")) { - xf86Msg(X_ERROR, - R128_NAME ": Failed to load \"r128\" module.\n"); - xf86DeleteScreen(pScrn->scrnIndex, 0); - continue; - } - - xf86LoaderReqSymLists(R128Symbols, NULL); - -#endif - + pScrn->driverVersion = R128_VERSION_CURRENT; + pScrn->driverName = R128_DRIVER_NAME; + pScrn->name = R128_NAME; pScrn->Probe = R128Probe; - R128FillInScreenInfo(pScrn); + pScrn->PreInit = R128PreInit; + pScrn->ScreenInit = R128ScreenInit; + pScrn->SwitchMode = R128SwitchMode; + pScrn->AdjustFrame = R128AdjustFrame; + pScrn->EnterVT = R128EnterVT; + pScrn->LeaveVT = R128LeaveVT; + pScrn->FreeScreen = R128FreeScreen; + pScrn->ValidMode = R128ValidMode; foundScreen = TRUE; diff --git a/src/r128_probe.h b/src/r128_probe.h index 91502963..180e52a9 100644 --- a/src/r128_probe.h +++ b/src/r128_probe.h @@ -73,6 +73,4 @@ extern ModeStatus R128ValidMode(int, DisplayModePtr, Bool, int); extern const OptionInfoRec * R128OptionsWeak(void); -extern void R128FillInScreenInfo(ScrnInfoPtr); - #endif /* _R128_PROBE_H_ */ diff --git a/src/radeon.h b/src/radeon.h index 5bb005b9..fa2bccdf 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -39,6 +39,7 @@ #include <stdlib.h> /* For abs() */ #include <unistd.h> /* For usleep() */ +#include <sys/time.h> /* For gettimeofday() */ #include "xf86str.h" #include "compiler.h" @@ -65,6 +66,8 @@ #include "xf86xv.h" #include "radeon_probe.h" +#include "radeon_tv.h" + /* DRI support */ #ifdef XF86DRI #define _XF86DRI_SERVER_ @@ -77,6 +80,9 @@ #endif #endif +#include "xf86Crtc.h" +#include "X11/Xatom.h" + /* Render support */ #ifdef RENDER #include "picturestr.h" @@ -115,21 +121,8 @@ typedef enum { OPTION_ACCEL_DFS, #endif #endif - OPTION_PANEL_OFF, OPTION_DDC_MODE, - OPTION_MONITOR_LAYOUT, OPTION_IGNORE_EDID, - OPTION_FBDEV, - OPTION_MERGEDFB, - OPTION_CRT2HSYNC, - OPTION_CRT2VREFRESH, - OPTION_CRT2POS, - OPTION_METAMODES, - OPTION_MERGEDDPI, - OPTION_RADEONXINERAMA, - OPTION_CRT2ISSCRN0, - OPTION_MERGEDFBNONRECT, - OPTION_MERGEDFBMOUSER, OPTION_DISP_PRIORITY, OPTION_PANEL_SIZE, OPTION_MIN_DOTCLOCK, @@ -157,39 +150,17 @@ typedef enum { OPTION_LVDS_PROBE_PLL, OPTION_ACCELMETHOD, OPTION_CONSTANTDPI, - OPTION_REVERSE_DISPLAY, - OPTION_DRI + OPTION_CONNECTORTABLE, + OPTION_DRI, + OPTION_DEFAULT_CONNECTOR_TABLE } RADEONOpts; -/* ------- mergedfb support ------------- */ - /* Psuedo Xinerama support */ -#define NEED_REPLIES /* ? */ -#define EXTENSION_PROC_ARGS void * -#include "extnsionst.h" /* required */ -#include <X11/extensions/panoramiXproto.h> /* required */ -#define RADEON_XINERAMA_MAJOR_VERSION 1 -#define RADEON_XINERAMA_MINOR_VERSION 1 - - -/* Relative merge position */ -typedef enum { - radeonLeftOf, - radeonRightOf, - radeonAbove, - radeonBelow, - radeonClone -} RADEONScrn2Rel; - -typedef struct _region { - int x0,x1,y0,y1; -} region; -/* ------------------------------------- */ - -#define RADEON_DEBUG 1 /* Turn off debugging output */ #define RADEON_IDLE_RETRY 16 /* Fall out of idle loops after this count */ #define RADEON_TIMEOUT 2000000 /* Fall out of wait loops after this count */ +#define RADEON_VSYNC_TIMEOUT 20000 /* Maximum wait for VSYNC (in usecs) */ + /* Buffer are aligned on 4096 byte boundaries */ #define RADEON_BUFFER_ALIGN 0x00000fff #define RADEON_VBIOS_SIZE 0x00010000 @@ -198,22 +169,28 @@ typedef struct _region { * for something else. */ -#if RADEON_DEBUG -#define RADEONTRACE(x) \ -do { \ - ErrorF("(**) %s(%d): ", RADEON_NAME, pScrn->scrnIndex); \ - ErrorF x; \ -} while(0) -#else -#define RADEONTRACE(x) do { } while(0) -#endif +#define RADEON_LOGLEVEL_DEBUG 4 +/* for Xv, outputs */ +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) /* Other macros */ #define RADEON_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define RADEON_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1)) #define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate) +typedef struct { + int revision; + CARD16 rr1_offset; + CARD16 rr2_offset; + CARD16 dyn_clk_offset; + CARD16 pll_offset; + CARD16 mem_config_offset; + CARD16 mem_reset_offset; + CARD16 short_mem_offset; + CARD16 rr3_offset; + CARD16 rr4_offset; +} RADEONBIOSInitTable; typedef struct { /* Common registers */ @@ -262,10 +239,11 @@ typedef struct { CARD32 disp_merge_cntl; CARD32 grph_buffer_cntl; CARD32 crtc_more_cntl; + CARD32 crtc_tile_x0_y0; /* CRTC2 registers */ CARD32 crtc2_gen_cntl; - + CARD32 dac_macro_cntl; CARD32 dac2_cntl; CARD32 disp_output_cntl; CARD32 disp_tv_out_cntl; @@ -279,6 +257,8 @@ typedef struct { CARD32 crtc2_offset; CARD32 crtc2_offset_cntl; CARD32 crtc2_pitch; + CARD32 crtc2_tile_x0_y0; + /* Flat panel registers */ CARD32 fp_crtc_h_total_disp; CARD32 fp_crtc_v_total_disp; @@ -306,7 +286,7 @@ typedef struct { unsigned ppll_ref_div; unsigned ppll_div_3; CARD32 htotal_cntl; - CARD32 vclk_cntl; + CARD32 vclk_ecp_cntl; /* Computed values for PLL2 */ CARD32 dot_clock_freq_2; @@ -325,7 +305,54 @@ typedef struct { CARD32 palette[256]; CARD32 palette2[256]; - CARD32 tv_dac_cntl; + CARD32 rs480_unk_e30; + CARD32 rs480_unk_e34; + CARD32 rs480_unk_e38; + CARD32 rs480_unk_e3c; + + /* TV out registers */ + CARD32 tv_master_cntl; + CARD32 tv_htotal; + CARD32 tv_hsize; + CARD32 tv_hdisp; + CARD32 tv_hstart; + CARD32 tv_vtotal; + CARD32 tv_vdisp; + CARD32 tv_timing_cntl; + CARD32 tv_vscaler_cntl1; + CARD32 tv_vscaler_cntl2; + CARD32 tv_sync_size; + CARD32 tv_vrestart; + CARD32 tv_hrestart; + CARD32 tv_frestart; + CARD32 tv_ftotal; + CARD32 tv_clock_sel_cntl; + CARD32 tv_clkout_cntl; + CARD32 tv_data_delay_a; + CARD32 tv_data_delay_b; + CARD32 tv_dac_cntl; + CARD32 tv_pll_cntl; + CARD32 tv_pll_cntl1; + CARD32 tv_pll_fine_cntl; + CARD32 tv_modulator_cntl1; + CARD32 tv_modulator_cntl2; + CARD32 tv_frame_lock_cntl; + CARD32 tv_pre_dac_mux_cntl; + CARD32 tv_rgb_cntl; + CARD32 tv_y_saw_tooth_cntl; + CARD32 tv_y_rise_cntl; + CARD32 tv_y_fall_cntl; + CARD32 tv_uv_adr; + CARD32 tv_upsamp_and_gain_cntl; + CARD32 tv_gain_limit_settings; + CARD32 tv_linear_gain_settings; + CARD32 tv_crc_cntl; + CARD32 tv_sync_cntl; + CARD32 gpiopad_a; + CARD32 pll_test_cntl; + + CARD16 h_code_timing[MAX_H_CODE_TIMING_LEN]; + CARD16 v_code_timing[MAX_V_CODE_TIMING_LEN]; } RADEONSaveRec, *RADEONSavePtr; @@ -402,11 +429,6 @@ typedef enum { } RADEONCardType; typedef struct { - CARD32 freq; - CARD32 value; -}RADEONTMDSPll; - -typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; PCITAG PciTag; @@ -414,8 +436,6 @@ typedef struct { RADEONChipFamily ChipFamily; RADEONErrata ChipErrata; - Bool FBDev; - unsigned long LinearAddr; /* Frame buffer physical address */ unsigned long MMIOAddr; /* MMIO region physical address */ unsigned long BIOSAddr; /* BIOS physical address */ @@ -438,36 +458,16 @@ typedef struct { unsigned long FbMapSize; /* Size of frame buffer, in bytes */ unsigned long FbSecureSize; /* Size of secured fb area at end of framebuffer */ - int Flags; /* Saved copy of mode flags */ - - /* VE/M6 support */ - RADEONMonitorType DisplayType; /* Monitor connected on */ - RADEONDDCType DDCType; - RADEONConnectorType ConnectorType; Bool IsMobility; /* Mobile chips for laptops */ Bool IsIGP; /* IGP chips */ Bool HasSingleDAC; /* only TVDAC on chip */ - Bool IsSecondary; /* Second Screen */ - Bool IsPrimary; /* Primary Screen */ - Bool IsSwitching; /* Flag for switching mode */ - Bool OverlayOnCRTC2; Bool ddc_mode; /* Validate mode by matching exactly * the modes supported in DDC data */ Bool R300CGWorkaround; /* EDID or BIOS values for FPs */ - int PanelXRes; - int PanelYRes; - int HOverPlus; - int HSyncWidth; - int HBlank; - int VOverPlus; - int VSyncWidth; - int VBlank; - int PanelPwrDly; - int DotClock; int RefDivider; int FeedbackDivider; int PostDivider; @@ -476,11 +476,9 @@ typedef struct { Bool ddc_bios; Bool ddc1; Bool ddc2; - I2CBusPtr pI2CBus; - CARD32 DDCReg; RADEONPLLRec pll; - RADEONTMDSPll tmds_pll[4]; + int RamWidth; float sclk; /* in MHz */ float mclk; /* in MHz */ @@ -497,6 +495,8 @@ typedef struct { #ifdef USE_EXA ExaDriverPtr exa; + int exaSyncMarker; + int exaMarkerSynced; int engineMode; #define EXA_ENGINEMODE_UNKNOWN 0 #define EXA_ENGINEMODE_2D 1 @@ -605,6 +605,7 @@ typedef struct { Bool allowPageFlip; /* Enable 3d page flipping */ #ifdef DAMAGE DamagePtr pDamage; + RegionRec driRegion; #endif Bool have3DWindows; /* Are there any 3d clients? */ @@ -614,7 +615,6 @@ typedef struct { unsigned long gartOffset; unsigned char *AGP; /* Map */ int agpMode; - int agpFastWrite; CARD32 pciCommand; @@ -774,42 +774,10 @@ typedef struct { /* X itself has the 3D context */ Bool XInited3D; - /* merged fb stuff, also covers clone modes */ - Bool MergedFB; - RADEONScrn2Rel CRT2Position; - char * CRT2HSync; - char * CRT2VRefresh; - char * MetaModes; - ScrnInfoPtr CRT2pScrn; - DisplayModePtr CRT1Modes; - DisplayModePtr CRT1CurrentMode; - int CRT1frameX0; - int CRT1frameY0; - int CRT1frameX1; - int CRT1frameY1; - RADEONMonitorType MergeType; - RADEONDDCType MergeDDCType; - void (*PointerMoved)(int index, int x, int y); - /* pseudo xinerama support for mergedfb */ - int maxCRT1_X1, maxCRT1_X2, maxCRT1_Y1, maxCRT1_Y2; - int maxCRT2_X1, maxCRT2_X2, maxCRT2_Y1, maxCRT2_Y2; - int maxClone_X1, maxClone_X2, maxClone_Y1, maxClone_Y2; - Bool UseRADEONXinerama; - Bool CRT2IsScrn0; - ExtensionEntry *XineramaExtEntry; - int RADEONXineramaVX, RADEONXineramaVY; - Bool AtLeastOneNonClone; - int MergedFBXDPI, MergedFBYDPI; - Bool NoVirtual; - int CRT1XOffs, CRT1YOffs, CRT2XOffs, CRT2YOffs; - int MBXNR1XMAX, MBXNR1YMAX, MBXNR2XMAX, MBXNR2YMAX; - Bool NonRect, HaveNonRect, HaveOffsRegions, MouseRestrictions; - region NonRectDead, OffDead1, OffDead2; + DisplayModePtr currentMode, savedCurrentMode; int constantDPI; /* -1 = auto, 0 = off, 1 = on */ int RADEONDPIVX, RADEONDPIVY; - RADEONScrn2Rel MergedDPISRel; - int RADEONMergedDPIVX, RADEONMergedDPIVY, RADEONMergedDPIRot; /* special handlings for DELL triple-head server */ Bool IsDellServer; @@ -820,7 +788,22 @@ typedef struct { int MaxLines; CARD32 tv_dac_adj; + CARD32 tv_dac_enable_mask; + + Bool want_vblank_interrupts; + RADEONBIOSConnector BiosConnector[RADEON_MAX_BIOS_CONNECTOR]; + RADEONBIOSInitTable BiosTable; + + /* save crtc state for console restore */ + Bool crtc_on; + Bool crtc2_on; + + Bool InternalTVOut; + int tvdac_use_count; + Rotation rotation; + void (*PointerMoved)(int, int, int); + CreateScreenResourcesProcPtr CreateScreenResources; } RADEONInfoRec, *RADEONInfoPtr; #define RADEONWaitForFifo(pScrn, entries) \ @@ -839,7 +822,7 @@ extern void RADEONWaitForIdleCP(ScrnInfoPtr pScrn); #endif extern void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, - int clone); + Bool clone); extern void RADEONEngineReset(ScrnInfoPtr pScrn); extern void RADEONEngineFlush(ScrnInfoPtr pScrn); @@ -858,6 +841,7 @@ extern Bool RADEONAccelInit(ScreenPtr pScreen); extern Bool RADEONSetupMemEXA (ScreenPtr pScreen); extern Bool RADEONDrawInitMMIO(ScreenPtr pScreen); #ifdef XF86DRI +extern unsigned long long RADEONTexOffsetStart(PixmapPtr pPix); extern Bool RADEONGetDatatypeBpp(int bpp, CARD32 *type); extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, CARD32 *pitch_offset); @@ -892,19 +876,47 @@ extern void RADEONPllErrataAfterData(RADEONInfoPtr info); extern Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10); extern Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn); extern Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn); -extern Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn); -extern Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn); -extern Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn); - +extern Bool RADEONGetLVDSInfoFromBIOS (xf86OutputPtr output); +extern Bool RADEONGetTMDSInfoFromBIOS (xf86OutputPtr output); +extern Bool RADEONGetTVInfoFromBIOS (xf86OutputPtr output); +extern Bool RADEONGetHardCodedEDIDFromBIOS (xf86OutputPtr output); + +extern void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreDACRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreFP2Registers(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreLVDSRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreRMXRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, + RADEONSavePtr restore); + +extern void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr save, + RADEONInfoPtr info); extern void RADEONInitDispBandwidth(ScrnInfoPtr pScrn); extern Bool RADEONI2cInit(ScrnInfoPtr pScrn); extern void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag); -extern void RADEONSetupConnectors(ScrnInfoPtr pScrn); -extern Bool RADEONMapControllers(ScrnInfoPtr pScrn); -extern void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable); +extern Bool RADEONSetupConnectors(ScrnInfoPtr pScrn); +extern void RADEONPrintPortMap(ScrnInfoPtr pScrn); +extern void RADEONEnableDisplay(xf86OutputPtr pPort, BOOL bEnable); extern void RADEONDisableDisplays(ScrnInfoPtr pScrn); extern void RADEONGetPanelInfo(ScrnInfoPtr pScrn); -extern void RADEONGetTVDacAdjInfo(ScrnInfoPtr pScrn); +extern void RADEONGetTVDacAdjInfo(xf86OutputPtr output); +extern void RADEONUnblank(ScrnInfoPtr pScrn); extern void RADEONUnblank(ScrnInfoPtr pScrn); extern void RADEONBlank(ScrnInfoPtr pScrn); extern void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, @@ -912,13 +924,48 @@ extern void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, int flags); extern Bool RADEONAllocateControllers(ScrnInfoPtr pScrn); extern Bool RADEONAllocateConnectors(ScrnInfoPtr pScrn); -extern RADEONConnector *RADEONGetCrtcConnector(ScrnInfoPtr pScrn, int crtc_num); extern int RADEONValidateMergeModes(ScrnInfoPtr pScrn); extern int RADEONValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName, RADEONMonitorType DisplayType, int crtc2); -extern int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName); +extern int RADEONValidateFPModes(xf86OutputPtr output, char **ppModeName, DisplayModePtr *modeList); extern void RADEONSetPitch (ScrnInfoPtr pScrn); - +extern void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode); + +DisplayModePtr +RADEONProbeOutputModes(xf86OutputPtr output); +extern Bool RADEONInit2(ScrnInfoPtr pScrn, DisplayModePtr crtc1, + DisplayModePtr crtc2, int crtc_mask, + RADEONSavePtr save, RADEONMonitorType montype); + +void +radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y); +void +radeon_crtc_show_cursor (xf86CrtcPtr crtc); +void +radeon_crtc_hide_cursor (xf86CrtcPtr crtc); +void +radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y); +void +radeon_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg); +void +radeon_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image); +void +RADEONEnableOutputs(ScrnInfoPtr pScrn, int crtc_num); + +extern void RADEONAdjustCrtcRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output); +extern void RADEONAdjustPLLRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output); +extern void RADEONAdjustCrtc2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output); +extern void RADEONAdjustPLL2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output); +extern void RADEONInitTVRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary); + +extern void RADEONRestoreTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore); +extern void RADEONRestoreTVRestarts(ScrnInfoPtr pScrn, RADEONSavePtr restore); +extern void RADEONRestoreTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr restore); #ifdef XF86DRI #ifdef USE_XAA @@ -937,6 +984,7 @@ extern drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn); extern void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard); extern void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn); extern int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info); +extern Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on); extern void RADEONHostDataParams(ScrnInfoPtr pScrn, CARD8 *dst, CARD32 pitch, int cpp, @@ -964,6 +1012,16 @@ do { \ info->CPStarted = TRUE; \ } while (0) +#define RADEONCP_RELEASE(pScrn, info) \ +do { \ + if (info->CPInUse) { \ + RADEON_PURGE_CACHE(); \ + RADEON_WAIT_UNTIL_IDLE(); \ + RADEONCPReleaseIndirect(pScrn); \ + info->CPInUse = FALSE; \ + } \ +} while (0) + #define RADEONCP_STOP(pScrn, info) \ do { \ int _ret; \ @@ -1128,14 +1186,6 @@ do { \ ADVANCE_RING(); \ } while (0) -#define RADEON_FLUSH_CACHE() \ -do { \ - BEGIN_RING(2); \ - OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_DC_FLUSH); \ - ADVANCE_RING(); \ -} while (0) - #define RADEON_PURGE_CACHE() \ do { \ BEGIN_RING(2); \ @@ -1176,4 +1226,21 @@ static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn) #endif } +static __inline__ void radeon_init_timeout(struct timeval *endtime, + unsigned int timeout) +{ + gettimeofday(endtime, NULL); + endtime->tv_usec += timeout; + endtime->tv_sec += endtime->tv_usec / 1000000; + endtime->tv_usec %= 1000000; +} + +static __inline__ int radeon_timedout(const struct timeval *endtime) +{ + struct timeval now; + gettimeofday(&now, NULL); + return now.tv_sec == endtime->tv_sec ? + now.tv_usec > endtime->tv_usec : now.tv_sec > endtime->tv_sec; +} + #endif /* _RADEON_H_ */ diff --git a/src/radeon_accel.c b/src/radeon_accel.c index 41859c4a..b739988f 100644 --- a/src/radeon_accel.c +++ b/src/radeon_accel.c @@ -134,9 +134,10 @@ void RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries) INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; if (info->fifo_slots >= entries) return; } - RADEONTRACE(("FIFO timed out: %u entries, stat=0x%08x\n", - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, - INREG(RADEON_RBBM_STATUS))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "FIFO timed out: %u entries, stat=0x%08x\n", + INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, + INREG(RADEON_RBBM_STATUS)); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FIFO timed out, resetting engine...\n"); RADEONEngineReset(pScrn); @@ -165,8 +166,9 @@ void RADEONEngineFlush(ScrnInfoPtr pScrn) break; } if (i == RADEON_TIMEOUT) { - RADEONTRACE(("DC flush timeout: %x\n", - INREG(RADEON_RB3D_DSTCACHE_CTLSTAT))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "DC flush timeout: %x\n", + INREG(RADEON_RB3D_DSTCACHE_CTLSTAT)); } } @@ -296,9 +298,10 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - RADEONTRACE(("EngineRestore (%d/%d)\n", - info->CurrentLayout.pixel_code, - info->CurrentLayout.bitsPerPixel)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "EngineRestore (%d/%d)\n", + info->CurrentLayout.pixel_code, + info->CurrentLayout.bitsPerPixel); /* Setup engine location. This shouldn't be necessary since we * set them appropriately before any accel ops, but let's avoid @@ -347,9 +350,10 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - RADEONTRACE(("EngineInit (%d/%d)\n", - info->CurrentLayout.pixel_code, - info->CurrentLayout.bitsPerPixel)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "EngineInit (%d/%d)\n", + info->CurrentLayout.pixel_code, + info->CurrentLayout.bitsPerPixel); OUTREG(RADEON_RB3D_CNTL, 0); @@ -362,15 +366,17 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) case 24: info->datatype = 5; break; case 32: info->datatype = 6; break; default: - RADEONTRACE(("Unknown depth/bpp = %d/%d (code = %d)\n", - info->CurrentLayout.depth, - info->CurrentLayout.bitsPerPixel, - info->CurrentLayout.pixel_code)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Unknown depth/bpp = %d/%d (code = %d)\n", + info->CurrentLayout.depth, + info->CurrentLayout.bitsPerPixel, + info->CurrentLayout.pixel_code); } info->pitch = ((info->CurrentLayout.displayWidth / 8) * (info->CurrentLayout.pixel_bytes == 3 ? 3 : 1)); - RADEONTRACE(("Pitch for acceleration = %d\n", info->pitch)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Pitch for acceleration = %d\n", info->pitch); info->dp_gui_master_cntl = ((info->datatype << RADEON_GMC_DST_DATATYPE_SHIFT) diff --git a/src/radeon_accelfuncs.c b/src/radeon_accelfuncs.c index 784b0745..212131fd 100644 --- a/src/radeon_accelfuncs.c +++ b/src/radeon_accelfuncs.c @@ -1204,8 +1204,14 @@ FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a) hardware accel two point lines */ miSetZeroLineBias(pScreen, (OCTANT5 | OCTANT6 | OCTANT7 | OCTANT8)); - a->SubsequentSolidTwoPointLine - = FUNC_NAME(RADEONSubsequentSolidTwoPointLine); +#ifdef ACCEL_CP + /* RV280s lock up with this using the CP for reasons to be determined. + * See https://bugs.freedesktop.org/show_bug.cgi?id=5986 . + */ + if (info->ChipFamily != CHIP_FAMILY_RV280) +#endif + a->SubsequentSolidTwoPointLine + = FUNC_NAME(RADEONSubsequentSolidTwoPointLine); /* Disabled on RV200 and newer because it does not pass XTest */ if (info->ChipFamily < CHIP_FAMILY_RV200) { diff --git a/src/radeon_bios.c b/src/radeon_bios.c index 1d4c9bbb..b24c4817 100644 --- a/src/radeon_bios.c +++ b/src/radeon_bios.c @@ -34,12 +34,27 @@ #include "xf86.h" #include "xf86_OSproc.h" +#include "xf86PciInfo.h" #include "radeon.h" #include "radeon_reg.h" #include "radeon_macros.h" #include "radeon_probe.h" #include "vbe.h" +int RADEONBIOSApplyConnectorQuirks(ScrnInfoPtr pScrn, int connector_found) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + /* quirk for compaq nx6125 - the bios lies about the VGA DDC */ + if (info->PciInfo->subsysVendor == PCI_VENDOR_HP) { + if (info->PciInfo->subsysCard == 0x308b) { + if (info->BiosConnector[1].DDCType == DDC_CRT2) + info->BiosConnector[1].DDCType = DDC_MONID; + } + } + return connector_found; +} + /* Read the Video BIOS block and the FP registers (if applicable). */ Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) { @@ -126,11 +141,191 @@ Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) return TRUE; } +static Bool RADEONGetATOMConnectorInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + int offset, i, tmp, tmp0, crtc, portinfo, gpio; + + if (!info->VBIOS) return FALSE; + + offset = RADEON_BIOS16(info->MasterDataStart + 22); + + if (offset) { + tmp = RADEON_BIOS16(offset + 4); + for (i = 0; i < 8; i++) { + if (tmp & (1 << i)) { + info->BiosConnector[i].valid = TRUE; + portinfo = RADEON_BIOS16(offset + 6 + i * 2); + info->BiosConnector[i].DACType = (portinfo & 0xf) - 1; + info->BiosConnector[i].ConnectorType = (portinfo >> 4) & 0xf; + crtc = (portinfo >> 8) & 0xf; + tmp0 = RADEON_BIOS16(info->MasterDataStart + 24); + gpio = RADEON_BIOS16(tmp0 + 4 + 27 * crtc) * 4; + switch(gpio) { + case RADEON_GPIO_MONID: + info->BiosConnector[i].DDCType = DDC_MONID; + break; + case RADEON_GPIO_DVI_DDC: + info->BiosConnector[i].DDCType = DDC_DVI; + break; + case RADEON_GPIO_VGA_DDC: + info->BiosConnector[i].DDCType = DDC_VGA; + break; + case RADEON_GPIO_CRT2_DDC: + info->BiosConnector[i].DDCType = DDC_CRT2; + break; + case RADEON_LCD_GPIO_MASK: + info->BiosConnector[i].DDCType = DDC_LCD; + break; + default: + info->BiosConnector[i].DDCType = DDC_NONE_DETECTED; + break; + } + + if (i == 3) + info->BiosConnector[i].TMDSType = TMDS_INT; + else if (i == 7) + info->BiosConnector[i].TMDSType = TMDS_EXT; + else + info->BiosConnector[i].TMDSType = TMDS_UNKNOWN; + + } else { + info->BiosConnector[i].valid = FALSE; + } + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n"); + return FALSE; + } + + /* DVI-I ports have 2 entries: one for analog, one for digital. combine them */ + if (info->BiosConnector[0].valid && info->BiosConnector[7].valid) { + info->BiosConnector[7].DACType = info->BiosConnector[0].DACType; + info->BiosConnector[0].valid = FALSE; + } + + if (info->BiosConnector[4].valid && info->BiosConnector[3].valid) { + info->BiosConnector[3].DACType = info->BiosConnector[4].DACType; + info->BiosConnector[4].valid = FALSE; + } + + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bios Connector table: \n"); + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].valid) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + i, info->BiosConnector[i].DDCType, info->BiosConnector[i].DACType, + info->BiosConnector[i].TMDSType, info->BiosConnector[i].ConnectorType); + } + } + + return TRUE; +} + +static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + int offset, i, entry, tmp, tmp0, tmp1; + + if (!info->VBIOS) return FALSE; + + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x50); + if (offset) { + for (i = 0; i < 4; i++) { + entry = offset + 2 + i*2; + + if (!RADEON_BIOS16(entry)) { + break; + } + info->BiosConnector[i].valid = TRUE; + tmp = RADEON_BIOS16(entry); + info->BiosConnector[i].ConnectorType = (tmp >> 12) & 0xf; + info->BiosConnector[i].DDCType = (tmp >> 8) & 0xf; + info->BiosConnector[i].DACType = tmp & 0x1; + info->BiosConnector[i].TMDSType = tmp & 0x10; + + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n"); + return FALSE; + } + + /* check LVDS table */ + if (info->IsMobility) { + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x40); + if (offset) { + info->BiosConnector[4].valid = TRUE; + info->BiosConnector[4].ConnectorType = CONNECTOR_PROPRIETARY; + info->BiosConnector[4].DACType = DAC_NONE; + info->BiosConnector[4].TMDSType = TMDS_NONE; + + tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42); + if (tmp) { + tmp0 = RADEON_BIOS16(tmp + 0x15); + if (tmp0) { + tmp1 = RADEON_BIOS8(tmp0+2) & 0x07; + if (tmp1) { + info->BiosConnector[4].DDCType = tmp1; + if (info->BiosConnector[4].DDCType > DDC_LCD) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Unknown DDCType %d found\n", + info->BiosConnector[4].DDCType); + info->BiosConnector[4].DDCType = DDC_NONE_DETECTED; + } + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); + } + } + } else { + info->BiosConnector[4].DDCType = DDC_NONE_DETECTED; + } + } + } + + /* check TV table */ + if (info->InternalTVOut) { + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); + if (offset) { + if (RADEON_BIOS8(offset + 6) == 'T') { + info->BiosConnector[5].valid = TRUE; + /* assume s-video for now */ + info->BiosConnector[5].ConnectorType = CONNECTOR_STV; + info->BiosConnector[5].DACType = DAC_TVDAC; + info->BiosConnector[5].TMDSType = TMDS_NONE; + info->BiosConnector[5].DDCType = DDC_NONE_DETECTED; + } + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bios Connector table: \n"); + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].valid) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + i, info->BiosConnector[i].DDCType, info->BiosConnector[i].DACType, + info->BiosConnector[i].TMDSType, info->BiosConnector[i].ConnectorType); + } + } + + return TRUE; +} + +Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + + if(!info->VBIOS) return FALSE; + + if (info->IsAtomBios) + return RADEONGetATOMConnectorInfoFromBIOS(pScrn); + else + return RADEONGetLegacyConnectorInfoFromBIOS(pScrn); +} + +#if 0 Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR (pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); int i = 0, j, tmp, tmp0=0, tmp1=0; + RADEONBIOSConnector tempConnector; if(!info->VBIOS) return FALSE; @@ -148,46 +343,49 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) /* sharing same port with id[0] */ if (((portinfo>>8) & 0xf) == id[0]) { if (i == 3) - pRADEONEnt->PortInfo[0]->TMDSType = TMDS_INT; + info->BiosConnector[0].TMDSType = TMDS_INT; else if (i == 7) - pRADEONEnt->PortInfo[0]->TMDSType = TMDS_EXT; + info->BiosConnector[0].TMDSType = TMDS_EXT; - if (pRADEONEnt->PortInfo[0]->DACType == DAC_UNKNOWN) - pRADEONEnt->PortInfo[0]->DACType = (portinfo & 0xf) - 1; + if (info->BiosConnector[0].DACType == DAC_UNKNOWN) + info->BiosConnector[0].DACType = (portinfo & 0xf) - 1; continue; } } id[crtc] = (portinfo>>8) & 0xf; - pRADEONEnt->PortInfo[crtc]->DACType = (portinfo & 0xf) - 1; - pRADEONEnt->PortInfo[crtc]->ConnectorType = (portinfo>>4) & 0xf; + info->BiosConnector[crtc].DACType = (portinfo & 0xf) - 1; + info->BiosConnector[crtc].ConnectorType = (portinfo>>4) & 0xf; if (i == 3) - pRADEONEnt->PortInfo[crtc]->TMDSType = TMDS_INT; + info->BiosConnector[crtc].TMDSType = TMDS_INT; else if (i == 7) - pRADEONEnt->PortInfo[crtc]->TMDSType = TMDS_EXT; + info->BiosConnector[crtc].TMDSType = TMDS_EXT; if((tmp0 = RADEON_BIOS16 (info->MasterDataStart + 24)) && id[crtc]) { switch (RADEON_BIOS16 (tmp0 + 4 + 27 * id[crtc]) * 4) { case RADEON_GPIO_MONID: - pRADEONEnt->PortInfo[crtc]->DDCType = DDC_MONID; + info->BiosConnector[crtc].DDCType = DDC_MONID; break; case RADEON_GPIO_DVI_DDC: - pRADEONEnt->PortInfo[crtc]->DDCType = DDC_DVI; + info->BiosConnector[crtc].DDCType = DDC_DVI; break; case RADEON_GPIO_VGA_DDC: - pRADEONEnt->PortInfo[crtc]->DDCType = DDC_VGA; + info->BiosConnector[crtc].DDCType = DDC_VGA; break; case RADEON_GPIO_CRT2_DDC: - pRADEONEnt->PortInfo[crtc]->DDCType = DDC_CRT2; + info->BiosConnector[crtc].DDCType = DDC_CRT2; + break; + case RADEON_LCD_GPIO_MASK: + info->BiosConnector[crtc].DDCType = DDC_LCD; break; default: - pRADEONEnt->PortInfo[crtc]->DDCType = DDC_NONE_DETECTED; + info->BiosConnector[crtc].DDCType = DDC_NONE_DETECTED; break; } } else { - pRADEONEnt->PortInfo[crtc]->DDCType = DDC_NONE_DETECTED; + info->BiosConnector[crtc].DDCType = DDC_NONE_DETECTED; } crtc++; } else { @@ -197,22 +395,28 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) for (j=0; j<2; j++) { if (((portinfo>>8) & 0xf) == id[j]) { if (i == 3) - pRADEONEnt->PortInfo[j]->TMDSType = TMDS_INT; + info->BiosConnector[j].TMDSType = TMDS_INT; else if (i == 7) - pRADEONEnt->PortInfo[j]->TMDSType = TMDS_EXT; + info->BiosConnector[j].TMDSType = TMDS_EXT; - if (pRADEONEnt->PortInfo[j]->DACType == DAC_UNKNOWN) - pRADEONEnt->PortInfo[j]->DACType = (portinfo & 0xf) - 1; + if (info->BiosConnector[j].DACType == DAC_UNKNOWN) + info->BiosConnector[j].DACType = (portinfo & 0xf) - 1; } } } } } + /* R4xx seem to get the connector table backwards */ + tempConnector = info->BiosConnector[0]; + info->BiosConnector[0] = info->BiosConnector[1]; + info->BiosConnector[1] = tempConnector; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bios Connector table: \n"); for (i=0; i<2; i++) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", - i, pRADEONEnt->PortInfo[i]->DDCType, pRADEONEnt->PortInfo[i]->DACType, - pRADEONEnt->PortInfo[i]->TMDSType, pRADEONEnt->PortInfo[i]->ConnectorType); + i, info->BiosConnector[i].DDCType, info->BiosConnector[i].DACType, + info->BiosConnector[i].TMDSType, info->BiosConnector[i].ConnectorType); } } else { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n"); @@ -239,25 +443,27 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) tmp0 = RADEON_BIOS16(tmp + i*2); if (((tmp0 >> 12) & 0x0f) == 0) continue; /* no connector */ if (connector_found > 0) { - if (pRADEONEnt->PortInfo[tmp1]->DDCType == ((tmp0 >> 8) & 0x0f)) + if (info->BiosConnector[tmp1].DDCType == ((tmp0 >> 8) & 0x0f)) continue; /* same connector */ } /* internal DDC_DVI port will get assigned to PortInfo[0], or if there is no DDC_DVI (like in some IGPs). */ tmp1 = ((((tmp0 >> 8) & 0xf) == DDC_DVI) || (tmp1 == 1)) ? 0 : 1; /* determine port info index */ - pRADEONEnt->PortInfo[tmp1]->DDCType = (tmp0 >> 8) & 0x0f; - if (pRADEONEnt->PortInfo[tmp1]->DDCType > DDC_CRT2) pRADEONEnt->PortInfo[tmp1]->DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[tmp1]->DACType = (tmp0 & 0x01) ? DAC_TVDAC : DAC_PRIMARY; - pRADEONEnt->PortInfo[tmp1]->ConnectorType = (tmp0 >> 12) & 0x0f; - if (pRADEONEnt->PortInfo[tmp1]->ConnectorType > CONNECTOR_UNSUPPORTED) pRADEONEnt->PortInfo[tmp1]->ConnectorType = CONNECTOR_UNSUPPORTED; - pRADEONEnt->PortInfo[tmp1]->TMDSType = ((tmp0 >> 4) & 0x01) ? TMDS_EXT : TMDS_INT; + info->BiosConnector[tmp1].DDCType = (tmp0 >> 8) & 0x0f; + if (info->BiosConnector[tmp1].DDCType > DDC_CRT2) + info->BiosConnector[tmp1].DDCType = DDC_NONE_DETECTED; + info->BiosConnector[tmp1].DACType = (tmp0 & 0x01) ? DAC_TVDAC : DAC_PRIMARY; + info->BiosConnector[tmp1].ConnectorType = (tmp0 >> 12) & 0x0f; + if (info->BiosConnector[tmp1].ConnectorType > CONNECTOR_UNSUPPORTED) + info->BiosConnector[tmp1].ConnectorType = CONNECTOR_UNSUPPORTED; + info->BiosConnector[tmp1].TMDSType = ((tmp0 >> 4) & 0x01) ? TMDS_EXT : TMDS_INT; /* some sanity checks */ - if (((pRADEONEnt->PortInfo[tmp1]->ConnectorType != CONNECTOR_DVI_D) && - (pRADEONEnt->PortInfo[tmp1]->ConnectorType != CONNECTOR_DVI_I)) && - pRADEONEnt->PortInfo[tmp1]->TMDSType == TMDS_INT) - pRADEONEnt->PortInfo[tmp1]->TMDSType = TMDS_UNKNOWN; + if (((info->BiosConnector[tmp1].ConnectorType != CONNECTOR_DVI_D) && + (info->BiosConnector[tmp1].ConnectorType != CONNECTOR_DVI_I)) && + info->BiosConnector[tmp1].TMDSType == TMDS_INT) + info->BiosConnector[tmp1].TMDSType = TMDS_UNKNOWN; connector_found += (tmp1 + 1); } @@ -267,69 +473,52 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) } if (info->IsMobility) { - /* For the cases where only one VGA connector is found, - we assume LVDS is not listed in the connector table, - add it in here as the first port. - */ - if ((connector_found < 3) && (pRADEONEnt->PortInfo[tmp1]->ConnectorType == CONNECTOR_CRT)) { - if (connector_found == 1) { - memcpy (&pRADEONEnt->PortInfo[1], &pRADEONEnt->PortInfo[0], - sizeof (pRADEONEnt->PortInfo[0])); - } - pRADEONEnt->PortInfo[0]->DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[0]->TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[0]->DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[0]->ConnectorType = CONNECTOR_PROPRIETARY; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "LVDS port is not in connector table, added in.\n"); - if (connector_found == 0) connector_found = 1; - else connector_found = 3; - } - if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42))) { if ((tmp0 = RADEON_BIOS16(tmp + 0x15))) { if ((tmp1 = RADEON_BIOS8(tmp0+2) & 0x07)) { - pRADEONEnt->PortInfo[0]->DDCType = tmp1; - if (pRADEONEnt->PortInfo[0]->DDCType > DDC_CRT2) { + info->BiosConnector[0].DDCType = tmp1; + if (info->BiosConnector[0].DDCType > DDC_LCD) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown DDCType %d found\n", - pRADEONEnt->PortInfo[0]->DDCType); - pRADEONEnt->PortInfo[0]->DDCType = DDC_NONE_DETECTED; + info->BiosConnector[0].DDCType); + info->BiosConnector[0].DDCType = DDC_NONE_DETECTED; } xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); } } } } else if (connector_found == 2) { - memcpy (&pRADEONEnt->PortInfo[0], &pRADEONEnt->PortInfo[1], - sizeof (pRADEONEnt->PortInfo[0])); - pRADEONEnt->PortInfo[1]->DACType = DAC_UNKNOWN; - pRADEONEnt->PortInfo[1]->TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[1]->DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_NONE; + memcpy (&info->BiosConnector[0], &info->BiosConnector[1], + sizeof (info->BiosConnector[0])); + info->BiosConnector[1].DACType = DAC_UNKNOWN; + info->BiosConnector[1].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[1].DDCType = DDC_NONE_DETECTED; + info->BiosConnector[1].ConnectorType = CONNECTOR_NONE; connector_found = 1; } + connector_found = RADEONBIOSApplyConnectorQuirks(pScrn, connector_found); + if (connector_found == 0) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No connector found in Connector Info Table.\n"); } else { - xf86DrvMsg(0, X_INFO, "Connector0: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", - pRADEONEnt->PortInfo[0]->DDCType, pRADEONEnt->PortInfo[0]->DACType, - pRADEONEnt->PortInfo[0]->TMDSType, pRADEONEnt->PortInfo[0]->ConnectorType); + xf86DrvMsg(0, X_INFO, "Bios Connector0: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + info->BiosConnector[0].DDCType, info->BiosConnector[0].DACType, + info->BiosConnector[0].TMDSType, info->BiosConnector[0].ConnectorType); } if (connector_found == 3) { - xf86DrvMsg(0, X_INFO, "Connector1: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", - pRADEONEnt->PortInfo[1]->DDCType, pRADEONEnt->PortInfo[1]->DACType, - pRADEONEnt->PortInfo[1]->TMDSType, pRADEONEnt->PortInfo[1]->ConnectorType); + xf86DrvMsg(0, X_INFO, "Bios Connector1: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + info->BiosConnector[1].DDCType, info->BiosConnector[1].DACType, + info->BiosConnector[1].TMDSType, info->BiosConnector[1].ConnectorType); } #if 0 /* External TMDS Table, not used now */ if ((tmp0 = RADEON_BIOS16(info->ROMHeaderStart + 0x58))) { - //pRADEONEnt->PortInfo[1]->DDCType = (RADEON_BIOS8(tmp0 + 7) & 0x07); - //pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_DVI_I; - //pRADEONEnt->PortInfo[1]->TMDSType = TMDS_EXT; + //info->BiosConnector[1].DDCType = (RADEON_BIOS8(tmp0 + 7) & 0x07); + //info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I; + //info->BiosConnector[1].TMDSType = TMDS_EXT; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "External TMDS found.\n"); } else { @@ -341,6 +530,100 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) } return TRUE; } +#endif + +Bool RADEONGetTVInfoFromBIOS (xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int offset, refclk, stds; + + if (!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + /* no idea where TV table is on ATOM bios */ + return FALSE; + } else { + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); + if (offset) { + if (RADEON_BIOS8(offset + 6) == 'T') { + switch (RADEON_BIOS8(offset + 7) & 0xf) { + case 1: + radeon_output->default_tvStd = TV_STD_NTSC; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC\n"); + break; + case 2: + radeon_output->default_tvStd = TV_STD_PAL; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL\n"); + break; + case 3: + radeon_output->default_tvStd = TV_STD_PAL_M; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-M\n"); + break; + case 4: + radeon_output->default_tvStd = TV_STD_PAL_60; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-60\n"); + break; + case 5: + radeon_output->default_tvStd = TV_STD_NTSC_J; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC-J\n"); + break; + case 6: + radeon_output->default_tvStd = TV_STD_SCART_PAL; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: SCART-PAL\n"); + break; + default: + radeon_output->default_tvStd = TV_STD_NTSC; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unknown TV standard; defaulting to NTSC\n"); + break; + } + radeon_output->tvStd = radeon_output->default_tvStd; + + refclk = (RADEON_BIOS8(offset + 9) >> 2) & 0x3; + if (refclk == 0) + radeon_output->TVRefClk = 29.498928713; /* MHz */ + else if (refclk == 1) + radeon_output->TVRefClk = 28.636360000; + else if (refclk == 2) + radeon_output->TVRefClk = 14.318180000; + else if (refclk == 3) + radeon_output->TVRefClk = 27.000000000; + + radeon_output->SupportedTVStds = radeon_output->default_tvStd; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standards supported by chip: "); + stds = RADEON_BIOS8(offset + 10) & 0x1f; + if (stds & TV_STD_NTSC) { + radeon_output->SupportedTVStds |= TV_STD_NTSC; + ErrorF("NTSC "); + } + if (stds & TV_STD_PAL) { + radeon_output->SupportedTVStds |= TV_STD_PAL; + ErrorF("PAL "); + } + if (stds & TV_STD_PAL_M) { + radeon_output->SupportedTVStds |= TV_STD_PAL_M; + ErrorF("PAL-M "); + } + if (stds & TV_STD_PAL_60) { + radeon_output->SupportedTVStds |= TV_STD_PAL_60; + ErrorF("PAL-60 "); + } + if (stds & TV_STD_NTSC_J) { + radeon_output->SupportedTVStds |= TV_STD_NTSC_J; + ErrorF("NTSC-J "); + } + if (stds & TV_STD_SCART_PAL) { + radeon_output->SupportedTVStds |= TV_STD_SCART_PAL; + ErrorF("SCART-PAL"); + } + ErrorF("\n"); + + return TRUE; + } + } + } + return FALSE; +} /* Read PLL parameters from BIOS block. Default to typical values if there is no BIOS. */ @@ -370,8 +653,11 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn) if (info->sclk == 0) info->sclk = 200; if (info->mclk == 0) info->mclk = 200; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_pll: %ld, max_pll: %ld, xclk: %d, sclk: %f, mclk: %f\n", - pll->reference_freq, pll->min_pll_freq, pll->max_pll_freq, pll->xclk, info->sclk, info->mclk); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_pll: %u, " + "max_pll: %u, xclk: %d, sclk: %f, mclk: %f\n", + pll->reference_freq, (unsigned)pll->min_pll_freq, + (unsigned)pll->max_pll_freq, pll->xclk, info->sclk, + info->mclk); } else { pll_info_block = RADEON_BIOS16 (info->ROMHeaderStart + 0x30); @@ -390,9 +676,11 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn) return TRUE; } -Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) +Bool RADEONGetLVDSInfoFromBIOS (xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; unsigned long tmp, i; if (!info->VBIOS) return FALSE; @@ -400,26 +688,29 @@ Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) if (info->IsAtomBios) { if((tmp = RADEON_BIOS16 (info->MasterDataStart + 16))) { - info->PanelXRes = RADEON_BIOS16(tmp+6); - info->PanelYRes = RADEON_BIOS16(tmp+10); - info->DotClock = RADEON_BIOS16(tmp+4)*10; - info->HBlank = RADEON_BIOS16(tmp+8); - info->HOverPlus = RADEON_BIOS16(tmp+14); - info->HSyncWidth = RADEON_BIOS16(tmp+16); - info->VBlank = RADEON_BIOS16(tmp+12); - info->VOverPlus = RADEON_BIOS16(tmp+18); - info->VSyncWidth = RADEON_BIOS16(tmp+20); - info->PanelPwrDly = RADEON_BIOS16(tmp+40); - - info->Flags = 0; + radeon_output->PanelXRes = RADEON_BIOS16(tmp+6); + radeon_output->PanelYRes = RADEON_BIOS16(tmp+10); + radeon_output->DotClock = RADEON_BIOS16(tmp+4)*10; + radeon_output->HBlank = RADEON_BIOS16(tmp+8); + radeon_output->HOverPlus = RADEON_BIOS16(tmp+14); + radeon_output->HSyncWidth = RADEON_BIOS16(tmp+16); + radeon_output->VBlank = RADEON_BIOS16(tmp+12); + radeon_output->VOverPlus = RADEON_BIOS16(tmp+18); + radeon_output->VSyncWidth = RADEON_BIOS16(tmp+20); + radeon_output->PanelPwrDly = RADEON_BIOS16(tmp+40); + + if (radeon_output->PanelPwrDly > 2000 || radeon_output->PanelPwrDly < 0) + radeon_output->PanelPwrDly = 2000; + + radeon_output->Flags = 0; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LVDS Info:\n" "XRes: %d, YRes: %d, DotClock: %d\n" "HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n" "VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n", - info->PanelXRes, info->PanelYRes, info->DotClock, - info->HBlank,info->HOverPlus, info->HSyncWidth, - info->VBlank, info->VOverPlus, info->VSyncWidth); + radeon_output->PanelXRes, radeon_output->PanelYRes, radeon_output->DotClock, + radeon_output->HBlank, radeon_output->HOverPlus, radeon_output->HSyncWidth, + radeon_output->VBlank, radeon_output->VOverPlus, radeon_output->VSyncWidth); } else { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No LVDS Info Table found in BIOS!\n"); @@ -444,14 +735,14 @@ Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel ID string: %s\n", stmp); - info->PanelXRes = RADEON_BIOS16(tmp+25); - info->PanelYRes = RADEON_BIOS16(tmp+27); + radeon_output->PanelXRes = RADEON_BIOS16(tmp+25); + radeon_output->PanelYRes = RADEON_BIOS16(tmp+27); xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n", - info->PanelXRes, info->PanelYRes); + radeon_output->PanelXRes, radeon_output->PanelYRes); - info->PanelPwrDly = RADEON_BIOS16(tmp+44); - if (info->PanelPwrDly > 2000 || info->PanelPwrDly < 0) - info->PanelPwrDly = 2000; + radeon_output->PanelPwrDly = RADEON_BIOS16(tmp+44); + if (radeon_output->PanelPwrDly > 2000 || radeon_output->PanelPwrDly < 0) + radeon_output->PanelPwrDly = 2000; /* some panels only work well with certain divider combinations. */ @@ -472,20 +763,20 @@ Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) for (i = 0; i < 32; i++) { tmp0 = RADEON_BIOS16(tmp+64+i*2); if (tmp0 == 0) break; - if ((RADEON_BIOS16(tmp0) == info->PanelXRes) && - (RADEON_BIOS16(tmp0+2) == info->PanelYRes)) { - info->HBlank = (RADEON_BIOS16(tmp0+17) - + if ((RADEON_BIOS16(tmp0) == radeon_output->PanelXRes) && + (RADEON_BIOS16(tmp0+2) == radeon_output->PanelYRes)) { + radeon_output->HBlank = (RADEON_BIOS16(tmp0+17) - RADEON_BIOS16(tmp0+19)) * 8; - info->HOverPlus = (RADEON_BIOS16(tmp0+21) - + radeon_output->HOverPlus = (RADEON_BIOS16(tmp0+21) - RADEON_BIOS16(tmp0+19) - 1) * 8; - info->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8; - info->VBlank = (RADEON_BIOS16(tmp0+24) - + radeon_output->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8; + radeon_output->VBlank = (RADEON_BIOS16(tmp0+24) - RADEON_BIOS16(tmp0+26)); - info->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) - + radeon_output->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) - RADEON_BIOS16(tmp0+26)); - info->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800) >> 11); - info->DotClock = RADEON_BIOS16(tmp0+9) * 10; - info->Flags = 0; + radeon_output->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800) >> 11); + radeon_output->DotClock = RADEON_BIOS16(tmp0+9) * 10; + radeon_output->Flags = 0; } } } @@ -493,9 +784,11 @@ Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) return TRUE; } -Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn) +Bool RADEONGetHardCodedEDIDFromBIOS (xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; unsigned long tmp; char EDID[256]; @@ -511,24 +804,26 @@ Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn) memcpy(EDID, (char*)(info->VBIOS + tmp), 256); - info->DotClock = (*(CARD16*)(EDID+54)) * 10; - info->PanelXRes = (*(CARD8*)(EDID+56)) + ((*(CARD8*)(EDID+58))>>4)*256; - info->HBlank = (*(CARD8*)(EDID+57)) + ((*(CARD8*)(EDID+58)) & 0xf)*256; - info->HOverPlus = (*(CARD8*)(EDID+62)) + ((*(CARD8*)(EDID+65)>>6)*256); - info->HSyncWidth = (*(CARD8*)(EDID+63)) + (((*(CARD8*)(EDID+65)>>4) & 3)*256); - info->PanelYRes = (*(CARD8*)(EDID+59)) + ((*(CARD8*)(EDID+61))>>4)*256; - info->VBlank = ((*(CARD8*)(EDID+60)) + ((*(CARD8*)(EDID+61)) & 0xf)*256); - info->VOverPlus = (((*(CARD8*)(EDID+64))>>4) + (((*(CARD8*)(EDID+65)>>2) & 3)*16)); - info->VSyncWidth = (((*(CARD8*)(EDID+64)) & 0xf) + ((*(CARD8*)(EDID+65)) & 3)*256); - info->Flags = V_NHSYNC | V_NVSYNC; /**(CARD8*)(EDID+71);*/ + radeon_output->DotClock = (*(CARD16*)(EDID+54)) * 10; + radeon_output->PanelXRes = (*(CARD8*)(EDID+56)) + ((*(CARD8*)(EDID+58))>>4)*256; + radeon_output->HBlank = (*(CARD8*)(EDID+57)) + ((*(CARD8*)(EDID+58)) & 0xf)*256; + radeon_output->HOverPlus = (*(CARD8*)(EDID+62)) + ((*(CARD8*)(EDID+65)>>6)*256); + radeon_output->HSyncWidth = (*(CARD8*)(EDID+63)) + (((*(CARD8*)(EDID+65)>>4) & 3)*256); + radeon_output->PanelYRes = (*(CARD8*)(EDID+59)) + ((*(CARD8*)(EDID+61))>>4)*256; + radeon_output->VBlank = ((*(CARD8*)(EDID+60)) + ((*(CARD8*)(EDID+61)) & 0xf)*256); + radeon_output->VOverPlus = (((*(CARD8*)(EDID+64))>>4) + (((*(CARD8*)(EDID+65)>>2) & 3)*16)); + radeon_output->VSyncWidth = (((*(CARD8*)(EDID+64)) & 0xf) + ((*(CARD8*)(EDID+65)) & 3)*256); + radeon_output->Flags = V_NHSYNC | V_NVSYNC; /**(CARD8*)(EDID+71);*/ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardcoded EDID data will be used for TMDS panel\n"); } return TRUE; } -Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn) +Bool RADEONGetTMDSInfoFromBIOS (xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; CARD32 tmp, maxfreq; int i, n; @@ -540,18 +835,19 @@ Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn) maxfreq = RADEON_BIOS16(tmp+4); for (i=0; i<4; i++) { - info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*6+6); + radeon_output->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*6+6); /* This assumes each field in TMDS_PLL has 6 bit as in R300/R420 */ - info->tmds_pll[i].value = ((RADEON_BIOS8(tmp+i*6+8) & 0x3f) | + radeon_output->tmds_pll[i].value = ((RADEON_BIOS8(tmp+i*6+8) & 0x3f) | ((RADEON_BIOS8(tmp+i*6+10) & 0x3f)<<6) | ((RADEON_BIOS8(tmp+i*6+9) & 0xf)<<12) | ((RADEON_BIOS8(tmp+i*6+11) & 0xf)<<16)); xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "TMDS PLL from BIOS: %ld %lx\n", - info->tmds_pll[i].freq, info->tmds_pll[i].value); + "TMDS PLL from BIOS: %u %x\n", + (unsigned)radeon_output->tmds_pll[i].freq, + (unsigned)radeon_output->tmds_pll[i].value); - if (maxfreq == info->tmds_pll[i].freq) { - info->tmds_pll[i].freq = 0xffffffff; + if (maxfreq == radeon_output->tmds_pll[i].freq) { + radeon_output->tmds_pll[i].freq = 0xffffffff; break; } } @@ -567,8 +863,8 @@ Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn) n = RADEON_BIOS8(tmp + 5) + 1; if (n > 4) n = 4; for (i=0; i<n; i++) { - info->tmds_pll[i].value = RADEON_BIOS32(tmp+i*10+0x08); - info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*10+0x10); + radeon_output->tmds_pll[i].value = RADEON_BIOS32(tmp+i*10+0x08); + radeon_output->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*10+0x10); } return TRUE; } else if (RADEON_BIOS8(tmp) == 4) { @@ -576,31 +872,475 @@ Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn) n = RADEON_BIOS8(tmp + 5) + 1; if (n > 4) n = 4; for (i=0; i<n; i++) { - info->tmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); - info->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); + radeon_output->tmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); + radeon_output->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); if (i == 0) stride += 10; else stride += 6; } return TRUE; } - - /* revision 4 has some problem as it appears in RV280, - comment it off for now, use default instead */ - /* - else if (RADEON_BIOS8(tmp) == 4) { - int stride = 0; - n = RADEON_BIOS8(tmp + 5) + 1; - if (n > 4) n = 4; - for (i=0; i<n; i++) { - info->tmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); - info->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); - if (i == 0) stride += 10; - else stride += 6; - } - return TRUE; - } - */ } } return FALSE; } + +/* support for init from bios tables + * + * Based heavily on the netbsd radeonfb driver + * Written by Garrett D'Amore + * Copyright (c) 2006 Itronix Inc. + * + */ + +/* bios table defines */ + +#define RADEON_TABLE_ENTRY_FLAG_MASK 0xe000 +#define RADEON_TABLE_ENTRY_INDEX_MASK 0x1fff +#define RADEON_TABLE_ENTRY_COMMAND_MASK 0x00ff + +#define RADEON_TABLE_FLAG_WRITE_INDEXED 0x0000 +#define RADEON_TABLE_FLAG_WRITE_DIRECT 0x2000 +#define RADEON_TABLE_FLAG_MASK_INDEXED 0x4000 +#define RADEON_TABLE_FLAG_MASK_DIRECT 0x6000 +#define RADEON_TABLE_FLAG_DELAY 0x8000 +#define RADEON_TABLE_FLAG_SCOMMAND 0xa000 + +#define RADEON_TABLE_SCOMMAND_WAIT_MC_BUSY_MASK 0x03 +#define RADEON_TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE 0x08 + +#define RADEON_PLL_FLAG_MASK 0xc0 +#define RADEON_PLL_INDEX_MASK 0x3f + +#define RADEON_PLL_FLAG_WRITE 0x00 +#define RADEON_PLL_FLAG_MASK_BYTE 0x40 +#define RADEON_PLL_FLAG_WAIT 0x80 + +#define RADEON_PLL_WAIT_150MKS 1 +#define RADEON_PLL_WAIT_5MS 2 +#define RADEON_PLL_WAIT_MC_BUSY_MASK 3 +#define RADEON_PLL_WAIT_DLL_READY_MASK 4 +#define RADEON_PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24 5 + +static CARD16 +RADEONValidateBIOSOffset(ScrnInfoPtr pScrn, CARD16 offset) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + CARD8 revision = RADEON_BIOS8(offset - 1); + + if (revision > 0x10) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Bad revision %d for BIOS table\n", revision); + return 0; + } + + if (offset < 0x60) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Bad offset 0x%x for BIOS Table\n", offset); + return 0; + } + + return offset; +} + +Bool +RADEONGetBIOSInitTableOffsets(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + CARD8 val; + + if (!info->VBIOS) { + return FALSE; + } else { + if (info->IsAtomBios) { + return FALSE; + } else { + info->BiosTable.revision = RADEON_BIOS8(info->ROMHeaderStart + 4); + info->BiosTable.rr1_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x0c); + if (info->BiosTable.rr1_offset) { + info->BiosTable.rr1_offset = + RADEONValidateBIOSOffset(pScrn, info->BiosTable.rr1_offset); + } + if (info->BiosTable.revision > 0x09) + return TRUE; + info->BiosTable.rr2_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x4e); + if (info->BiosTable.rr2_offset) { + info->BiosTable.rr2_offset = + RADEONValidateBIOSOffset(pScrn, info->BiosTable.rr2_offset); + } + info->BiosTable.dyn_clk_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x52); + if (info->BiosTable.dyn_clk_offset) { + info->BiosTable.dyn_clk_offset = + RADEONValidateBIOSOffset(pScrn, info->BiosTable.dyn_clk_offset); + } + info->BiosTable.pll_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x46); + if (info->BiosTable.pll_offset) { + info->BiosTable.pll_offset = + RADEONValidateBIOSOffset(pScrn, info->BiosTable.pll_offset); + } + info->BiosTable.mem_config_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x48); + if (info->BiosTable.mem_config_offset) { + info->BiosTable.mem_config_offset = + RADEONValidateBIOSOffset(pScrn, info->BiosTable.mem_config_offset); + } + if (info->BiosTable.mem_config_offset) { + info->BiosTable.mem_reset_offset = info->BiosTable.mem_config_offset; + if (info->BiosTable.mem_reset_offset) { + while (RADEON_BIOS8(info->BiosTable.mem_reset_offset)) + info->BiosTable.mem_reset_offset++; + info->BiosTable.mem_reset_offset++; + info->BiosTable.mem_reset_offset += 2; + } + } + if (info->BiosTable.mem_config_offset) { + info->BiosTable.short_mem_offset = info->BiosTable.mem_config_offset; + if ((info->BiosTable.short_mem_offset != 0) && + (RADEON_BIOS8(info->BiosTable.short_mem_offset - 2) <= 64)) + info->BiosTable.short_mem_offset += + RADEON_BIOS8(info->BiosTable.short_mem_offset - 3); + } + if (info->BiosTable.rr2_offset) { + info->BiosTable.rr3_offset = info->BiosTable.rr2_offset; + if (info->BiosTable.rr3_offset) { + while ((val = RADEON_BIOS8(info->BiosTable.rr3_offset + 1)) != 0) { + if (val & 0x40) + info->BiosTable.rr3_offset += 10; + else if (val & 0x80) + info->BiosTable.rr3_offset += 4; + else + info->BiosTable.rr3_offset += 6; + } + info->BiosTable.rr3_offset += 2; + } + } + + if (info->BiosTable.rr3_offset) { + info->BiosTable.rr4_offset = info->BiosTable.rr3_offset; + if (info->BiosTable.rr4_offset) { + while ((val = RADEON_BIOS8(info->BiosTable.rr4_offset + 1)) != 0) { + if (val & 0x40) + info->BiosTable.rr4_offset += 10; + else if (val & 0x80) + info->BiosTable.rr4_offset += 4; + else + info->BiosTable.rr4_offset += 6; + } + info->BiosTable.rr4_offset += 2; + } + } + + if (info->BiosTable.rr3_offset + 1 == info->BiosTable.pll_offset) { + info->BiosTable.rr3_offset = 0; + info->BiosTable.rr4_offset = 0; + } + + return TRUE; + + } + } +} + +static void +RADEONRestoreBIOSRegBlock(ScrnInfoPtr pScrn, CARD16 table_offset) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD16 offset = table_offset; + CARD16 value, flag, index, count; + CARD32 andmask, ormask, val, channel_complete_mask; + CARD8 command; + + if (offset == 0) + return; + + while ((value = RADEON_BIOS16(offset)) != 0) { + flag = value & RADEON_TABLE_ENTRY_FLAG_MASK; + index = value & RADEON_TABLE_ENTRY_INDEX_MASK; + command = value & RADEON_TABLE_ENTRY_COMMAND_MASK; + + offset += 2; + + switch (flag) { + case RADEON_TABLE_FLAG_WRITE_INDEXED: + val = RADEON_BIOS32(offset); + ErrorF("WRITE INDEXED: 0x%x 0x%x\n", + index, (unsigned)val); + OUTREG(RADEON_MM_INDEX, index); + OUTREG(RADEON_MM_DATA, val); + offset += 4; + break; + + case RADEON_TABLE_FLAG_WRITE_DIRECT: + val = RADEON_BIOS32(offset); + ErrorF("WRITE DIRECT: 0x%x 0x%x\n", index, (unsigned)val); + OUTREG(index, val); + offset += 4; + break; + + case RADEON_TABLE_FLAG_MASK_INDEXED: + andmask = RADEON_BIOS32(offset); + offset += 4; + ormask = RADEON_BIOS32(offset); + offset += 4; + ErrorF("MASK INDEXED: 0x%x 0x%x 0x%x\n", + index, (unsigned)andmask, (unsigned)ormask); + OUTREG(RADEON_MM_INDEX, index); + val = INREG(RADEON_MM_DATA); + val = (val & andmask) | ormask; + OUTREG(RADEON_MM_DATA, val); + break; + + case RADEON_TABLE_FLAG_MASK_DIRECT: + andmask = RADEON_BIOS32(offset); + offset += 4; + ormask = RADEON_BIOS32(offset); + offset += 4; + ErrorF("MASK DIRECT: 0x%x 0x%x 0x%x\n", + index, (unsigned)andmask, (unsigned)ormask); + val = INREG(index); + val = (val & andmask) | ormask; + OUTREG(index, val); + break; + + case RADEON_TABLE_FLAG_DELAY: + count = RADEON_BIOS16(offset); + ErrorF("delay: %d\n", count); + usleep(count); + offset += 2; + break; + + case RADEON_TABLE_FLAG_SCOMMAND: + ErrorF("SCOMMAND 0x%x\n", command); + switch (command) { + case RADEON_TABLE_SCOMMAND_WAIT_MC_BUSY_MASK: + count = RADEON_BIOS16(offset); + ErrorF("SCOMMAND_WAIT_MC_BUSY_MASK %d\n", count); + while (count--) { + if (!(INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & + RADEON_MC_BUSY)) + break; + } + break; + + case RADEON_TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE: + count = RADEON_BIOS16(offset); + ErrorF("SCOMMAND_WAIT_MEM_PWRUP_COMPLETE %d\n", count); + /* may need to take into account how many memory channels + * each card has + */ + if (IS_R300_VARIANT) + channel_complete_mask = R300_MEM_PWRUP_COMPLETE; + else + channel_complete_mask = RADEON_MEM_PWRUP_COMPLETE; + while (count--) { + /* XXX: may need indexed access */ + if ((INREG(RADEON_MEM_STR_CNTL) & + channel_complete_mask) == + channel_complete_mask) + break; + } + break; + + } + offset += 2; + break; + } + } +} + +static void +RADEONRestoreBIOSMemBlock(ScrnInfoPtr pScrn, CARD16 table_offset) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD16 offset = table_offset; + CARD16 count; + CARD32 ormask, val, channel_complete_mask; + CARD8 index; + + if (offset == 0) + return; + + while ((index = RADEON_BIOS8(offset)) != 0xff) { + offset++; + if (index == 0x0f) { + count = 20000; + ErrorF("MEM_WAIT_MEM_PWRUP_COMPLETE %d\n", count); + /* may need to take into account how many memory channels + * each card has + */ + if (IS_R300_VARIANT) + channel_complete_mask = R300_MEM_PWRUP_COMPLETE; + else + channel_complete_mask = RADEON_MEM_PWRUP_COMPLETE; + while (count--) { + /* XXX: may need indexed access */ + if ((INREG(RADEON_MEM_STR_CNTL) & + channel_complete_mask) == + channel_complete_mask) + break; + } + } else { + ormask = RADEON_BIOS16(offset); + offset += 2; + + ErrorF("INDEX RADEON_MEM_SDRAM_MODE_REG %x %x\n", + RADEON_SDRAM_MODE_MASK, (unsigned)ormask); + + /* can this use direct access? */ + OUTREG(RADEON_MM_INDEX, RADEON_MEM_SDRAM_MODE_REG); + val = INREG(RADEON_MM_DATA); + val = (val & RADEON_SDRAM_MODE_MASK) | ormask; + OUTREG(RADEON_MM_DATA, val); + + ormask = (CARD32)index << 24; + + ErrorF("INDEX RADEON_MEM_SDRAM_MODE_REG %x %x\n", + RADEON_B3MEM_RESET_MASK, (unsigned)ormask); + + /* can this use direct access? */ + OUTREG(RADEON_MM_INDEX, RADEON_MEM_SDRAM_MODE_REG); + val = INREG(RADEON_MM_DATA); + val = (val & RADEON_B3MEM_RESET_MASK) | ormask; + OUTREG(RADEON_MM_DATA, val); + } + } +} + +static void +RADEONRestoreBIOSPllBlock(ScrnInfoPtr pScrn, CARD16 table_offset) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + CARD16 offset = table_offset; + CARD8 index, shift; + CARD32 andmask, ormask, val, clk_pwrmgt_cntl; + CARD16 count; + + if (offset == 0) + return; + + while ((index = RADEON_BIOS8(offset)) != 0) { + offset++; + + switch (index & RADEON_PLL_FLAG_MASK) { + case RADEON_PLL_FLAG_WAIT: + switch (index & RADEON_PLL_INDEX_MASK) { + case RADEON_PLL_WAIT_150MKS: + ErrorF("delay: 150 us\n"); + usleep(150); + break; + case RADEON_PLL_WAIT_5MS: + ErrorF("delay: 5 ms\n"); + usleep(5000); + break; + + case RADEON_PLL_WAIT_MC_BUSY_MASK: + count = 1000; + ErrorF("PLL_WAIT_MC_BUSY_MASK %d\n", count); + while (count--) { + if (!(INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & + RADEON_MC_BUSY)) + break; + } + break; + + case RADEON_PLL_WAIT_DLL_READY_MASK: + count = 1000; + ErrorF("PLL_WAIT_DLL_READY_MASK %d\n", count); + while (count--) { + if (INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & + RADEON_DLL_READY) + break; + } + break; + + case RADEON_PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24: + ErrorF("PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24\n"); + clk_pwrmgt_cntl = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL); + if (clk_pwrmgt_cntl & RADEON_CG_NO1_DEBUG_0) { + val = INPLL(pScrn, RADEON_MCLK_CNTL); + /* is this right? */ + val = (val & 0xFFFF0000) | 0x1111; /* seems like we should clear these... */ + OUTPLL(pScrn, RADEON_MCLK_CNTL, val); + usleep(10000); + OUTPLL(pScrn, RADEON_CLK_PWRMGT_CNTL, + clk_pwrmgt_cntl & ~RADEON_CG_NO1_DEBUG_0); + usleep(10000); + } + break; + } + break; + + case RADEON_PLL_FLAG_MASK_BYTE: + shift = RADEON_BIOS8(offset) * 8; + offset++; + + andmask = + (((CARD32)RADEON_BIOS8(offset)) << shift) | + ~((CARD32)0xff << shift); + offset++; + + ormask = ((CARD32)RADEON_BIOS8(offset)) << shift; + offset++; + + ErrorF("PLL_MASK_BYTE 0x%x 0x%x 0x%x 0x%x\n", + index, shift, (unsigned)andmask, (unsigned)ormask); + val = INPLL(pScrn, index); + val = (val & andmask) | ormask; + OUTPLL(pScrn, index, val); + break; + + case RADEON_PLL_FLAG_WRITE: + val = RADEON_BIOS32(offset); + ErrorF("PLL_WRITE 0x%x 0x%x\n", index, (unsigned)val); + OUTPLL(pScrn, index, val); + offset += 4; + break; + } + } +} + +Bool +RADEONPostCardFromBIOSTables(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + + if (!info->VBIOS) { + return FALSE; + } else { + if (info->IsAtomBios) { + return FALSE; + } else { + if (info->BiosTable.rr1_offset) { + ErrorF("rr1 restore, 0x%x\n", info->BiosTable.rr1_offset); + RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr1_offset); + } + if (info->BiosTable.revision < 0x09) { + if (info->BiosTable.pll_offset) { + ErrorF("pll restore, 0x%x\n", info->BiosTable.pll_offset); + RADEONRestoreBIOSPllBlock(pScrn, info->BiosTable.pll_offset); + } + if (info->BiosTable.rr2_offset) { + ErrorF("rr2 restore, 0x%x\n", info->BiosTable.rr2_offset); + RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr2_offset); + } + if (info->BiosTable.rr4_offset) { + ErrorF("rr4 restore, 0x%x\n", info->BiosTable.rr4_offset); + RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr4_offset); + } + if (info->BiosTable.mem_reset_offset) { + ErrorF("mem reset restore, 0x%x\n", info->BiosTable.mem_reset_offset); + RADEONRestoreBIOSMemBlock(pScrn, info->BiosTable.mem_reset_offset); + } + if (info->BiosTable.rr3_offset) { + ErrorF("rr3 restore, 0x%x\n", info->BiosTable.rr3_offset); + RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr3_offset); + } + if (info->BiosTable.dyn_clk_offset) { + ErrorF("dyn_clk restore, 0x%x\n", info->BiosTable.dyn_clk_offset); + RADEONRestoreBIOSPllBlock(pScrn, info->BiosTable.dyn_clk_offset); + } + } + } + } + return TRUE; +} diff --git a/src/radeon_common.h b/src/radeon_common.h index 3f2c6aba..467addf4 100644 --- a/src/radeon_common.h +++ b/src/radeon_common.h @@ -420,6 +420,8 @@ typedef union { #define RADEON_PARAM_SAREA_HANDLE 9 #define RADEON_PARAM_GART_TEX_HANDLE 10 #define RADEON_PARAM_SCRATCH_OFFSET 11 +#define RADEON_PARAM_CARD_TYPE 12 +#define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */ typedef struct drm_radeon_getparam { int param; @@ -473,7 +475,7 @@ typedef struct drm_radeon_set_param { #define RADEON_SETPARAM_PCIGART_LOCATION 3 #define RADEON_SETPARAM_NEW_MEMMAP 4 #define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 - +#define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */ /* 1.14: Clients can allocate/free a surface */ typedef struct drm_radeon_surface_alloc { @@ -486,4 +488,7 @@ typedef struct drm_radeon_surface_free { unsigned int address; } drmRadeonSurfaceFree; +#define DRM_RADEON_VBLANK_CRTC1 1 +#define DRM_RADEON_VBLANK_CRTC2 2 + #endif diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c index 70f7ddc1..6a999af5 100644 --- a/src/radeon_commonfuncs.c +++ b/src/radeon_commonfuncs.c @@ -156,9 +156,10 @@ void FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn) #endif #if 0 - RADEONTRACE(("WaitForIdle (entering): %d entries, stat=0x%08x\n", - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, - INREG(RADEON_RBBM_STATUS))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "WaitForIdle (entering): %d entries, stat=0x%08x\n", + INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, + INREG(RADEON_RBBM_STATUS)); #endif /* Wait for the engine to go idle */ @@ -171,9 +172,10 @@ void FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn) return; } } - RADEONTRACE(("Idle timed out: %u entries, stat=0x%08x\n", - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, - INREG(RADEON_RBBM_STATUS))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Idle timed out: %u entries, stat=0x%08x\n", + INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, + INREG(RADEON_RBBM_STATUS)); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Idle timed out, resetting engine...\n"); RADEONEngineReset(pScrn); diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c new file mode 100644 index 00000000..e976e2c9 --- /dev/null +++ b/src/radeon_crtc.c @@ -0,0 +1,1317 @@ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR + * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdio.h> + +/* X and server generic header files */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "vgaHW.h" +#include "xf86Modes.h" + +/* Driver data structures */ +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_version.h" + +#ifdef XF86DRI +#define _XF86DRI_SERVER_ +#include "radeon_dri.h" +#include "radeon_sarea.h" +#include "sarea.h" +#endif + +void radeon_crtc_load_lut(xf86CrtcPtr crtc); + +static void +radeon_crtc_dpms(xf86CrtcPtr crtc, int mode) +{ + int mask; + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + mask = radeon_crtc->crtc_id ? (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_REQ_EN_B) : (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_VSYNC_DIS); + + + switch(mode) { + case DPMSModeOn: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask); + } + break; + case DPMSModeStandby: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), ~mask); + } + break; + case DPMSModeSuspend: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), ~mask); + } + break; + case DPMSModeOff: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, mask, ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, mask, ~mask); + } + break; + } + + if (mode != DPMSModeOff) + radeon_crtc_load_lut(crtc); +} + +static Bool +radeon_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +static void +radeon_crtc_mode_prepare(xf86CrtcPtr crtc) +{ + radeon_crtc_dpms(crtc, DPMSModeOff); +} + +/* Define common registers for requested video mode */ +static void +RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) +{ + save->ovr_clr = 0; + save->ovr_wid_left_right = 0; + save->ovr_wid_top_bottom = 0; + save->ov0_scale_cntl = 0; + save->subpic_cntl = 0; + save->viph_control = 0; + save->i2c_cntl_1 = 0; + save->rbbm_soft_reset = 0; + save->cap0_trig_cntl = 0; + save->cap1_trig_cntl = 0; + save->bus_cntl = info->BusCntl; + /* + * If bursts are enabled, turn on discards + * Radeon doesn't have write bursts + */ + if (save->bus_cntl & (RADEON_BUS_READ_BURST)) + save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; +} + +static void +RADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save) +{ + ScrnInfoPtr pScrn = crtc->scrn; + + save->surface_cntl = 0; + +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* We must set both apertures as they can be both used to map the entire + * video memory. -BenH. + */ + switch (pScrn->bitsPerPixel) { + case 16: + save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; + save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; + break; + + case 32: + save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; + save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; + break; + } +#endif + +} + +static Bool +RADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save, + int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int Base; +#ifdef XF86DRI + RADEONSAREAPrivPtr pSAREAPriv; + XF86DRISAREAPtr pSAREA; +#endif + + save->crtc_offset = pScrn->fbOffset; +#ifdef XF86DRI + if (info->allowPageFlip) + save->crtc_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL; + else +#endif + save->crtc_offset_cntl = 0; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) + save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; + } + else { + if (IS_R300_VARIANT) + save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } + + Base = pScrn->fbOffset; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) { + /* On r300/r400 when tiling is enabled crtc_offset is set to the address of + * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc + * Makes tiling MUCH easier. + */ + save->crtc_tile_x0_y0 = x | (y << 16); + Base &= ~0x7ff; + } else { + /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the + drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes + flickering when scrolling vertically in a virtual screen, possibly because crtc will + pick up the new offset value at the end of each scanline, but the new offset_cntl value + only after a vsync. We'd probably need to wait (in drm) for vsync and only then update + OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ + /*save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL) & ~0xf;*/ +#if 0 + /* try to get rid of flickering when scrolling at least for 2d */ +#ifdef XF86DRI + if (!info->have3DWindows) +#endif + save->crtc_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; +#endif + + int byteshift = info->CurrentLayout.bitsPerPixel >> 4; + /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ + int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; + Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + save->crtc_offset_cntl = save->crtc_offset_cntl | (y % 16); + } + } + else { + int offset = y * info->CurrentLayout.displayWidth + x; + switch (info->CurrentLayout.pixel_code) { + case 15: + case 16: offset *= 2; break; + case 24: offset *= 3; break; + case 32: offset *= 4; break; + } + Base += offset; + } + + if (crtc->rotatedData != NULL) { + Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; + } + + Base &= ~7; /* 3 lower bits are always 0 */ + + +#ifdef XF86DRI + if (info->directRenderingInited) { + /* note cannot use pScrn->pScreen since this is unitialized when called from + RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ + /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for + *** pageflipping! + ***/ + pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]); + /* can't get at sarea in a semi-sane way? */ + pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); + + pSAREA->frame.x = (Base / info->CurrentLayout.pixel_bytes) + % info->CurrentLayout.displayWidth; + pSAREA->frame.y = (Base / info->CurrentLayout.pixel_bytes) + / info->CurrentLayout.displayWidth; + pSAREA->frame.width = pScrn->frameX1 - x + 1; + pSAREA->frame.height = pScrn->frameY1 - y + 1; + + if (pSAREAPriv->pfCurrentPage == 1) { + Base += info->backOffset - info->frontOffset; + } + } +#endif + save->crtc_offset = Base; + + return TRUE; + +} + +/* Define CRTC registers for requested video mode */ +static Bool +RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save, + DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + + switch (info->CurrentLayout.pixel_code) { + case 4: format = 1; break; + case 8: format = 2; break; + case 15: format = 3; break; /* 555 */ + case 16: format = 4; break; /* 565 */ + case 24: format = 5; break; /* RGB */ + case 32: format = 6; break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", + info->CurrentLayout.bitsPerPixel); + return FALSE; + } + + save->bios_4_scratch = info->SavedReg.bios_4_scratch; + save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN + | RADEON_CRTC_EN + | (format << 8) + | ((mode->Flags & V_DBLSCAN) + ? RADEON_CRTC_DBL_SCAN_EN + : 0) + | ((mode->Flags & V_CSYNC) + ? RADEON_CRTC_CSYNC_EN + : 0) + | ((mode->Flags & V_INTERLACE) + ? RADEON_CRTC_INTERLACE_EN + : 0)); + + save->crtc_ext_cntl |= (RADEON_XCRT_CNT_EN| + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS | + RADEON_CRTC_DISPLAY_DIS); + + save->disp_merge_cntl = info->SavedReg.disp_merge_cntl; + save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; + + save->crtc_more_cntl = 0; + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) { + /* This is to workaround the asic bug for RMX, some versions + of BIOS dosen't have this register initialized correctly. + */ + save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; + } + + save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) + << 16)); + + hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; + if (!hsync_wid) hsync_wid = 1; + if (hsync_wid > 0x3f) hsync_wid = 0x3f; + hsync_start = mode->CrtcHSyncStart - 8; + + save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) + | (hsync_wid << 16) + | ((mode->Flags & V_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + /* This works for double scan mode. */ + save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay - 1) << 16)); + + vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; + if (!vsync_wid) vsync_wid = 1; + if (vsync_wid > 0x1f) vsync_wid = 0x1f; + + save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) + | (vsync_wid << 16) + | ((mode->Flags & V_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0)); + + save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / + (pScrn->bitsPerPixel * 8)); + save->crtc_pitch |= save->crtc_pitch << 16; + + save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; + save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; + save->fp_crtc_h_total_disp = save->crtc_h_total_disp; + save->fp_crtc_v_total_disp = save->crtc_v_total_disp; + + if (info->IsDellServer) { + save->dac2_cntl = info->SavedReg.dac2_cntl; + save->tv_dac_cntl = info->SavedReg.tv_dac_cntl; + save->crtc2_gen_cntl = info->SavedReg.crtc2_gen_cntl; + save->disp_hw_debug = info->SavedReg.disp_hw_debug; + + save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; + save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + + /* For CRT on DAC2, don't turn it on if BIOS didn't + enable it, even it's detected. + */ + save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + save->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16)); + save->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16)); + } + + return TRUE; +} + +static Bool +RADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save, + int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int Base; +#ifdef XF86DRI + RADEONSAREAPrivPtr pSAREAPriv; + XF86DRISAREAPtr pSAREA; +#endif + + /* It seems all fancy options apart from pflip can be safely disabled + */ + save->crtc2_offset = pScrn->fbOffset; +#ifdef XF86DRI + if (info->allowPageFlip) + save->crtc2_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL; + else +#endif + save->crtc2_offset_cntl = 0; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) + save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN; + } + else { + if (IS_R300_VARIANT) + save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } + + Base = pScrn->fbOffset; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) { + /* On r300/r400 when tiling is enabled crtc_offset is set to the address of + * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc + * Makes tiling MUCH easier. + */ + save->crtc2_tile_x0_y0 = x | (y << 16); + Base &= ~0x7ff; + } else { + /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the + drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes + flickering when scrolling vertically in a virtual screen, possibly because crtc will + pick up the new offset value at the end of each scanline, but the new offset_cntl value + only after a vsync. We'd probably need to wait (in drm) for vsync and only then update + OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ + /*save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & ~0xf;*/ +#if 0 + /* try to get rid of flickering when scrolling at least for 2d */ +#ifdef XF86DRI + if (!info->have3DWindows) +#endif + save->crtc2_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; +#endif + + int byteshift = info->CurrentLayout.bitsPerPixel >> 4; + /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ + int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; + Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + save->crtc2_offset_cntl = save->crtc_offset_cntl | (y % 16); + } + } + else { + int offset = y * info->CurrentLayout.displayWidth + x; + switch (info->CurrentLayout.pixel_code) { + case 15: + case 16: offset *= 2; break; + case 24: offset *= 3; break; + case 32: offset *= 4; break; + } + Base += offset; + } + + if (crtc->rotatedData != NULL) { + Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; + } + + Base &= ~7; /* 3 lower bits are always 0 */ + +#ifdef XF86DRI + if (info->directRenderingInited) { + /* note cannot use pScrn->pScreen since this is unitialized when called from + RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ + /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for + *** pageflipping! + ***/ + pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]); + /* can't get at sarea in a semi-sane way? */ + pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); + + pSAREAPriv->crtc2_base = Base; + + if (pSAREAPriv->pfCurrentPage == 1) { + Base += info->backOffset - info->frontOffset; + } + } +#endif + save->crtc2_offset = Base; + + return TRUE; +} + +/* Define CRTC2 registers for requested video mode */ +static Bool +RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save, + DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + + switch (info->CurrentLayout.pixel_code) { + case 4: format = 1; break; + case 8: format = 2; break; + case 15: format = 3; break; /* 555 */ + case 16: format = 4; break; /* 565 */ + case 24: format = 5; break; /* RGB */ + case 32: format = 6; break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", + info->CurrentLayout.bitsPerPixel); + return FALSE; + } + + save->crtc2_h_total_disp = + ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; + if (!hsync_wid) hsync_wid = 1; + if (hsync_wid > 0x3f) hsync_wid = 0x3f; + hsync_start = mode->CrtcHSyncStart - 8; + + save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) + | (hsync_wid << 16) + | ((mode->Flags & V_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + /* This works for double scan mode. */ + save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay - 1) << 16)); + + vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; + if (!vsync_wid) vsync_wid = 1; + if (vsync_wid > 0x1f) vsync_wid = 0x1f; + + save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) + | (vsync_wid << 16) + | ((mode->Flags & V_NVSYNC) + ? RADEON_CRTC2_V_SYNC_POL + : 0)); + + save->crtc2_pitch = ((pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); + save->crtc2_pitch |= save->crtc2_pitch << 16; + + /* check to see if TV DAC is enabled for another crtc and keep it enabled */ + if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON) + save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON; + else + save->crtc2_gen_cntl = 0; + + save->crtc2_gen_cntl |= (RADEON_CRTC2_EN + | (format << 8) + | RADEON_CRTC2_VSYNC_DIS + | RADEON_CRTC2_HSYNC_DIS + | RADEON_CRTC2_DISP_DIS + | ((mode->Flags & V_DBLSCAN) + ? RADEON_CRTC2_DBL_SCAN_EN + : 0) + | ((mode->Flags & V_CSYNC) + ? RADEON_CRTC2_CSYNC_EN + : 0) + | ((mode->Flags & V_INTERLACE) + ? RADEON_CRTC2_INTERLACE_EN + : 0)); + + save->disp2_merge_cntl = info->SavedReg.disp2_merge_cntl; + save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); + + save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; + save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid; + + if (info->ChipFamily == CHIP_FAMILY_RS400) { + save->rs480_unk_e30 = 0x105DC1CC; /* because I'm worth it */ + save->rs480_unk_e34 = 0x2749D000; /* AMD really should */ + save->rs480_unk_e38 = 0x29ca71dc; /* release docs */ + save->rs480_unk_e3c = 0x28FBC3AC; /* this is so a trade secret */ + } + + return TRUE; +} + + +/* Compute n/d with rounding */ +static int RADEONDiv(int n, int d) +{ + return (n + (d / 2)) / d; +} + +/* Define PLL registers for requested video mode */ +static void +RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info, + RADEONSavePtr save, RADEONPLLPtr pll, + double dot_clock) +{ + unsigned long freq = dot_clock * 100; + + struct { + int divider; + int bitvalue; + } *post_div, post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + * Reference Manual (Technical Reference + * Manual P/N RRG-G04100-C Rev. 0.04), page + * 3-17 (PLL_DIV_[3:0]). + */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + { 16, 5 }, /* VCLK_SRC/16 */ + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + + if (info->UseBiosDividers) { + save->ppll_ref_div = info->RefDivider; + save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); + save->htotal_cntl = 0; + return; + } + + if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; + if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + save->pll_output_freq = post_div->divider * freq; + + if (save->pll_output_freq >= pll->min_pll_freq + && save->pll_output_freq <= pll->max_pll_freq) break; + } + + if (!post_div->divider) { + save->pll_output_freq = freq; + post_div = &post_divs[0]; + } + + save->dot_clock_freq = freq; + save->feedback_div = RADEONDiv(pll->reference_div + * save->pll_output_freq, + pll->reference_freq); + save->post_div = post_div->divider; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "dc=%u, of=%u, fd=%d, pd=%d\n", + (unsigned)save->dot_clock_freq, + (unsigned)save->pll_output_freq, + save->feedback_div, + save->post_div); + + save->ppll_ref_div = pll->reference_div; + save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); + save->htotal_cntl = 0; + + save->vclk_ecp_cntl = (info->SavedReg.vclk_ecp_cntl & + ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; + +} + +/* Define PLL2 registers for requested video mode */ +static void +RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, + RADEONPLLPtr pll, double dot_clock, + int no_odd_postdiv) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long freq = dot_clock * 100; + + struct { + int divider; + int bitvalue; + } *post_div, post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + * Reference Manual (Technical Reference + * Manual P/N RRG-G04100-C Rev. 0.04), page + * 3-17 (PLL_DIV_[3:0]). + */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + + if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; + if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + /* Odd post divider value don't work properly on the second digital + * output + */ + if (no_odd_postdiv && (post_div->divider & 1)) + continue; + save->pll_output_freq_2 = post_div->divider * freq; + if (save->pll_output_freq_2 >= pll->min_pll_freq + && save->pll_output_freq_2 <= pll->max_pll_freq) break; + } + + if (!post_div->divider) { + save->pll_output_freq_2 = freq; + post_div = &post_divs[0]; + } + + save->dot_clock_freq_2 = freq; + save->feedback_div_2 = RADEONDiv(pll->reference_div + * save->pll_output_freq_2, + pll->reference_freq); + save->post_div_2 = post_div->divider; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "dc=%u, of=%u, fd=%d, pd=%d\n", + (unsigned)save->dot_clock_freq_2, + (unsigned)save->pll_output_freq_2, + save->feedback_div_2, + save->post_div_2); + + save->p2pll_ref_div = pll->reference_div; + save->p2pll_div_0 = (save->feedback_div_2 | + (post_div->bitvalue << 16)); + save->htotal_cntl2 = 0; + + save->pixclks_cntl = ((info->SavedReg.pixclks_cntl & + ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | + RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); + +} + +static void +radeon_update_tv_routing(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + /* pixclks_cntl controls tv clock routing */ + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl); +} + +static void +radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode, int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + Bool tilingOld = info->tilingEnabled; + int i = 0; + double dot_clock = 0; + Bool no_odd_post_div = FALSE; + Bool update_tv_routing = FALSE; + + + if (info->allowColorTiling) { + info->tilingEnabled = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; +#ifdef XF86DRI + if (info->directRenderingEnabled && (info->tilingEnabled != tilingOld)) { + RADEONSAREAPrivPtr pSAREAPriv; + if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_SWITCH_TILING, (info->tilingEnabled ? 1 : 0)) < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed changing tiling status\n"); + pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + info->tilingEnabled = pSAREAPriv->tiling_enabled ? TRUE : FALSE; + } +#endif + } + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (output->crtc == crtc) { + if (radeon_output->MonType != MT_CRT) + no_odd_post_div = TRUE; + } + } + + ErrorF("init memmap\n"); + RADEONInitMemMapRegisters(pScrn, &info->ModeReg, info); + ErrorF("init common\n"); + RADEONInitCommonRegisters(&info->ModeReg, info); + + RADEONInitSurfaceCntl(crtc, &info->ModeReg); + + switch (radeon_crtc->crtc_id) { + case 0: + ErrorF("init crtc1\n"); + RADEONInitCrtcRegisters(crtc, &info->ModeReg, adjusted_mode); + RADEONInitCrtcBase(crtc, &info->ModeReg, x, y); + dot_clock = adjusted_mode->Clock / 1000.0; + if (dot_clock) { + ErrorF("init pll1\n"); + RADEONInitPLLRegisters(pScrn, info, &info->ModeReg, &info->pll, dot_clock); + } else { + info->ModeReg.ppll_ref_div = info->SavedReg.ppll_ref_div; + info->ModeReg.ppll_div_3 = info->SavedReg.ppll_div_3; + info->ModeReg.htotal_cntl = info->SavedReg.htotal_cntl; + } + break; + case 1: + ErrorF("init crtc2\n"); + RADEONInitCrtc2Registers(crtc, &info->ModeReg, adjusted_mode); + RADEONInitCrtc2Base(crtc, &info->ModeReg, x, y); + dot_clock = adjusted_mode->Clock / 1000.0; + if (dot_clock) { + ErrorF("init pll2\n"); + RADEONInitPLL2Registers(pScrn, &info->ModeReg, &info->pll, dot_clock, no_odd_post_div); + } + break; + } + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (output->crtc == crtc) { + if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) { + switch (radeon_crtc->crtc_id) { + case 0: + RADEONAdjustCrtcRegistersForTV(pScrn, &info->ModeReg, adjusted_mode, output); + RADEONAdjustPLLRegistersForTV(pScrn, &info->ModeReg, adjusted_mode, output); + update_tv_routing = TRUE; + break; + case 1: + RADEONAdjustCrtc2RegistersForTV(pScrn, &info->ModeReg, adjusted_mode, output); + RADEONAdjustPLL2RegistersForTV(pScrn, &info->ModeReg, adjusted_mode, output); + break; + } + } + } + } + + ErrorF("restore memmap\n"); + RADEONRestoreMemMapRegisters(pScrn, &info->ModeReg); + ErrorF("restore common\n"); + RADEONRestoreCommonRegisters(pScrn, &info->ModeReg); + + switch (radeon_crtc->crtc_id) { + case 0: + ErrorF("restore crtc1\n"); + RADEONRestoreCrtcRegisters(pScrn, &info->ModeReg); + ErrorF("restore pll1\n"); + RADEONRestorePLLRegisters(pScrn, &info->ModeReg); + break; + case 1: + ErrorF("restore crtc2\n"); + RADEONRestoreCrtc2Registers(pScrn, &info->ModeReg); + ErrorF("restore pll2\n"); + RADEONRestorePLL2Registers(pScrn, &info->ModeReg); + break; + } + + /* pixclks_cntl handles tv-out clock routing */ + if (update_tv_routing) + radeon_update_tv_routing(pScrn, &info->ModeReg); + + if (info->DispPriority) + RADEONInitDispBandwidth(pScrn); + + if (info->tilingEnabled != tilingOld) { + /* need to redraw front buffer, I guess this can be considered a hack ? */ + xf86EnableDisableFBAccess(pScrn->scrnIndex, FALSE); + RADEONChangeSurfaces(pScrn); + xf86EnableDisableFBAccess(pScrn->scrnIndex, TRUE); + /* xf86SetRootClip would do, but can't access that here */ + } + + /* reset ecp_div for Xv */ + info->ecp_div = -1; + +} + +static void +radeon_crtc_mode_commit(xf86CrtcPtr crtc) +{ + radeon_crtc_dpms(crtc, DPMSModeOn); +} + +void radeon_crtc_load_lut(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int i; + + if (!crtc->enabled) + return; + + PAL_SELECT(radeon_crtc->crtc_id); + + for (i = 0; i < 256; i++) { + OUTPAL(i, radeon_crtc->lut_r[i], radeon_crtc->lut_g[i], radeon_crtc->lut_b[i]); + } + +} + + +static void +radeon_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, + CARD16 *blue, int size) +{ + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + ScrnInfoPtr pScrn = crtc->scrn; + int i, j; + + if (pScrn->depth == 16) { + for (i = 0; i < 64; i++) { + if (i <= 31) { + for (j = 0; j < 8; j++) { + radeon_crtc->lut_r[i * 8 + j] = red[i] >> 8; + radeon_crtc->lut_b[i * 8 + j] = blue[i] >> 8; + } + } + + for (j = 0; j < 4; j++) { + radeon_crtc->lut_g[i * 4 + j] = green[i] >> 8; + } + } + } else { + for (i = 0; i < 256; i++) { + radeon_crtc->lut_r[i] = red[i] >> 8; + radeon_crtc->lut_g[i] = green[i] >> 8; + radeon_crtc->lut_b[i] = blue[i] >> 8; + } + } + + radeon_crtc_load_lut(crtc); +} + +static Bool +radeon_crtc_lock(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + +#ifdef XF86DRI + if (info->CPStarted && pScrn->pScreen) { + DRILock(pScrn->pScreen, 0); + if (info->accelOn) + RADEON_SYNC(info, pScrn); + return TRUE; + } +#endif + if (info->accelOn) + RADEON_SYNC(info, pScrn); + + return FALSE; + +} + +static void +radeon_crtc_unlock(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + +#ifdef XF86DRI + if (info->CPStarted && pScrn->pScreen) DRIUnlock(pScrn->pScreen); +#endif + + if (info->accelOn) + RADEON_SYNC(info, pScrn); +} + +#ifdef USE_XAA +/** + * Allocates memory from the XF86 linear allocator, but also purges + * memory if possible to cause the allocation to succeed. + */ +static FBLinearPtr +radeon_xf86AllocateOffscreenLinear(ScreenPtr pScreen, int length, + int granularity, + MoveLinearCallbackProcPtr moveCB, + RemoveLinearCallbackProcPtr removeCB, + pointer privData) +{ + FBLinearPtr linear; + int max_size; + + linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB, + removeCB, privData); + if (linear != NULL) + return linear; + + /* The above allocation didn't succeed, so purge unlocked stuff and try + * again. + */ + xf86QueryLargestOffscreenLinear(pScreen, &max_size, granularity, + PRIORITY_EXTREME); + + if (max_size < length) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + + linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB, + removeCB, privData); + + return linear; +} +#endif + +/** + * Allocates memory for a locked-in-framebuffer shadow of the given + * width and height for this CRTC's rotated shadow framebuffer. + */ + +static void * +radeon_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height) +{ + ScrnInfoPtr pScrn = crtc->scrn; + ScreenPtr pScreen = pScrn->pScreen; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + unsigned long rotate_pitch; + unsigned long rotate_offset; + int align = 4096, size; + int cpp = pScrn->bitsPerPixel / 8; + + rotate_pitch = pScrn->displayWidth * cpp; + size = rotate_pitch * height; + +#ifdef USE_EXA + /* We could get close to what we want here by just creating a pixmap like + * normal, but we have to lock it down in framebuffer, and there is no + * setter for offscreen area locking in EXA currently. So, we just + * allocate offscreen memory and fake up a pixmap header for it. + */ + if (info->useEXA) { + assert(radeon_crtc->rotate_mem_exa == NULL); + + radeon_crtc->rotate_mem_exa = exaOffscreenAlloc(pScreen, size, align, + TRUE, NULL, NULL); + if (radeon_crtc->rotate_mem_exa == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow memory for rotated CRTC\n"); + return NULL; + } + rotate_offset = radeon_crtc->rotate_mem_exa->offset; + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + /* The XFree86 linear allocator operates in units of screen pixels, + * sadly. + */ + size = (size + cpp - 1) / cpp; + align = (align + cpp - 1) / cpp; + + assert(radeon_crtc->rotate_mem_xaa == NULL); + + radeon_crtc->rotate_mem_xaa = + radeon_xf86AllocateOffscreenLinear(pScreen, size, align, + NULL, NULL, NULL); + if (radeon_crtc->rotate_mem_xaa == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow memory for rotated CRTC\n"); + return NULL; + } +#ifdef XF86DRI + rotate_offset = info->frontOffset + + radeon_crtc->rotate_mem_xaa->offset * cpp; +#endif + } +#endif /* USE_XAA */ + + return info->FB + rotate_offset; +} + +/** + * Creates a pixmap for this CRTC's rotated shadow framebuffer. + */ +static PixmapPtr +radeon_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) +{ + ScrnInfoPtr pScrn = crtc->scrn; + unsigned long rotate_pitch; + PixmapPtr rotate_pixmap; + int cpp = pScrn->bitsPerPixel / 8; + + if (!data) + data = radeon_crtc_shadow_allocate(crtc, width, height); + + rotate_pitch = pScrn->displayWidth * cpp; + + rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, + width, height, + pScrn->depth, + pScrn->bitsPerPixel, + rotate_pitch, + data); + + if (rotate_pixmap == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow pixmap for rotated CRTC\n"); + } + + return rotate_pixmap; +} + +static void +radeon_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + if (rotate_pixmap) + FreeScratchPixmapHeader(rotate_pixmap); + + if (data) { +#ifdef USE_EXA + if (info->useEXA && radeon_crtc->rotate_mem_exa != NULL) { + exaOffscreenFree(pScrn->pScreen, radeon_crtc->rotate_mem_exa); + radeon_crtc->rotate_mem_exa = NULL; + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + xf86FreeOffscreenLinear(radeon_crtc->rotate_mem_xaa); + radeon_crtc->rotate_mem_xaa = NULL; + } +#endif /* USE_XAA */ + } +} + +static const xf86CrtcFuncsRec radeon_crtc_funcs = { + .dpms = radeon_crtc_dpms, + .save = NULL, /* XXX */ + .restore = NULL, /* XXX */ + .mode_fixup = radeon_crtc_mode_fixup, + .prepare = radeon_crtc_mode_prepare, + .mode_set = radeon_crtc_mode_set, + .commit = radeon_crtc_mode_commit, + .gamma_set = radeon_crtc_gamma_set, + .lock = radeon_crtc_lock, + .unlock = radeon_crtc_unlock, + .shadow_create = radeon_crtc_shadow_create, + .shadow_allocate = radeon_crtc_shadow_allocate, + .shadow_destroy = radeon_crtc_shadow_destroy, + .set_cursor_colors = radeon_crtc_set_cursor_colors, + .set_cursor_position = radeon_crtc_set_cursor_position, + .show_cursor = radeon_crtc_show_cursor, + .hide_cursor = radeon_crtc_hide_cursor, + .load_cursor_argb = radeon_crtc_load_cursor_argb, + .destroy = NULL, /* XXX */ +}; + +Bool RADEONAllocateControllers(ScrnInfoPtr pScrn) +{ + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + if (pRADEONEnt->Controller[0]) + return TRUE; + + pRADEONEnt->pCrtc[0] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs); + if (!pRADEONEnt->pCrtc[0]) + return FALSE; + + pRADEONEnt->Controller[0] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1); + if (!pRADEONEnt->Controller[0]) + return FALSE; + + pRADEONEnt->pCrtc[0]->driver_private = pRADEONEnt->Controller[0]; + pRADEONEnt->Controller[0]->crtc_id = 0; + + if (!pRADEONEnt->HasCRTC2) + return TRUE; + + pRADEONEnt->pCrtc[1] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs); + if (!pRADEONEnt->pCrtc[1]) + return FALSE; + + pRADEONEnt->Controller[1] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1); + if (!pRADEONEnt->Controller[1]) + { + xfree(pRADEONEnt->Controller[0]); + return FALSE; + } + + pRADEONEnt->pCrtc[1]->driver_private = pRADEONEnt->Controller[1]; + pRADEONEnt->Controller[1]->crtc_id = 1; + return TRUE; +} + +/** + * In the current world order, there are lists of modes per output, which may + * or may not include the mode that was asked to be set by XFree86's mode + * selection. Find the closest one, in the following preference order: + * + * - Equality + * - Closer in size to the requested mode, but no larger + * - Closer in refresh rate to the requested mode. + */ +DisplayModePtr +RADEONCrtcFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + DisplayModePtr pBest = NULL, pScan = NULL; + int i; + + /* Assume that there's only one output connected to the given CRTC. */ + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc && output->probed_modes != NULL) + { + pScan = output->probed_modes; + break; + } + } + + /* If the pipe doesn't have any detected modes, just let the system try to + * spam the desired mode in. + */ + if (pScan == NULL) { + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No crtc mode list for crtc %d," + "continuing with desired mode\n", radeon_crtc->crtc_id); + return pMode; + } + + for (; pScan != NULL; pScan = pScan->next) { + assert(pScan->VRefresh != 0.0); + + /* If there's an exact match, we're done. */ + if (xf86ModesEqual(pScan, pMode)) { + pBest = pMode; + break; + } + + /* Reject if it's larger than the desired mode. */ + if (pScan->HDisplay > pMode->HDisplay || + pScan->VDisplay > pMode->VDisplay) + { + continue; + } + + if (pBest == NULL) { + pBest = pScan; + continue; + } + + /* Find if it's closer to the right size than the current best + * option. + */ + if ((pScan->HDisplay > pBest->HDisplay && + pScan->VDisplay >= pBest->VDisplay) || + (pScan->HDisplay >= pBest->HDisplay && + pScan->VDisplay > pBest->VDisplay)) + { + pBest = pScan; + continue; + } + + /* Find if it's still closer to the right refresh than the current + * best resolution. + */ + if (pScan->HDisplay == pBest->HDisplay && + pScan->VDisplay == pBest->VDisplay && + (fabs(pScan->VRefresh - pMode->VRefresh) < + fabs(pBest->VRefresh - pMode->VRefresh))) { + pBest = pScan; + } + } + + if (pBest == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No suitable mode found to program for the pipe.\n" + " continuing with desired mode %dx%d@%.1f\n", + pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); + } else if (!xf86ModesEqual(pBest, pMode)) { + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + int crtc = radeon_crtc->crtc_id; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 " + "mode %dx%d@%.1f\n", crtc, + pBest->HDisplay, pBest->VDisplay, pBest->VRefresh, + pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); + pMode = pBest; + } + return pMode; +} + diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c index a45198ae..f19f2bc0 100644 --- a/src/radeon_cursor.c +++ b/src/radeon_cursor.c @@ -31,7 +31,7 @@ #endif #define RADEONCTRACE(x) -/* #define RADEONCTRACE(x) RADEONTRACE(x) */ +/*#define RADEONCTRACE(x) RADEONTRACE(x) */ /* * Authors: @@ -55,24 +55,13 @@ #include "radeon_version.h" #include "radeon_reg.h" #include "radeon_macros.h" -#include "radeon_mergedfb.h" /* X and server generic header files */ #include "xf86.h" -/* Mono ARGB cursor colours (premultiplied). */ -static CARD32 mono_cursor_color[] = { - 0x00000000, /* White, fully transparent. */ - 0x00000000, /* Black, fully transparent. */ - 0xffffffff, /* White, fully opaque. */ - 0xff000000, /* Black, fully opaque. */ -}; - #define CURSOR_WIDTH 64 #define CURSOR_HEIGHT 64 -#define COMMON_CURSOR_SWAPPING_START() RADEON_SYNC(info, pScrn) - /* * The cursor bits are always 32bpp. On MSBFirst buses, * configure byte swapping to swap 32 bit units when writing @@ -84,7 +73,6 @@ static CARD32 mono_cursor_color[] = { #define CURSOR_SWAPPING_DECL_MMIO unsigned char *RADEONMMIO = info->MMIO; #define CURSOR_SWAPPING_START() \ do { \ - COMMON_CURSOR_SWAPPING_START(); \ OUTREG(RADEON_SURFACE_CNTL, \ (info->ModeReg.surface_cntl | \ RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP) & \ @@ -96,278 +84,151 @@ static CARD32 mono_cursor_color[] = { #else #define CURSOR_SWAPPING_DECL_MMIO -#define CURSOR_SWAPPING_START() \ - do { \ - COMMON_CURSOR_SWAPPING_START(); \ - } while (0) +#define CURSOR_SWAPPING_START() #define CURSOR_SWAPPING_END() #endif - -/* Set cursor foreground and background colors */ -static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +void +radeon_crtc_show_cursor (xf86CrtcPtr crtc) { - RADEONInfoPtr info = RADEONPTR(pScrn); - CARD32 *pixels = (CARD32 *)(pointer)(info->FB + info->cursor_offset + pScrn->fbOffset); - int pixel, i; - CURSOR_SWAPPING_DECL_MMIO - - RADEONCTRACE(("RADEONSetCursorColors\n")); - -#ifdef ARGB_CURSOR - /* Don't recolour cursors set with SetCursorARGB. */ - if (info->cursor_argb) - return; -#endif + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + int crtc_id = radeon_crtc->crtc_id; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; - fg |= 0xff000000; - bg |= 0xff000000; + if (crtc_id == 0) + OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN | 2 << 20, + ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK)); + else if (crtc_id == 1) + OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN | 2 << 20, + ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_CUR_MODE_MASK)); +} - /* Don't recolour the image if we don't have to. */ - if (fg == info->cursor_fg && bg == info->cursor_bg) - return; +void +radeon_crtc_hide_cursor (xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + int crtc_id = radeon_crtc->crtc_id; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; - CURSOR_SWAPPING_START(); + if (crtc_id == 0) + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_CUR_EN); + else if (crtc_id == 1) + OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN); - /* Note: We assume that the pixels are either fully opaque or fully - * transparent, so we won't premultiply them, and we can just - * check for non-zero pixel values; those are either fg or bg - */ - for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT; i++, pixels++) - if ((pixel = *pixels)) - *pixels = (pixel == info->cursor_fg) ? fg : bg; - CURSOR_SWAPPING_END(); - info->cursor_fg = fg; - info->cursor_bg = bg; } - -/* Set cursor position to (x,y) with offset into cursor bitmap at - * (xorigin,yorigin) - */ -static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +void +radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) { + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + int crtc_id = radeon_crtc->crtc_id; RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - xf86CursorInfoPtr cursor = info->cursor; - int xorigin = 0; - int yorigin = 0; - int total_y = pScrn->frameY1 - pScrn->frameY0; - int stride = 256; - - if(info->MergedFB) { - RADEONCTRACE(("RADEONSetCursorPositionMerged\n")); - RADEONSetCursorPositionMerged(pScrn, x, y); - return; - } - - RADEONCTRACE(("RADEONSetCursorPosition\n")); + int xorigin = 0, yorigin = 0; + int stride = 256; + DisplayModePtr mode = &crtc->mode; if (x < 0) xorigin = -x+1; if (y < 0) yorigin = -y+1; - if (y > total_y) y = total_y; - if (info->Flags & V_DBLSCAN) y *= 2; - if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; - if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; + if (xorigin >= CURSOR_WIDTH) xorigin = CURSOR_WIDTH - 1; + if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1; - if (!info->IsSecondary) { + if (mode->Flags & V_INTERLACE) + y /= 2; + else if (mode->Flags & V_DBLSCAN) + y *= 2; + + if (crtc_id == 0) { OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK | (xorigin << 16) | yorigin)); OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); - RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d\n", - info->cursor_offset + pScrn->fbOffset, yorigin, stride)); + RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d, temp %08X\n", + info->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); OUTREG(RADEON_CUR_OFFSET, info->cursor_offset + pScrn->fbOffset + yorigin * stride); - } else { + } else if (crtc_id == 1) { OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK | (xorigin << 16) | yorigin)); OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK - | ((xorigin ? 0 : x) << 16) - | (yorigin ? 0 : y))); + | ((xorigin ? 0 : x) << 16) + | (yorigin ? 0 : y))); + RADEONCTRACE(("cursor_offset2: 0x%x, yorigin: %d, stride: %d, temp %08X\n", + info->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); OUTREG(RADEON_CUR2_OFFSET, - info->cursor_offset + pScrn->fbOffset + yorigin * stride); + info->cursor_offset + pScrn->fbOffset + yorigin * stride); } } -/* Copy cursor image from `image' to video memory. RADEONSetCursorPosition - * will be called after this, so we can ignore xorigin and yorigin. - */ -static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) +void +radeon_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - CARD8 *s = (CARD8 *)(pointer)image; - CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_offset + pScrn->fbOffset); - CARD32 save1 = 0; - CARD32 save2 = 0; - CARD8 chunk; - CARD32 i, j; - - RADEONCTRACE(("RADEONLoadCursorImage (at %x)\n", info->cursor_offset)); - - if (!info->IsSecondary) { - save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20); - save1 |= (CARD32) (2 << 20); - OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN); - } + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD32 *pixels = (CARD32 *)(pointer)(info->FB + info->cursor_offset + pScrn->fbOffset); + int pixel, i; + CURSOR_SWAPPING_DECL_MMIO - if (info->IsSecondary || info->MergedFB) { - save2 = INREG(RADEON_CRTC2_GEN_CNTL) & ~(CARD32) (3 << 20); - save2 |= (CARD32) (2 << 20); - OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN); - } + RADEONCTRACE(("RADEONSetCursorColors\n")); #ifdef ARGB_CURSOR - info->cursor_argb = FALSE; + /* Don't recolour cursors set with SetCursorARGB. */ + if (info->cursor_argb) + return; #endif - /* - * Convert the bitmap to ARGB32. - * - * HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 always places - * source in the low bit of the pair and mask in the high bit, - * and MSBFirst machines set HARDWARE_CURSOR_BIT_ORDER_MSBFIRST - * (which actually bit swaps the image) to make the bits LSBFirst - */ - CURSOR_SWAPPING_START(); -#define ARGB_PER_CHUNK (8 * sizeof (chunk) / 2) - for (i = 0; i < (CURSOR_WIDTH * CURSOR_HEIGHT / ARGB_PER_CHUNK); i++) { - chunk = *s++; - for (j = 0; j < ARGB_PER_CHUNK; j++, chunk >>= 2) - *d++ = mono_cursor_color[chunk & 3]; - } - CURSOR_SWAPPING_END(); - - info->cursor_bg = mono_cursor_color[2]; - info->cursor_fg = mono_cursor_color[3]; - - if (!info->IsSecondary) - OUTREG(RADEON_CRTC_GEN_CNTL, save1); - - if (info->IsSecondary || info->MergedFB) - OUTREG(RADEON_CRTC2_GEN_CNTL, save2); - -} - -/* Hide hardware cursor. */ -static void RADEONHideCursor(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - RADEONCTRACE(("RADEONHideCursor\n")); - - if (info->IsSecondary || info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN); - - if (!info->IsSecondary) - OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_CUR_EN); -} - -/* Show hardware cursor. */ -static void RADEONShowCursor(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - RADEONCTRACE(("RADEONShowCursor\n")); + fg |= 0xff000000; + bg |= 0xff000000; - if (info->IsSecondary || info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN, - ~RADEON_CRTC2_CUR_EN); + /* Don't recolour the image if we don't have to. */ + if (fg == info->cursor_fg && bg == info->cursor_bg) + return; - if (!info->IsSecondary) - OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN, - ~RADEON_CRTC_CUR_EN); -} + CURSOR_SWAPPING_START(); -/* Determine if hardware cursor is in use. */ -static Bool RADEONUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - RADEONInfoPtr info = RADEONPTR(pScrn); + /* Note: We assume that the pixels are either fully opaque or fully + * transparent, so we won't premultiply them, and we can just + * check for non-zero pixel values; those are either fg or bg + */ + for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT; i++, pixels++) + if ((pixel = *pixels)) + *pixels = (pixel == info->cursor_fg) ? fg : bg; - return info->cursor ? TRUE : FALSE; + CURSOR_SWAPPING_END(); + info->cursor_fg = fg; + info->cursor_bg = bg; } #ifdef ARGB_CURSOR -#include "cursorstr.h" -static Bool RADEONUseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs) -{ - if (RADEONUseHWCursor(pScreen, pCurs) && - pCurs->bits->height <= CURSOR_HEIGHT && pCurs->bits->width <= CURSOR_WIDTH) - return TRUE; - return FALSE; -} - -static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) +void +radeon_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) { + ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_offset + pScrn->fbOffset); - int x, y, w, h; - CARD32 save1 = 0; - CARD32 save2 = 0; - CARD32 *image = pCurs->bits->argb; - CARD32 *i; RADEONCTRACE(("RADEONLoadCursorARGB\n")); - if (!info->IsSecondary) { - save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20); - save1 |= (CARD32) (2 << 20); - OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN); - } - - if (info->IsSecondary || info->MergedFB) { - save2 = INREG(RADEON_CRTC2_GEN_CNTL) & ~(CARD32) (3 << 20); - save2 |= (CARD32) (2 << 20); - OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN); - } - -#ifdef ARGB_CURSOR info->cursor_argb = TRUE; -#endif CURSOR_SWAPPING_START(); - w = pCurs->bits->width; - if (w > CURSOR_WIDTH) - w = CURSOR_WIDTH; - h = pCurs->bits->height; - if (h > CURSOR_HEIGHT) - h = CURSOR_HEIGHT; - for (y = 0; y < h; y++) - { - i = image; - image += pCurs->bits->width; - for (x = 0; x < w; x++) - *d++ = *i++; - /* pad to the right with transparent */ - for (; x < CURSOR_WIDTH; x++) - *d++ = 0; - } - /* pad below with transparent */ - for (; y < CURSOR_HEIGHT; y++) - for (x = 0; x < CURSOR_WIDTH; x++) - *d++ = 0; + memcpy (d, image, CURSOR_HEIGHT * CURSOR_WIDTH * 4); CURSOR_SWAPPING_END (); - - if (!info->IsSecondary) - OUTREG(RADEON_CRTC_GEN_CNTL, save1); - - if (info->IsSecondary || info->MergedFB) - OUTREG(RADEON_CRTC2_GEN_CNTL, save2); - } #endif @@ -378,39 +239,12 @@ Bool RADEONCursorInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - xf86CursorInfoPtr cursor; int width; int width_bytes; int height; int size_bytes; - if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE; - cursor->MaxWidth = CURSOR_WIDTH; - cursor->MaxHeight = CURSOR_HEIGHT; - cursor->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP - | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* this is a lie -- - * HARDWARE_CURSOR_BIT_ORDER_MSBFIRST - * actually inverts the bit order, so - * this switches to LSBFIRST - */ - | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST -#endif - | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1); - - cursor->SetCursorColors = RADEONSetCursorColors; - cursor->SetCursorPosition = RADEONSetCursorPosition; - cursor->LoadCursorImage = RADEONLoadCursorImage; - cursor->HideCursor = RADEONHideCursor; - cursor->ShowCursor = RADEONShowCursor; - cursor->UseHWCursor = RADEONUseHWCursor; - -#ifdef ARGB_CURSOR - cursor->UseHWCursorARGB = RADEONUseHWCursorARGB; - cursor->LoadCursorARGB = RADEONLoadCursorARGB; -#endif size_bytes = CURSOR_WIDTH * 4 * CURSOR_HEIGHT; width = pScrn->displayWidth; width_bytes = width * (pScrn->bitsPerPixel / 8); @@ -440,5 +274,17 @@ Bool RADEONCursorInit(ScreenPtr pScreen) } #endif - return xf86InitCursor(pScreen, cursor); + return xf86_cursors_init (pScreen, CURSOR_WIDTH, CURSOR_HEIGHT, + (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* this is a lie -- + * HARDWARE_CURSOR_BIT_ORDER_MSBFIRST + * actually inverts the bit order, so + * this switches to LSBFIRST + */ + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | +#endif + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | + HARDWARE_CURSOR_ARGB)); } diff --git a/src/radeon_display.c b/src/radeon_display.c index d661c17b..fa80e104 100644 --- a/src/radeon_display.c +++ b/src/radeon_display.c @@ -36,8 +36,8 @@ /* X and server generic header files */ #include "xf86.h" #include "xf86_OSproc.h" -#include "fbdevhw.h" #include "vgaHW.h" +#include "xf86Modes.h" /* Driver data structures */ #include "radeon.h" @@ -45,97 +45,9 @@ #include "radeon_macros.h" #include "radeon_probe.h" #include "radeon_version.h" -#include "radeon_mergedfb.h" extern int getRADEONEntityIndex(void); -const char *MonTypeName[7] = { - "AUTO", - "NONE", - "CRT", - "LVDS", - "TMDS", - "CTV", - "STV" -}; - -const RADEONMonitorType MonTypeID[7] = { - MT_UNKNOWN, /* this is just a dummy value for AUTO DETECTION */ - MT_NONE, /* NONE -> NONE */ - MT_CRT, /* CRT -> CRT */ - MT_LCD, /* Laptop LCDs are driven via LVDS port */ - MT_DFP, /* DFPs are driven via TMDS */ - MT_CTV, /* CTV -> CTV */ - MT_STV, /* STV -> STV */ -}; - -const char *TMDSTypeName[3] = { - "NONE", - "Internal", - "External" -}; - -const char *DDCTypeName[5] = { - "NONE", - "MONID", - "DVI_DDC", - "VGA_DDC", - "CRT2_DDC" -}; - -const char *DACTypeName[3] = { - "Unknown", - "Primary", - "TVDAC/ExtDAC", -}; - -const char *ConnectorTypeName[8] = { - "None", - "Proprietary", - "VGA", - "DVI-I", - "DVI-D", - "CTV", - "STV", - "Unsupported" -}; - -const char *ConnectorTypeNameATOM[10] = { - "None", - "VGA", - "DVI-I", - "DVI-D", - "DVI-A", - "STV", - "CTV", - "LVDS", - "Digital", - "Unsupported" -}; - - -static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = -{ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ - {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ - {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ - {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ - {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /*CHIP_FAMILY_RV280*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */ -}; - static const CARD32 default_tvdac_adj [CHIP_FAMILY_LAST] = { 0x00000000, /* unknown */ @@ -158,53 +70,6 @@ static const CARD32 default_tvdac_adj [CHIP_FAMILY_LAST] = 0x00780000, /* rs400 */ /* FIXME: just values from rv380 used... */ }; -static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long val; - unsigned char *RADEONMMIO = info->MMIO; - - /* Get the result */ - val = INREG(info->DDCReg); - - *Clock = (val & RADEON_GPIO_Y_1) != 0; - *data = (val & RADEON_GPIO_Y_0) != 0; -} - -static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long val; - unsigned char *RADEONMMIO = info->MMIO; - - val = INREG(info->DDCReg) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1); - val |= (Clock ? 0:RADEON_GPIO_EN_1); - val |= (data ? 0:RADEON_GPIO_EN_0); - OUTREG(info->DDCReg, val); - - /* read back to improve reliability on some cards. */ - val = INREG(info->DDCReg); -} - -Bool RADEONI2cInit(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - info->pI2CBus = xf86CreateI2CBusRec(); - if (!info->pI2CBus) return FALSE; - - info->pI2CBus->BusName = "DDC"; - info->pI2CBus->scrnIndex = pScrn->scrnIndex; - info->pI2CBus->I2CPutBits = RADEONI2CPutBits; - info->pI2CBus->I2CGetBits = RADEONI2CGetBits; - info->pI2CBus->AcknTimeout = 5; - - if (!xf86I2CBusInit(info->pI2CBus)) return FALSE; - return TRUE; -} - void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) { MonPtr mon = pScrn->monitor; @@ -293,1137 +158,21 @@ void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) } } -static RADEONMonitorType -RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int bConnected = 0; - - /* the monitor either wasn't connected or it is a non-DDC CRT. - * try to probe it - */ - if(IsCrtDac) { - unsigned long ulOrigVCLK_ECP_CNTL; - unsigned long ulOrigDAC_CNTL; - unsigned long ulOrigDAC_MACRO_CNTL; - unsigned long ulOrigDAC_EXT_CNTL; - unsigned long ulOrigCRTC_EXT_CNTL; - unsigned long ulData; - unsigned long ulMask; - - ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - - ulData = ulOrigVCLK_ECP_CNTL; - ulData &= ~(RADEON_PIXCLK_ALWAYS_ONb - | RADEON_PIXCLK_DAC_ALWAYS_ONb); - ulMask = ~(RADEON_PIXCLK_ALWAYS_ONb - |RADEON_PIXCLK_DAC_ALWAYS_ONb); - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); - - ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL); - ulData = ulOrigCRTC_EXT_CNTL; - ulData |= RADEON_CRTC_CRT_ON; - OUTREG(RADEON_CRTC_EXT_CNTL, ulData); - - ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); - ulData = ulOrigDAC_EXT_CNTL; - ulData &= ~RADEON_DAC_FORCE_DATA_MASK; - ulData |= (RADEON_DAC_FORCE_BLANK_OFF_EN - |RADEON_DAC_FORCE_DATA_EN - |RADEON_DAC_FORCE_DATA_SEL_MASK); - if ((info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280)) - ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); - else - ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); - - OUTREG(RADEON_DAC_EXT_CNTL, ulData); - - /* turn on power so testing can go through */ - ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); - ulOrigDAC_CNTL &= ~RADEON_DAC_PDWN; - OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL); - - ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); - ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); - - /* Enable comparators and set DAC range to PS2 (VGA) output level */ - ulData = ulOrigDAC_CNTL; - ulData |= RADEON_DAC_CMP_EN; - ulData &= ~RADEON_DAC_RANGE_CNTL_MASK; - ulData |= 0x2; - OUTREG(RADEON_DAC_CNTL, ulData); - - /* Settle down */ - usleep(10000); - - /* Read comparators */ - ulData = INREG(RADEON_DAC_CNTL); - bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; - - /* Restore things */ - ulData = ulOrigVCLK_ECP_CNTL; - ulMask = 0xFFFFFFFFL; - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); - - OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); - OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); - OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); - - if (!bConnected) { - /* Power DAC down if CRT is not connected */ - ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); - ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); - - ulData = INREG(RADEON_DAC_CNTL); - ulData |= RADEON_DAC_PDWN; - OUTREG(RADEON_DAC_CNTL, ulData); - } - } else { /* TV DAC */ - - /* This doesn't seem to work reliably (maybe worse on some OEM cards), - for now we always return false. If one wants to connected a - non-DDC monitor on the DVI port when CRT port is also connected, - he will need to explicitly tell the driver in the config file - with Option MonitorLayout. - */ - bConnected = FALSE; - -#if 0 - if (info->ChipFamily == CHIP_FAMILY_R200) { - unsigned long ulOrigGPIO_MONID; - unsigned long ulOrigFP2_GEN_CNTL; - unsigned long ulOrigDISP_OUTPUT_CNTL; - unsigned long ulOrigCRTC2_GEN_CNTL; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_A; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_B; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_C; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_D; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_E; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_F; - unsigned long ulOrigCRTC2_H_TOTAL_DISP; - unsigned long ulOrigCRTC2_V_TOTAL_DISP; - unsigned long ulOrigCRTC2_H_SYNC_STRT_WID; - unsigned long ulOrigCRTC2_V_SYNC_STRT_WID; - unsigned long ulData, i; - - ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID); - ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL); - ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); - ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); - ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); - ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); - ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); - ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); - ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); - ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); - - ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP); - ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP); - ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); - ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); - - ulData = INREG(RADEON_GPIO_MONID); - ulData &= ~RADEON_GPIO_A_0; - OUTREG(RADEON_GPIO_MONID, ulData); - - OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c); - - OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012); - - OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); - - for (i = 0; i < 200; i++) { - ulData = INREG(RADEON_GPIO_MONID); - bConnected = (ulData & RADEON_GPIO_Y_0)?1:0; - if (!bConnected) break; - - usleep(1000); - } - - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F); - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID); - OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL); - OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); - OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); - OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); - } else { - unsigned long ulOrigPIXCLKSDATA; - unsigned long ulOrigTV_MASTER_CNTL; - unsigned long ulOrigTV_DAC_CNTL; - unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; - unsigned long ulOrigDAC_CNTL2; - unsigned long ulData; - unsigned long ulMask; - - ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - - ulData = ulOrigPIXCLKSDATA; - ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb - | RADEON_PIX2CLK_DAC_ALWAYS_ONb); - ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb - | RADEON_PIX2CLK_DAC_ALWAYS_ONb); - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); - - ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); - ulData = ulOrigTV_MASTER_CNTL; - ulData &= ~RADEON_TVCLK_ALWAYS_ONb; - OUTREG(RADEON_TV_MASTER_CNTL, ulData); - - ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); - ulData = ulOrigDAC_CNTL2; - ulData &= ~RADEON_DAC2_DAC2_CLK_SEL; - OUTREG(RADEON_DAC_CNTL2, ulData); - - ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); - - ulData = 0x00880213; - OUTREG(RADEON_TV_DAC_CNTL, ulData); - - ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); - - ulData = (RADEON_Y_RED_EN - | RADEON_C_GRN_EN - | RADEON_CMP_BLU_EN - | RADEON_RED_MX_FORCE_DAC_DATA - | RADEON_GRN_MX_FORCE_DAC_DATA - | RADEON_BLU_MX_FORCE_DAC_DATA); - if (IS_R300_VARIANT) - ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT; - else - ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT; - OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData); - - usleep(10000); - - ulData = INREG(RADEON_TV_DAC_CNTL); - bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; - - ulData = ulOrigPIXCLKSDATA; - ulMask = 0xFFFFFFFFL; - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); - - OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); - OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); - OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); - OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); - } -#endif - } - - return(bConnected ? MT_CRT : MT_NONE); -} - - -static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, RADEONConnector* port) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - unsigned long DDCReg; - RADEONMonitorType MonType = MT_NONE; - xf86MonPtr* MonInfo = &port->MonInfo; - int i, j; - - DDCReg = info->DDCReg; - switch(DDCType) - { - case DDC_MONID: - info->DDCReg = RADEON_GPIO_MONID; - break; - case DDC_DVI: - info->DDCReg = RADEON_GPIO_DVI_DDC; - break; - case DDC_VGA: - info->DDCReg = RADEON_GPIO_VGA_DDC; - break; - case DDC_CRT2: - info->DDCReg = RADEON_GPIO_CRT2_DDC; - break; - default: - info->DDCReg = DDCReg; - return MT_NONE; - } - - /* Read and output monitor info using DDC2 over I2C bus */ - if (info->pI2CBus && info->ddc2) { - OUTREG(info->DDCReg, INREG(info->DDCReg) & - (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); - - /* For some old monitors (like Compaq Presario FP500), we need - * following process to initialize/stop DDC - */ - OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (j = 0; j < 3; j++) { - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(13000); - - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (i = 0; i < 10; i++) { - usleep(15000); - if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) - break; - } - if (i == 10) continue; - - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(15000); - *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (i = 0; i < 5; i++) { - usleep(15000); - if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) - break; - } - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - if(*MonInfo) break; - } - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); - MonType = MT_NONE; - } - - OUTREG(info->DDCReg, INREG(info->DDCReg) & - ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1)); - - if (*MonInfo) { - if ((*MonInfo)->rawData[0x14] & 0x80) { - /* Note some laptops have a DVI output that uses internal TMDS, - * when its DVI is enabled by hotkey, LVDS panel is not used. - * In this case, the laptop is configured as DVI+VGA as a normal - * desktop card. - * Also for laptop, when X starts with lid closed (no DVI connection) - * both LDVS and TMDS are disable, we still need to treat it as a LVDS panel. - */ - if (port->TMDSType == TMDS_EXT) MonType = MT_DFP; - else { - if ((INREG(RADEON_FP_GEN_CNTL) & RADEON_FP_EN_TMDS) || !info->IsMobility) - MonType = MT_DFP; - else - MonType = MT_LCD; - } - } else MonType = MT_CRT; - } else MonType = MT_NONE; - - info->DDCReg = DDCReg; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "DDC Type: %d, Detected Type: %d\n", DDCType, MonType); - - return MonType; -} - -static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - CARD32 fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); - CARD32 fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); - - info->PanelPwrDly = 200; - if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) { - info->PanelYRes = (fp_vert_stretch>>12) + 1; - } else { - info->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; - } - if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { - info->PanelXRes = ((fp_horz_stretch>>16) + 1) * 8; - } else { - info->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; - } - - if ((info->PanelXRes < 640) || (info->PanelYRes < 480)) { - info->PanelXRes = 640; - info->PanelYRes = 480; - } - - if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { - CARD32 ppll_div_sel, ppll_val; - - ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; - RADEONPllErrataAfterIndex(info); - ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); - if ((ppll_val & 0x000707ff) == 0x1bb) - goto noprobe; - info->FeedbackDivider = ppll_val & 0x7ff; - info->PostDivider = (ppll_val >> 16) & 0x7; - info->RefDivider = info->pll.reference_div; - info->UseBiosDividers = TRUE; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Existing panel PLL dividers will be used.\n"); - } - noprobe: - - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Panel size %dx%d is derived, this may not be correct.\n" - "If not, use PanelSize option to overwrite this setting\n", - info->PanelXRes, info->PanelYRes); -} - - -/* BIOS may not have right panel size, we search through all supported - * DDC modes looking for the maximum panel size. - */ -static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) -{ - int j; - RADEONInfoPtr info = RADEONPTR (pScrn); - xf86MonPtr ddc = pScrn->monitor->DDC; - DisplayModePtr p; - - if ((info->UseBiosDividers && info->DotClock != 0) || (ddc == NULL)) - return; - - /* Go thru detailed timing table first */ - for (j = 0; j < 4; j++) { - if (ddc->det_mon[j].type == 0) { - struct detailed_timings *d_timings = - &ddc->det_mon[j].section.d_timings; - int match = 0; - - /* If we didn't get a panel clock or guessed one, try to match the - * mode with the panel size. We do that because we _need_ a panel - * clock, or ValidateFPModes will fail, even when UseBiosDividers - * is set. - */ - if (info->DotClock == 0 && - info->PanelXRes == d_timings->h_active && - info->PanelYRes == d_timings->v_active) - match = 1; - - /* If we don't have a BIOS provided panel data with fixed dividers, - * check for a larger panel size - */ - if (info->PanelXRes < d_timings->h_active && - info->PanelYRes < d_timings->v_active && - !info->UseBiosDividers) - match = 1; - - if (match) { - info->PanelXRes = d_timings->h_active; - info->PanelYRes = d_timings->v_active; - info->DotClock = d_timings->clock / 1000; - info->HOverPlus = d_timings->h_sync_off; - info->HSyncWidth = d_timings->h_sync_width; - info->HBlank = d_timings->h_blanking; - info->VOverPlus = d_timings->v_sync_off; - info->VSyncWidth = d_timings->v_sync_width; - info->VBlank = d_timings->v_blanking; - info->Flags = (d_timings->interlaced ? V_INTERLACE : 0); - if (d_timings->sync == 3) { - switch (d_timings->misc) { - case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break; - case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break; - case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break; - case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break; - } - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC detailed: %dx%d\n", - info->PanelXRes, info->PanelYRes); - } - } - } - - if (info->UseBiosDividers && info->DotClock != 0) - return; - - /* Search thru standard VESA modes from EDID */ - for (j = 0; j < 8; j++) { - if ((info->PanelXRes < ddc->timings2[j].hsize) && - (info->PanelYRes < ddc->timings2[j].vsize)) { - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - if ((ddc->timings2[j].hsize == p->HDisplay) && - (ddc->timings2[j].vsize == p->VDisplay)) { - float refresh = - (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; - - if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) { - /* Is this good enough? */ - info->PanelXRes = ddc->timings2[j].hsize; - info->PanelYRes = ddc->timings2[j].vsize; - info->HBlank = p->HTotal - p->HDisplay; - info->HOverPlus = p->HSyncStart - p->HDisplay; - info->HSyncWidth = p->HSyncEnd - p->HSyncStart; - info->VBlank = p->VTotal - p->VDisplay; - info->VOverPlus = p->VSyncStart - p->VDisplay; - info->VSyncWidth = p->VSyncEnd - p->VSyncStart; - info->DotClock = p->Clock; - info->Flags = p->Flags; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC VESA/EDID: %dx%d\n", - info->PanelXRes, info->PanelYRes); - } - } - } - } - } -} - -static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (!RADEONGetLVDSInfoFromBIOS(pScrn)) - RADEONGetPanelInfoFromReg(pScrn); - - /* The panel size we collected from BIOS may not be the - * maximum size supported by the panel. If not, we update - * it now. These will be used if no matching mode can be - * found from EDID data. - */ - RADEONUpdatePanelSize(pScrn); - - if (info->DotClock == 0) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - DisplayModePtr tmp_mode = NULL; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "No valid timing info from BIOS.\n"); - /* No timing information for the native mode, - use whatever specified in the Modeline. - If no Modeline specified, we'll just pick - the VESA mode at 60Hz refresh rate which - is likely to be the best for a flat panel. - */ - tmp_mode = pScrn->monitor->Modes; - while(tmp_mode) { - if ((tmp_mode->HDisplay == info->PanelXRes) && - (tmp_mode->VDisplay == info->PanelYRes)) { - - float refresh = - (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; - if ((abs(60.0 - refresh) < 1.0) || - (tmp_mode->type == 0)) { - info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; - info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; - info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; - info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; - info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; - info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; - info->DotClock = tmp_mode->Clock; - info->Flags = 0; - break; - } - tmp_mode = tmp_mode->next; - } - } - if ((info->DotClock == 0) && !pRADEONEnt->PortInfo[0]->MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Panel size is not correctly detected.\n" - "Please try to use PanelSize option for correct settings.\n"); - return FALSE; - } - } - - return TRUE; -} - -static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - int i; - - for (i=0; i<4; i++) { - info->tmds_pll[i].value = 0; - info->tmds_pll[i].freq = 0; - } - - if (RADEONGetTMDSInfoFromBIOS(pScrn)) return; - - for (i=0; i<4; i++) { - info->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; - info->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; - } -} - -void RADEONGetPanelInfo (ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - char* s; - - if((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { - info->PanelPwrDly = 200; - if (sscanf (s, "%dx%d", &info->PanelXRes, &info->PanelYRes) != 2) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s); - RADEONGetPanelInfoFromReg(pScrn); - } - } else { - - if(info->DisplayType == MT_LCD) { - RADEONGetLVDSInfo(pScrn); - if (info->MergeType == MT_DFP) { - RADEONGetTMDSInfo(pScrn); - } - } else if ((info->DisplayType == MT_DFP) || (info->MergeType == MT_DFP)) { - RADEONGetTMDSInfo(pScrn); - if (!pScrn->monitor->DDC) - RADEONGetHardCodedEDIDFromBIOS(pScrn); - else if (!info->IsSecondary) - RADEONUpdatePanelSize(pScrn); - } - } -} - -void RADEONGetTVDacAdjInfo(ScrnInfoPtr pScrn) +void RADEONGetTVDacAdjInfo(xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; /* Todo: get this setting from BIOS */ - info->tv_dac_adj = default_tvdac_adj[info->ChipFamily]; + radeon_output->tv_dac_adj = default_tvdac_adj[info->ChipFamily]; if (info->IsMobility) { /* some mobility chips may different */ if (info->ChipFamily == CHIP_FAMILY_RV250) - info->tv_dac_adj = 0x00880000; + radeon_output->tv_dac_adj = 0x00880000; } } /* - * initialise the static data sos we don't have to re-do at randr change */ -void RADEONSetupConnectors(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - const char *s; - Bool ignore_edid = FALSE; - int i = 0, second = 0, max_mt = 5; - - /* We first get the information about all connectors from BIOS. - * This is how the card is phyiscally wired up. - * The information should be correct even on a OEM card. - * If not, we may have problem -- need to use MonitorLayout option. - */ - for (i = 0; i < 2; i++) { - pRADEONEnt->PortInfo[i]->MonType = MT_UNKNOWN; - pRADEONEnt->PortInfo[i]->MonInfo = NULL; - pRADEONEnt->PortInfo[i]->DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[i]->DACType = DAC_UNKNOWN; - pRADEONEnt->PortInfo[i]->TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[i]->ConnectorType = CONNECTOR_NONE; - } - pRADEONEnt->Controller[0]->IsUsed = FALSE; - pRADEONEnt->Controller[1]->IsUsed = FALSE; - pRADEONEnt->Controller[0]->IsActive = FALSE; - pRADEONEnt->Controller[1]->IsActive = FALSE; - - if (!RADEONGetConnectorInfoFromBIOS(pScrn) || - ((pRADEONEnt->PortInfo[0]->DDCType == 0) && - (pRADEONEnt->PortInfo[1]->DDCType == 0))) { - /* Below is the most common setting, but may not be true */ - pRADEONEnt->PortInfo[0]->MonType = MT_UNKNOWN; - pRADEONEnt->PortInfo[0]->MonInfo = NULL; - pRADEONEnt->PortInfo[0]->DDCType = DDC_DVI; - pRADEONEnt->PortInfo[0]->DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[0]->TMDSType = TMDS_INT; - pRADEONEnt->PortInfo[0]->ConnectorType = CONNECTOR_DVI_I; - - pRADEONEnt->PortInfo[1]->MonType = MT_UNKNOWN; - pRADEONEnt->PortInfo[1]->MonInfo = NULL; - pRADEONEnt->PortInfo[1]->DDCType = DDC_VGA; - pRADEONEnt->PortInfo[1]->DACType = DAC_PRIMARY; - pRADEONEnt->PortInfo[1]->TMDSType = TMDS_EXT; - pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_CRT; - - - /* Some cards have the DDC lines swapped and we have no way to - * detect it yet (Mac cards) - */ - if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) { - pRADEONEnt->PortInfo[0]->DDCType = DDC_VGA; - pRADEONEnt->PortInfo[1]->DDCType = DDC_DVI; - } - } - - /* always make TMDS_INT port first*/ - if (pRADEONEnt->PortInfo[1]->TMDSType == TMDS_INT) { - RADEONConnector *connector; - connector = pRADEONEnt->PortInfo[0]; - pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; - pRADEONEnt->PortInfo[1] = connector; - } else if ((pRADEONEnt->PortInfo[0]->TMDSType != TMDS_INT && - pRADEONEnt->PortInfo[1]->TMDSType != TMDS_INT)) { - /* no TMDS_INT port, make primary DAC port first */ - /* On my Inspiron 8600 both internal and external ports are - marked DAC_PRIMARY in BIOS. So be extra careful - only - swap when the first port is not DAC_PRIMARY */ - if ((!(pRADEONEnt->PortInfo[0]->ConnectorType == CONNECTOR_PROPRIETARY)) && (pRADEONEnt->PortInfo[1]->DACType == DAC_PRIMARY) && - (pRADEONEnt->PortInfo[0]->DACType != DAC_PRIMARY)) { - RADEONConnector *connector; - connector = pRADEONEnt->PortInfo[0]; - pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1]; - pRADEONEnt->PortInfo[1] = connector; - } - } - - if (info->HasSingleDAC) { - /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/ - if (pRADEONEnt->PortInfo[0]->ConnectorType == CONNECTOR_CRT) { - pRADEONEnt->PortInfo[0]->DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[1]->DACType = DAC_PRIMARY; - } else { - pRADEONEnt->PortInfo[1]->DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[0]->DACType = DAC_PRIMARY; - } - } else if (!pRADEONEnt->HasCRTC2) { - pRADEONEnt->PortInfo[0]->DACType = DAC_PRIMARY; - } - - /* IgnoreEDID option is different from the NoDDCxx options used by DDC module - * When IgnoreEDID is used, monitor detection will still use DDC - * detection, but all EDID data will not be used in mode validation. - * You can use this option when you have a DDC monitor but want specify your own - * monitor timing parameters by using HSync, VRefresh and Modeline, - */ - if (xf86GetOptValBool(info->Options, OPTION_IGNORE_EDID, &ignore_edid)) { - if (ignore_edid) - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "IgnoreEDID is specified, EDID data will be ignored\n"); - } - - /* - * MonitorLayout option takes a string for two monitors connected in following format: - * Option "MonitorLayout" "primary-port-display, secondary-port-display" - * primary and secondary port displays can have one of following: - * NONE, CRT, LVDS, TMDS - * With this option, driver will bring up monitors as specified, - * not using auto-detection routines to probe monitors. - * - * This option can be used when the false monitor detection occurs. - * - * This option can also be used to disable one connected display. - * For example, if you have a laptop connected to an external CRT - * and you want to disable the internal LCD panel, you can specify - * Option "MonitorLayout" "NONE, CRT" - * - * This option can also used to disable Clone mode. One there is only - * one monitor is specified, clone mode will be turned off automatically - * even you have two monitors connected. - * - * Another usage of this option is you want to config the server - * to start up with a certain monitor arrangement even one monitor - * is not plugged in when server starts. - * For example, you can config your laptop with - * Option "MonitorLayout" "LVDS, CRT" - * Option "CloneHSync" "40-150" - * Option "CloneVRefresh" "60-120" - * With these options, you can connect in your CRT monitor later - * after the X server has started. - */ - if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { - char s1[5], s2[5]; - i = 0; - /* When using user specified monitor types, we will not do DDC detection - * - */ - do { - switch(*s) { - case ',': - s1[i] = '\0'; - i = 0; - second = 1; - break; - case ' ': - case '\t': - case '\n': - case '\r': - break; - default: - if (second) - s2[i] = *s; - else - s1[i] = *s; - i++; - break; - } - if (i > 4) i = 4; - } while(*s++); - s2[i] = '\0'; - - for (i = 0; i < max_mt; i++) - { - if (strcmp(s1, MonTypeName[i]) == 0) - { - pRADEONEnt->PortInfo[0]->MonType = MonTypeID[i]; - break; - } - } - if (i == max_mt) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Invalid Monitor type specified for 1st port \n"); - - for (i = 0; i < max_mt; i++) - { - if (strcmp(s2, MonTypeName[i]) == 0) - { - pRADEONEnt->PortInfo[1]->MonType = MonTypeID[i]; - break; - } - - } - if (i == max_mt) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Invalid Monitor type specified for 2nd port \n"); - - if (i == max_mt) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Invalid Monitor type specified for 2nd port \n"); - - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "MonitorLayout Option: \n\tMonitor1--Type %s, Monitor2--Type %s\n\n", s1, s2); -#if 0 - if (pRADEONEnt->PortInfo[1]->MonType == MT_CRT) { - pRADEONEnt->PortInfo[1]->DACType = DAC_PRIMARY; - pRADEONEnt->PortInfo[1]->TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[1]->DDCType = DDC_VGA; - pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_CRT; - pRADEONEnt->PortInfo[0]->DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[0]->TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[0]->DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[0]->ConnectorType = pRADEONEnt->PortInfo[0]->MonType+1; - pRADEONEnt->PortInfo[0]->MonInfo = NULL; - } -#endif - - /* some thinkpads and powerbooks use lvds and internal tmds - * at the same time. --AGD - */ - if ((pRADEONEnt->PortInfo[0]->MonType == MT_LCD) && - (pRADEONEnt->PortInfo[1]->MonType == MT_DFP)) { - pRADEONEnt->PortInfo[1]->DDCType = DDC_DVI; - pRADEONEnt->PortInfo[0]->DDCType = DDC_MONID; - pRADEONEnt->PortInfo[1]->TMDSType = TMDS_INT; - pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_DVI_I; - pRADEONEnt->PortInfo[0]->TMDSType = TMDS_UNKNOWN; - } - - } -} - -static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, int connector) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - if (info->IsMobility) { - switch(connector) { - case 0: - /* non-DDC laptop panel connected on primary */ - if (INREG(RADEON_BIOS_4_SCRATCH) & 4) - return MT_LCD; - break; - case 1: - /* non-DDC TMDS panel connected through DVO */ - if (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_ON) - return MT_DFP; - break; - default: - break; - } - } - return MT_NONE; -} - -/* Primary Head (DVI or Laptop Int. panel)*/ -/* A ddc capable display connected on DVI port */ -/* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ -void RADEONConnectorFindMonitor(ScrnInfoPtr pScrn, int connector) -{ - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONConnector *pPort = pRADEONEnt->PortInfo[connector]; - - if (pPort->MonType == MT_UNKNOWN) { - if ((pPort->MonType = RADEONDisplayDDCConnected(pScrn, - pPort->DDCType, - pPort))); - else if((pPort->MonType = RADEONPortCheckNonDDC(pScrn, connector))); - else - pPort->MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pPort->DACType)); - } -} - -static void RADEONQueryConnectedDisplays(ScrnInfoPtr pScrn) -{ - - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - const char *s; - Bool ignore_edid = FALSE; - - /* IgnoreEDID option is different from the NoDDCxx options used by DDC module - * When IgnoreEDID is used, monitor detection will still use DDC - * detection, but all EDID data will not be used in mode validation. - * You can use this option when you have a DDC monitor but want specify your own - * monitor timing parameters by using HSync, VRefresh and Modeline, - */ - if (xf86GetOptValBool(info->Options, OPTION_IGNORE_EDID, &ignore_edid)) { - if (ignore_edid) - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "IgnoreEDID is specified, EDID data will be ignored\n"); - } - - if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { - if (!ignore_edid) { - if ((pRADEONEnt->PortInfo[0]->MonType > MT_NONE) && - (pRADEONEnt->PortInfo[0]->MonType < MT_STV)) - RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0]->DDCType, - pRADEONEnt->PortInfo[0]); - if ((pRADEONEnt->PortInfo[1]->MonType > MT_NONE) && - (pRADEONEnt->PortInfo[1]->MonType < MT_STV)) - RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1]->DDCType, - pRADEONEnt->PortInfo[1]); - } - } - else { - /* force monitor redetection */ - pRADEONEnt->PortInfo[0]->MonType = MT_UNKNOWN; - pRADEONEnt->PortInfo[1]->MonType = MT_UNKNOWN; - } - - - if (pRADEONEnt->PortInfo[0]->MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1]->MonType == MT_UNKNOWN) { - - if ((!pRADEONEnt->HasCRTC2) && (pRADEONEnt->PortInfo[0]->MonType == MT_UNKNOWN)) { - if((pRADEONEnt->PortInfo[0]->MonType = RADEONDisplayDDCConnected(pScrn, DDC_DVI, - pRADEONEnt->PortInfo[0]))); - else if((pRADEONEnt->PortInfo[0]->MonType = RADEONDisplayDDCConnected(pScrn, DDC_VGA, - pRADEONEnt->PortInfo[0]))); - else if((pRADEONEnt->PortInfo[0]->MonType = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, - pRADEONEnt->PortInfo[0]))); - else - pRADEONEnt->PortInfo[0]->MonType = MT_CRT; - - if (!ignore_edid) { - if (pRADEONEnt->PortInfo[0]->MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); - xf86PrintEDID(pRADEONEnt->PortInfo[0]->MonInfo ); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); - } - } - - pRADEONEnt->PortInfo[1]->MonType = MT_NONE; - pRADEONEnt->PortInfo[1]->MonInfo = NULL; - pRADEONEnt->PortInfo[1]->DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[1]->DACType = DAC_UNKNOWN; - pRADEONEnt->PortInfo[1]->TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_NONE; - - pRADEONEnt->PortInfo[0]->crtc_num = 1; - pRADEONEnt->PortInfo[1]->crtc_num = 2; - - return; - } - - RADEONConnectorFindMonitor(pScrn, 0); - RADEONConnectorFindMonitor(pScrn, 1); - - } - - if(ignore_edid) { - pRADEONEnt->PortInfo[0]->MonInfo = NULL; - pRADEONEnt->PortInfo[1]->MonInfo = NULL; - } else { - if (pRADEONEnt->PortInfo[0]->MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on 1st port ----------------------\n"); - xf86PrintEDID( pRADEONEnt->PortInfo[0]->MonInfo ); - } - - if (pRADEONEnt->PortInfo[1]->MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on 2nd port -----------------------\n"); - xf86PrintEDID( pRADEONEnt->PortInfo[1]->MonInfo ); - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); - - return; -} - -Bool RADEONMapControllers(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - Bool head_reversed = FALSE; - RADEONConnector *connector; - - info->MergeType = MT_NONE; - - if (!info->IsSecondary) { - RADEONQueryConnectedDisplays(pScrn); - - pRADEONEnt->PortInfo[0]->crtc_num = 1; - pRADEONEnt->PortInfo[1]->crtc_num = 2; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Port1:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", - MonTypeName[pRADEONEnt->PortInfo[0]->MonType+1], - info->IsAtomBios ? - ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0]->ConnectorType]: - ConnectorTypeName[pRADEONEnt->PortInfo[0]->ConnectorType], - DACTypeName[pRADEONEnt->PortInfo[0]->DACType+1], - TMDSTypeName[pRADEONEnt->PortInfo[0]->TMDSType+1], - DDCTypeName[pRADEONEnt->PortInfo[0]->DDCType]); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Port2:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", - MonTypeName[pRADEONEnt->PortInfo[1]->MonType+1], - info->IsAtomBios ? - ConnectorTypeNameATOM[pRADEONEnt->PortInfo[1]->ConnectorType]: - ConnectorTypeName[pRADEONEnt->PortInfo[1]->ConnectorType], - DACTypeName[pRADEONEnt->PortInfo[1]->DACType+1], - TMDSTypeName[pRADEONEnt->PortInfo[1]->TMDSType+1], - DDCTypeName[pRADEONEnt->PortInfo[1]->DDCType]); - - /* no display detected on primary port*/ - if (pRADEONEnt->PortInfo[0]->MonType == MT_NONE) { - if (pRADEONEnt->PortInfo[1]->MonType != MT_NONE) { - /* Only one detected on secondary, let it to be primary */ - pRADEONEnt->PortInfo[0]->crtc_num = 2; - pRADEONEnt->PortInfo[1]->crtc_num = 1; - head_reversed = TRUE; - } else { - /* None detected, Default to a CRT connected */ - pRADEONEnt->PortInfo[0]->MonType = MT_CRT; - } - } - - if ((pRADEONEnt->PortInfo[0]->MonType == MT_LCD) && - (pRADEONEnt->PortInfo[1]->MonType == MT_CRT)) { - if (!(INREG(RADEON_LVDS_GEN_CNTL) & RADEON_LVDS_ON)) { - /* LCD is switched off, don't turn it on, otherwise it may casue lockup due to SS issue. */ - pRADEONEnt->PortInfo[0]->crtc_num = 2; - pRADEONEnt->PortInfo[1]->crtc_num = 1; - pRADEONEnt->PortInfo[0]->MonType = MT_NONE; - head_reversed = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "LCD is switched off, only CRT will be used\n"); - } - } - - if ((pRADEONEnt->PortInfo[0]->MonType != MT_NONE) && - (pRADEONEnt->PortInfo[1]->MonType != MT_NONE)) { - if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DISPLAY, FALSE)) { - if (info->IsMobility) { - /* Don't reverse display for mobility chips, as only CRTC1 path has RMX which - will be required by many LCD panels - */ - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Reverse Display cannot be used for mobility chip\n"); - } else { - pRADEONEnt->PortInfo[0]->crtc_num = 2; - pRADEONEnt->PortInfo[1]->crtc_num = 1; - head_reversed = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Primary and Secondary mapping is reversed\n"); - } - } - } - - if (pRADEONEnt->HasSecondary && pRADEONEnt->PortInfo[1]->MonType == MT_NONE) { - pRADEONEnt->HasSecondary = FALSE; - } - } - - if(pRADEONEnt->HasCRTC2) { - if(info->IsSecondary) { - connector = RADEONGetCrtcConnector(pScrn, 2); - pRADEONEnt->Controller[1]->binding = 2; - if (connector) { - info->DisplayType = connector->MonType; - pScrn->monitor->DDC = connector->MonInfo; - } - } else { - connector = RADEONGetCrtcConnector(pScrn, 1); - pRADEONEnt->Controller[0]->binding = 1; - if (connector) { - info->DisplayType = connector->MonType; - pScrn->monitor->DDC = connector->MonInfo; - } - } - - if(!pRADEONEnt->HasSecondary) { - connector = RADEONGetCrtcConnector(pScrn, 2); - if (connector) - info->MergeType = connector->MonType; - if (info->MergeType) - pRADEONEnt->Controller[1]->binding = 1; - } - } else { - connector = RADEONGetCrtcConnector(pScrn, 1); - if (connector) { - if (connector->MonType == MT_NONE) - connector->MonType = MT_CRT; - info->DisplayType = connector->MonType; - pScrn->monitor->DDC = connector->MonInfo; - } - connector = RADEONGetCrtcConnector(pScrn, 2); - if (connector) - connector->MonType = MT_NONE; - pRADEONEnt->Controller[1]->binding = 1; - } - - if (!info->IsSecondary) { - connector = RADEONGetCrtcConnector(pScrn, 2); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Primary Head: Port%d ---- \n", head_reversed?2:1); - if (connector->MonType != MT_NONE) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Secondary Head: Port%d ----\n", head_reversed?1:2); - else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Secondary Head: Not used ----\n"); - } - - info->HBlank = 0; - info->HOverPlus = 0; - info->HSyncWidth = 0; - info->VBlank = 0; - info->VOverPlus = 0; - info->VSyncWidth = 0; - info->DotClock = 0; - info->UseBiosDividers = FALSE; - - info->OverlayOnCRTC2 = FALSE; - - return TRUE; -} - -/* * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant). * */ @@ -1436,8 +185,7 @@ static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) CARD32 dac_cntl; CARD32 dac_macro_cntl = 0; dac_cntl = INREG(RADEON_DAC_CNTL); - if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) - dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); + dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); if (IsOn) { dac_cntl &= ~RADEON_DAC_PDWN; dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | @@ -1450,8 +198,7 @@ static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) RADEON_DAC_PDWN_B); } OUTREG(RADEON_DAC_CNTL, dac_cntl); - if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) - OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); + OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); } else { CARD32 tv_dac_cntl; CARD32 fp2_gen_cntl; @@ -1528,6 +275,13 @@ void RADEONDisableDisplays(ScrnInfoPtr pScrn) { } RADEONDacPowerSet(pScrn, FALSE, FALSE); + /* turn off tv-out */ + if (info->InternalTVOut) { + tmp = INREG(RADEON_TV_MASTER_CNTL); + tmp &= ~RADEON_TV_ON; + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + } + /* FP 1 */ tmp = INREG(RADEON_FP_GEN_CNTL); tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); @@ -1539,39 +293,47 @@ void RADEONDisableDisplays(ScrnInfoPtr pScrn) { OUTREG(RADEON_FP2_GEN_CNTL, tmp); /* LVDS */ - tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - if (info->IsMobility || info->IsIGP) { - /* Asic bug, when turning off LVDS_ON, we have to make sure - RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off - */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); - } - tmp = INREG(RADEON_LVDS_GEN_CNTL); - tmp |= (RADEON_LVDS_ON | RADEON_LVDS_DISPLAY_DIS); - tmp &= ~(RADEON_LVDS_BLON); - OUTREG(RADEON_LVDS_GEN_CNTL, tmp); - if (info->IsMobility || info->IsIGP) { - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + if (info->IsMobility) { + tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + if (info->IsMobility || info->IsIGP) { + /* Asic bug, when turning off LVDS_ON, we have to make sure + RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off + */ + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); + } + tmp = INREG(RADEON_LVDS_GEN_CNTL); + tmp |= RADEON_LVDS_DISPLAY_DIS; + tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON); + OUTREG(RADEON_LVDS_GEN_CNTL, tmp); + if (info->IsMobility || info->IsIGP) { + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + } } } /* This is to be used enable/disable displays dynamically */ -void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable) +void RADEONEnableDisplay(xf86OutputPtr output, BOOL bEnable) { + ScrnInfoPtr pScrn = output->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); RADEONSavePtr save = &info->ModeReg; unsigned char * RADEONMMIO = info->MMIO; unsigned long tmp; + RADEONOutputPrivatePtr radeon_output; + int tv_dac_change = 0; + radeon_output = output->driver_private; if (bEnable) { - if (pPort->MonType == MT_CRT) { - if (pPort->DACType == DAC_PRIMARY) { + ErrorF("enable montype: %d\n", radeon_output->MonType); + if (radeon_output->MonType == MT_CRT) { + if (radeon_output->DACType == DAC_PRIMARY) { tmp = INREG(RADEON_CRTC_EXT_CNTL); tmp |= RADEON_CRTC_CRT_ON; OUTREG(RADEON_CRTC_EXT_CNTL, tmp); save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; - } else if (pPort->DACType == DAC_TVDAC) { + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + } else if (radeon_output->DACType == DAC_TVDAC) { if (info->ChipFamily == CHIP_FAMILY_R200) { tmp = INREG(RADEON_FP2_GEN_CNTL); tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); @@ -1579,41 +341,50 @@ void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); } else { tmp = INREG(RADEON_CRTC2_GEN_CNTL); - tmp |= RADEON_CRTC2_CRT2_ON; + tmp |= RADEON_CRTC2_CRT2_ON; OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; } + tv_dac_change = 1; } - RADEONDacPowerSet(pScrn, bEnable, (pPort->DACType == DAC_PRIMARY)); - } else if (pPort->MonType == MT_DFP) { - if (pPort->TMDSType == TMDS_INT) { + } else if (radeon_output->MonType == MT_DFP) { + if (radeon_output->TMDSType == TMDS_INT) { tmp = INREG(RADEON_FP_GEN_CNTL); tmp |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); OUTREG(RADEON_FP_GEN_CNTL, tmp); save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); - } else if (pPort->TMDSType == TMDS_EXT) { + } else if (radeon_output->TMDSType == TMDS_EXT) { tmp = INREG(RADEON_FP2_GEN_CNTL); tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); OUTREG(RADEON_FP2_GEN_CNTL, tmp); save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); } - } else if (pPort->MonType == MT_LCD) { + } else if (radeon_output->MonType == MT_LCD) { tmp = INREG(RADEON_LVDS_GEN_CNTL); tmp |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); tmp &= ~(RADEON_LVDS_DISPLAY_DIS); - usleep (info->PanelPwrDly * 1000); + usleep (radeon_output->PanelPwrDly * 1000); OUTREG(RADEON_LVDS_GEN_CNTL, tmp); save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); save->lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); - } + } else if (radeon_output->MonType == MT_STV || + radeon_output->MonType == MT_CTV) { + tmp = INREG(RADEON_TV_MASTER_CNTL); + tmp |= RADEON_TV_ON; + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + tv_dac_change = 2; + radeon_output->tv_on = TRUE; + } } else { - if (pPort->MonType == MT_CRT || pPort->MonType == NONE) { - if (pPort->DACType == DAC_PRIMARY) { + ErrorF("disable montype: %d\n", radeon_output->MonType); + if (radeon_output->MonType == MT_CRT) { + if (radeon_output->DACType == DAC_PRIMARY) { tmp = INREG(RADEON_CRTC_EXT_CNTL); - tmp &= ~RADEON_CRTC_CRT_ON; + tmp &= ~RADEON_CRTC_CRT_ON; OUTREG(RADEON_CRTC_EXT_CNTL, tmp); save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; - } else if (pPort->DACType == DAC_TVDAC) { + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + } else if (radeon_output->DACType == DAC_TVDAC) { if (info->ChipFamily == CHIP_FAMILY_R200) { tmp = INREG(RADEON_FP2_GEN_CNTL); tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); @@ -1625,26 +396,21 @@ void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); save->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; } + tv_dac_change = 1; } - RADEONDacPowerSet(pScrn, bEnable, (pPort->DACType == DAC_PRIMARY)); - } - - if (pPort->MonType == MT_DFP || pPort->MonType == NONE) { - if (pPort->TMDSType == TMDS_INT) { + } else if (radeon_output->MonType == MT_DFP) { + if (radeon_output->TMDSType == TMDS_INT) { tmp = INREG(RADEON_FP_GEN_CNTL); tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); OUTREG(RADEON_FP_GEN_CNTL, tmp); save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - } else if (pPort->TMDSType == TMDS_EXT) { + } else if (radeon_output->TMDSType == TMDS_EXT) { tmp = INREG(RADEON_FP2_GEN_CNTL); tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); OUTREG(RADEON_FP2_GEN_CNTL, tmp); save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); } - } - - if (pPort->MonType == MT_LCD || - (pPort->MonType == NONE && pPort->ConnectorType == CONNECTOR_PROPRIETARY)) { + } else if (radeon_output->MonType == MT_LCD) { unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); if (info->IsMobility || info->IsIGP) { /* Asic bug, when turning off LVDS_ON, we have to make sure @@ -1653,21 +419,39 @@ void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); } tmp = INREG(RADEON_LVDS_GEN_CNTL); - tmp |= (RADEON_LVDS_ON | RADEON_LVDS_DISPLAY_DIS); - tmp &= ~(RADEON_LVDS_BLON); + tmp |= RADEON_LVDS_DISPLAY_DIS; + tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON); OUTREG(RADEON_LVDS_GEN_CNTL, tmp); - save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_DISPLAY_DIS); - save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON); + save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; + save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON); if (info->IsMobility || info->IsIGP) { OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); } - } + } else if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) { + tmp = INREG(RADEON_TV_MASTER_CNTL); + tmp &= ~RADEON_TV_ON; + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + tv_dac_change = 2; + radeon_output->tv_on = FALSE; + } + } + + if (tv_dac_change) { + if (bEnable) + info->tv_dac_enable_mask |= tv_dac_change; + else + info->tv_dac_enable_mask &= ~tv_dac_change; + + if (bEnable && info->tv_dac_enable_mask) + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + else if (!bEnable && info->tv_dac_enable_mask == 0) + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + } } /* Calculate display buffer watermark to prevent buffer underflow */ -void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoPtr info2, - DisplayModePtr mode1, DisplayModePtr mode2) +void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2, DisplayModePtr mode1, DisplayModePtr mode2) { RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; @@ -1705,7 +489,7 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP */ if ((info->DispPriority == 2) && IS_R300_VARIANT) { CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); - if (pRADEONEnt->Controller[1]->IsActive) { + if (pRADEONEnt->pCrtc[1]->enabled) { mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ } else { mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ @@ -1717,11 +501,6 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP /* R420 and RV410 family not supported yet */ if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; - if (pRADEONEnt->pSecondaryScrn) { - if (info->IsSecondary) return; - info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); - } else if (pRADEONEnt->Controller[1]->binding == 1) info2 = info; - /* * Determine if there is enough bandwidth for current display mode */ @@ -1734,8 +513,8 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP pix_clk2 = 0; peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes); - if (info2) - peak_disp_bw += (pix_clk2 * info2->CurrentLayout.pixel_bytes); + if (pixel_bytes2) + peak_disp_bw += (pix_clk2 * pixel_bytes2); if (peak_disp_bw >= mem_bw * min_mem_eff) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, @@ -1875,8 +654,8 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP Find the drain rate of the display buffer. */ disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes); - if (info2) - disp_drain_rate2 = pix_clk2 / (16.0/info2->CurrentLayout.pixel_bytes); + if (pixel_bytes2) + disp_drain_rate2 = pix_clk2 / (16.0/pixel_bytes2); else disp_drain_rate2 = 0; @@ -1925,11 +704,13 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); - RADEONTRACE(("GRPH_BUFFER_CNTL from %x to %x\n", - (unsigned int)info->SavedReg.grph_buffer_cntl, INREG(RADEON_GRPH_BUFFER_CNTL))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "GRPH_BUFFER_CNTL from %x to %x\n", + (unsigned int)info->SavedReg.grph_buffer_cntl, + INREG(RADEON_GRPH_BUFFER_CNTL)); if (mode2) { - stop_req = mode2->HDisplay * info2->CurrentLayout.pixel_bytes / 16; + stop_req = mode2->HDisplay * pixel_bytes2 / 16; if (stop_req > max_stop_req) stop_req = max_stop_req; @@ -1973,427 +754,81 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); - RADEONTRACE(("GRPH2_BUFFER_CNTL from %x to %x\n", - (unsigned int)info->SavedReg.grph2_buffer_cntl, INREG(RADEON_GRPH2_BUFFER_CNTL))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "GRPH2_BUFFER_CNTL from %x to %x\n", + (unsigned int)info->SavedReg.grph2_buffer_cntl, + INREG(RADEON_GRPH2_BUFFER_CNTL)); } } void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); DisplayModePtr mode1, mode2; - RADEONInfoPtr info2 = NULL; - - if (pRADEONEnt->pSecondaryScrn) { - if (info->IsSecondary) return; - info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); - } else if (pRADEONEnt->Controller[1]->binding == 1) info2 = info; + int pixel_bytes2 = 0; mode1 = info->CurrentLayout.mode; - if (info->MergedFB) { - mode1 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT1; - mode2 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2; - } else if ((pRADEONEnt->HasSecondary) && info2) { - mode2 = info2->CurrentLayout.mode; - } else { - mode2 = NULL; - } + mode2 = NULL; + pixel_bytes2 = info->CurrentLayout.pixel_bytes; - RADEONInitDispBandwidth2(pScrn, info, info2, mode1, mode2); -} + if (xf86_config->num_crtc == 2) { + pixel_bytes2 = 0; + mode2 = NULL; -static void RADEONBlankSet(ScrnInfoPtr pScrn, RADEONConnector *pPort) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - switch(pPort->MonType) { - case MT_LCD: - OUTREGP(RADEON_LVDS_GEN_CNTL, RADEON_LVDS_DISPLAY_DIS, ~RADEON_LVDS_DISPLAY_DIS); - break; + if (xf86_config->crtc[1]->enabled && xf86_config->crtc[0]->enabled) { + pixel_bytes2 = info->CurrentLayout.pixel_bytes; + mode1 = &xf86_config->crtc[0]->mode; + mode2 = &xf86_config->crtc[1]->mode; + } else if (xf86_config->crtc[0]->enabled) { + mode1 = &xf86_config->crtc[0]->mode; + } else if (xf86_config->crtc[1]->enabled) { + mode1 = &xf86_config->crtc[1]->mode; + } else + return; + } - case MT_CRT: - if ((info->ChipFamily == CHIP_FAMILY_R200) && - (pPort->DACType == DAC_TVDAC)) - OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); - - break; - case MT_DFP: - if (pPort->TMDSType == TMDS_EXT) - OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); - else - OUTREGP(RADEON_FP_GEN_CNTL, RADEON_FP_BLANK_EN, ~RADEON_FP_BLANK_EN); - - break; - case MT_NONE: - default: - break; - } + RADEONInitDispBandwidth2(pScrn, info, pixel_bytes2, mode1, mode2); } -/* Blank screen */ void RADEONBlank(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONConnector *pPort; - - if (!pRADEONEnt->HasSecondary || - (pRADEONEnt->HasSecondary && !info->IsSwitching) || - (info->IsSwitching && (!info->IsSecondary))) { - pPort = RADEONGetCrtcConnector(pScrn, 1); - if (pPort) - RADEONBlankSet(pScrn, pPort); - OUTREGP (RADEON_CRTC_EXT_CNTL, - RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS, - ~(RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS)); - - if (!pRADEONEnt->HasCRTC2) return; - - if (pRADEONEnt->Controller[1]->binding == 1) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) - RADEONBlankSet(pScrn, pPort); - OUTREGP (RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS, - ~(RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS)); - } - } + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + int o, c; - if ((pRADEONEnt->HasSecondary && !info->IsSwitching) || - (info->IsSwitching && info->IsSecondary)) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) - RADEONBlankSet(pScrn, pPort); - OUTREGP (RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS, - ~(RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS)); - } -} - -static void RADEONUnblankSet(ScrnInfoPtr pScrn, RADEONConnector *pPort) -{ - RADEONInfoPtr info = RADEONPTR (pScrn); - unsigned char *RADEONMMIO = info->MMIO; + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + for (o = 0; o < xf86_config->num_output; o++) { + output = xf86_config->output[o]; + if (output->crtc != crtc) + continue; - switch(pPort->MonType) { - case MT_LCD: - OUTREGP(RADEON_LVDS_GEN_CNTL, 0, ~RADEON_LVDS_DISPLAY_DIS); - break; - case MT_CRT: - if ((info->ChipFamily == CHIP_FAMILY_R200) && - (pPort->DACType == DAC_TVDAC)) - OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); - break; - case MT_DFP: - if (pPort->TMDSType == TMDS_EXT) - OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); - else - OUTREGP(RADEON_FP_GEN_CNTL, 0, ~RADEON_FP_BLANK_EN); - break; - case MT_NONE: - default: - break; + output->funcs->dpms(output, DPMSModeOff); + } + crtc->funcs->dpms(crtc, DPMSModeOff); } } -/* Unblank screen */ void RADEONUnblank(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONConnector *pPort; - - if (!pRADEONEnt->HasSecondary || (info->IsSwitching && !info->IsSecondary)) { - pPort = RADEONGetCrtcConnector(pScrn, 1); - if (pPort) - RADEONUnblankSet(pScrn, pPort); - OUTREGP(RADEON_CRTC_EXT_CNTL, - 0, - ~(RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS)); - - if (!pRADEONEnt->HasCRTC2) return; - - if (pRADEONEnt->Controller[1]->binding == 1) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) - RADEONUnblankSet(pScrn, pPort); - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, - ~(RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS)); - } - } - - if (info->IsSwitching && info->IsSecondary) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) - RADEONUnblankSet(pScrn, pPort); - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, - ~(RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS)); - } -} - -static void RADEONDPMSSetOn(ScrnInfoPtr pScrn, RADEONConnector *pPort) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONMonitorType MonType; - RADEONTmdsType TmdsType; - RADEONDacType DacType; - - MonType = pPort->MonType; - TmdsType = pPort->TMDSType; - DacType = pPort->DACType; - - switch(MonType) { - case MT_LCD: - OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON); - usleep (info->PanelPwrDly * 1000); - OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON); - break; - case MT_DFP: - if (TmdsType == TMDS_EXT) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, - ~RADEON_FP2_DVO_EN); - } - } else - OUTREGP (RADEON_FP_GEN_CNTL, (RADEON_FP_FPON | RADEON_FP_TMDS_EN), - ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); - break; - case MT_CRT: - default: - RADEONDacPowerSet(pScrn, TRUE, (DacType == DAC_PRIMARY)); - break; - } -} - -static void RADEONDPMSSetOff(ScrnInfoPtr pScrn, RADEONConnector *pPort) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONMonitorType MonType; - RADEONTmdsType TmdsType; - RADEONDacType DacType; - unsigned long tmpPixclksCntl; - - MonType = pPort->MonType; - TmdsType = pPort->TMDSType; - DacType = pPort->DACType; - - switch(MonType) { - case MT_LCD: - tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - if (info->IsMobility || info->IsIGP) { - /* Asic bug, when turning off LVDS_ON, we have to make sure - RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off - */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); - } - OUTREGP (RADEON_LVDS_GEN_CNTL, 0, - ~(RADEON_LVDS_BLON | RADEON_LVDS_ON)); - if (info->IsMobility || info->IsIGP) { - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); - } - break; - case MT_DFP: - if (TmdsType == TMDS_EXT) { - OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); - if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN); - } - } else - OUTREGP (RADEON_FP_GEN_CNTL, 0, ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); - break; - case MT_CRT: - default: - RADEONDacPowerSet(pScrn, FALSE, (DacType == DAC_PRIMARY)); - break; - } -} - - -/* Sets VESA Display Power Management Signaling (DPMS) Mode */ -void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, - int PowerManagementMode, - int flags) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONConnector *pPort; - if (!pScrn->vtSema) return; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + int o, c; - RADEONTRACE(("RADEONDisplayPowerManagementSet(%d,0x%x)\n", PowerManagementMode, flags)); + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + if(!crtc->enabled) + continue; + crtc->funcs->dpms(crtc, DPMSModeOn); + for (o = 0; o < xf86_config->num_output; o++) { + output = xf86_config->output[o]; + if (output->crtc != crtc) + continue; -#ifdef XF86DRI - if (info->CPStarted) DRILock(pScrn->pScreen, 0); -#endif - - if (info->accelOn) - RADEON_SYNC(info, pScrn); - - if (info->FBDev) { - fbdevHWDPMSSet(pScrn, PowerManagementMode, flags); - } else { - int mask1 = (RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_HSYNC_DIS | - RADEON_CRTC_VSYNC_DIS); - int mask2 = (RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS); - - switch (PowerManagementMode) { - case DPMSModeOn: - /* Screen: On; HSync: On, VSync: On */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); - else { - if (pRADEONEnt->Controller[1]->binding == 1) - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask1); - } - break; - - case DPMSModeStandby: - /* Screen: Off; HSync: Off, VSync: On */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), - ~mask2); - else { - if (pRADEONEnt->Controller[1]->binding == 1) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), - ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, - (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), - ~mask1); - } - break; - - case DPMSModeSuspend: - /* Screen: Off; HSync: On, VSync: Off */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), - ~mask2); - else { - if (pRADEONEnt->Controller[1]->binding == 1) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), - ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, - (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), - ~mask1); - } - break; - - case DPMSModeOff: - /* Screen: Off; HSync: Off, VSync: Off */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); - else { - if (pRADEONEnt->Controller[1]->binding == 1) - OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, mask1, ~mask1); - } - break; + output->funcs->dpms(output, DPMSModeOn); } - - if (PowerManagementMode == DPMSModeOn) { - pPort = RADEONGetCrtcConnector(pScrn, info->IsSecondary ? 2 : 1); - RADEONDPMSSetOn(pScrn, pPort); - if (pRADEONEnt->Controller[1]->binding == 1) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - RADEONDPMSSetOn(pScrn, pPort); - } - } else if ((PowerManagementMode == DPMSModeOff) || - (PowerManagementMode == DPMSModeSuspend) || - (PowerManagementMode == DPMSModeStandby)) { - pPort = RADEONGetCrtcConnector(pScrn, info->IsSecondary ? 2 : 1); - RADEONDPMSSetOff(pScrn, pPort); - if (pRADEONEnt->Controller[1]->binding == 1) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - RADEONDPMSSetOff(pScrn, pPort); - } - } } - -#ifdef XF86DRI - if (info->CPStarted) DRIUnlock(pScrn->pScreen); -#endif -} - -Bool RADEONAllocateControllers(ScrnInfoPtr pScrn) -{ - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - if (pRADEONEnt->Controller[0]) - return TRUE; - - pRADEONEnt->Controller[0] = xcalloc(sizeof(RADEONController), 1); - if (!pRADEONEnt->Controller[0]) - return FALSE; - - pRADEONEnt->Controller[1] = xcalloc(sizeof(RADEONController), 1); - if (!pRADEONEnt->Controller[1]) - { - xfree(pRADEONEnt->Controller[0]); - return FALSE; - } - - return TRUE; -} - -Bool RADEONAllocateConnectors(ScrnInfoPtr pScrn) -{ - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - int i; - - if (pRADEONEnt->PortInfo[0]) - return TRUE; - - /* for now always allocate max connectors */ - for (i = 0 ; i < RADEON_MAX_CONNECTOR; i++) { - pRADEONEnt->PortInfo[i] = xcalloc(sizeof(RADEONConnector), 1); - if (!pRADEONEnt->PortInfo[i]) - return FALSE; - } - - return TRUE; -} - -RADEONConnector *RADEONGetCrtcConnector(ScrnInfoPtr pScrn, int crtc_num) -{ - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - if (pRADEONEnt->PortInfo[0]->crtc_num == crtc_num) - return pRADEONEnt->PortInfo[0]; - else if (pRADEONEnt->PortInfo[1]->crtc_num == crtc_num) - return pRADEONEnt->PortInfo[1]; - return NULL; } diff --git a/src/radeon_dri.c b/src/radeon_dri.c index ee6192e9..24018e8b 100644 --- a/src/radeon_dri.c +++ b/src/radeon_dri.c @@ -69,7 +69,12 @@ static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen); static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen); #ifdef DAMAGE -static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, RegionPtr pReg); + +#if (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)) +static void RADEONDRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num); +#endif #endif /* Initialize the visual configs that are supported by the hardware. @@ -398,10 +403,10 @@ static void RADEONLeaveServer(ScreenPtr pScreen) #ifdef DAMAGE if (info->pDamage) { RegionPtr pDamageReg = DamageRegion(info->pDamage); + int nrects = pDamageReg ? REGION_NUM_RECTS(pDamageReg) : 0; - if (pDamageReg) { - RADEONDRIRefreshArea(pScrn, REGION_NUM_RECTS(pDamageReg), - REGION_RECTS(pDamageReg)); + if (nrects) { + RADEONDRIRefreshArea(pScrn, pDamageReg); } } #endif @@ -409,13 +414,7 @@ static void RADEONLeaveServer(ScreenPtr pScreen) /* The CP is always running, but if we've generated any CP commands * we must flush them to the kernel module now. */ - if (info->CPInUse) { - RADEON_FLUSH_CACHE(); - RADEON_WAIT_UNTIL_IDLE(); - RADEONCPReleaseIndirect(pScrn); - - info->CPInUse = FALSE; - } + RADEONCP_RELEASE(pScrn, info); #ifdef USE_EXA info->engineMode = EXA_ENGINEMODE_UNKNOWN; @@ -754,28 +753,6 @@ static Bool RADEONSetAgpMode(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, from, "Using AGP %dx\n", info->agpMode); - info->agpFastWrite = 0; // Always off by default as it sucks - - from = xf86GetOptValInteger(info->Options, OPTION_AGP_FW, - &info->agpFastWrite) ? X_CONFIG : X_DEFAULT; - - if (info->agpFastWrite && - (vendor == PCI_VENDOR_AMD) && - (device == PCI_CHIP_AMD761)) { - - /* Disable fast write for AMD 761 chipset, since they cause - * lockups when enabled. - */ - info->agpFastWrite = FALSE; - from = X_DEFAULT; - xf86DrvMsg(pScreen->myNum, X_WARNING, - "[agp] Not enabling Fast Writes on AMD 761 chipset to avoid " - "lockups"); - } - - xf86DrvMsg(pScreen->myNum, from, "AGP Fast Writes %sabled\n", - info->agpFastWrite ? "en" : "dis"); - mode &= ~RADEON_AGP_MODE_MASK; if (is_v3) { /* only set one mode bit for AGPv3 */ @@ -794,8 +771,26 @@ static Bool RADEONSetAgpMode(RADEONInfoPtr info, ScreenPtr pScreen) } } - if (info->agpFastWrite) mode |= RADEON_AGP_FW_MODE; - else mode &= ~RADEON_AGP_FW_MODE; + /* AGP Fast Writes. + * TODO: take into account that certain agp modes don't support fast + * writes at all */ + mode &= ~RADEON_AGP_FW_MODE; /* Disable per default */ + if (xf86ReturnOptValBool(info->Options, OPTION_AGP_FW, FALSE)) { + xf86DrvMsg(pScreen->myNum, X_WARNING, + "WARNING: Using the AGPFastWrite option is not recommended.\n"); + xf86Msg(X_NONE, "\tThis option does not provide much of a noticable speed" + " boost, while it\n\twill probably hard lock your machine." + " All bets are off!\n"); + + /* Black list some host/AGP bridges. */ + if ((vendor == PCI_VENDOR_AMD) && (device == PCI_CHIP_AMD761)) + xf86DrvMsg(pScreen->myNum, X_PROBED, "Ignoring AGPFastWrite option " + "for the AMD 761 northbridge.\n"); + else { + xf86DrvMsg(pScreen->myNum, X_CONFIG, "Enabling AGP Fast Writes.\n"); + mode |= RADEON_AGP_FW_MODE; + } + } /* Don't mention this otherwise, so that people don't get funny ideas */ xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", @@ -1250,7 +1245,7 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn) /* Check the DRI version */ DRIQueryVersion(&major, &minor, &patch); - if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { + if (major != DRIINFO_MAJOR_VERSION || minor < 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] RADEONDRIGetVersion failed because of a version " "mismatch.\n" @@ -1258,7 +1253,7 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn) "needed.\n" "[dri] Disabling DRI.\n", major, minor, patch, - DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); + DRIINFO_MAJOR_VERSION, 0); return FALSE; } @@ -1358,6 +1353,29 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn) return TRUE; } +Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int value = 0; + + if (info->directRenderingEnabled && info->pKernelDRMVersion->version_minor >= 28) { + if (on) { + if (xf86_config->num_crtc > 1 && xf86_config->crtc[1]->enabled) + value = DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2; + else + value = DRM_RADEON_VBLANK_CRTC1; + } + + if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_VBLANK_CRTC, value)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RADEON Vblank Crtc Setup Failed %d\n", value); + return FALSE; + } + } + return TRUE; +} + + /* Initialize the screen-specific data structures for the DRI and the * Radeon. This is the main entry point to the device-specific * initialization code. It calls device-independent DRI functions to @@ -1477,10 +1495,31 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) pDRIInfo->TransitionTo3d = RADEONDRITransitionTo3d; pDRIInfo->TransitionSingleToMulti3D = RADEONDRITransitionSingleToMulti3d; pDRIInfo->TransitionMultiToSingle3D = RADEONDRITransitionMultiToSingle3d; +#if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && \ + DRIINFO_MINOR_VERSION >= 1)) + pDRIInfo->ClipNotify = RADEONDRIClipNotify; +#endif pDRIInfo->createDummyCtx = TRUE; pDRIInfo->createDummyCtxPriv = FALSE; +#ifdef USE_EXA + if (info->useEXA) { +#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3 + int major, minor, patch; + + DRIQueryVersion(&major, &minor, &patch); + + if (minor >= 3) +#endif +#if DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3) + pDRIInfo->texOffsetStart = RADEONTexOffsetStart; +#endif + } +#endif + if (!DRIScreenInit(pScreen, pDRIInfo, &info->drmFD)) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRIScreenInit failed. Disabling DRI.\n"); @@ -1646,6 +1685,9 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) info->DRICloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = RADEONDRIDoCloseScreen; + /* disable vblank at startup */ + RADEONDRISetVBlankInterrupt (pScrn, FALSE); + return TRUE; } @@ -1696,20 +1738,15 @@ void RADEONDRIStop(ScreenPtr pScreen) RADEONInfoPtr info = RADEONPTR(pScrn); RING_LOCALS; - RADEONTRACE(("RADEONDRIStop\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONDRIStop\n"); /* Stop the CP */ if (info->directRenderingInited) { /* If we've generated any CP commands, we must flush them to the * kernel module now. */ - if (info->CPInUse) { - RADEON_FLUSH_CACHE(); - RADEON_WAIT_UNTIL_IDLE(); - RADEONCPReleaseIndirect(pScrn); - - info->CPInUse = FALSE; - } + RADEONCP_RELEASE(pScrn, info); RADEONCP_STOP(pScrn, info); } info->directRenderingInited = FALSE; @@ -1724,9 +1761,15 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) RADEONInfoPtr info = RADEONPTR(pScrn); drmRadeonInit drmInfo; - RADEONTRACE(("RADEONDRICloseScreen\n")); - + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONDRICloseScreen\n"); + +#ifdef DAMAGE + REGION_UNINIT(pScreen, &info->driRegion); +#endif + if (info->irq) { + RADEONDRISetVBlankInterrupt (pScrn, FALSE); drmCtlUninstHandler(info->drmFD); info->irq = 0; info->ModeReg.gen_int_cntl = 0; @@ -1819,15 +1862,17 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) */ -static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, RegionPtr pReg) { RADEONInfoPtr info = RADEONPTR(pScrn); - int i; + int i, num; ScreenPtr pScreen = pScrn->pScreen; RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); #ifdef USE_EXA PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); #endif + RegionRec region; + BoxPtr pbox; if (!info->directRenderingInited || !info->CPStarted) return; @@ -1838,6 +1883,17 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) return; + REGION_NULL(pScreen, ®ion); + REGION_SUBTRACT(pScreen, ®ion, pReg, &info->driRegion); + + num = REGION_NUM_RECTS(®ion); + + if (!num) { + goto out; + } + + pbox = REGION_RECTS(®ion); + /* pretty much a hack. */ #ifdef USE_EXA @@ -1858,7 +1914,7 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) if (!info->useEXA) { /* Make sure accel has been properly inited */ if (info->accel == NULL || info->accel->SetupForScreenToScreenCopy == NULL) - return; + goto out; if (info->tilingEnabled) info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; (*info->accel->SetupForScreenToScreenCopy)(pScrn, @@ -1894,6 +1950,8 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) info->dst_pitch_offset &= ~RADEON_DST_TILE_MACRO; #endif +out: + REGION_NULL(pScreen, ®ion); DamageEmpty(info->pDamage); } @@ -1907,16 +1965,13 @@ static void RADEONEnablePageFlip(ScreenPtr pScreen) if (info->allowPageFlip) { RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + BoxRec box = { .x1 = 0, .y1 = 0, .x2 = pScrn->virtualX - 1, + .y2 = pScrn->virtualY - 1 }; + RegionPtr pReg = REGION_CREATE(pScreen, &box, 1); pSAREAPriv->pfAllowPageFlip = 1; - -#ifdef USE_XAA - if (!info->useEXA) { - BoxRec box = { .x1 = 0, .y1 = 0, .x2 = pScrn->virtualX - 1, - .y2 = pScrn->virtualY - 1 }; - RADEONDRIRefreshArea(pScrn, 1, &box); - } -#endif + RADEONDRIRefreshArea(pScrn, pReg); + REGION_DESTROY(pScreen, pReg); } #endif } @@ -2023,6 +2078,9 @@ static void RADEONDRITransitionTo3d(ScreenPtr pScreen) RADEONChangeSurfaces(pScrn); RADEONEnablePageFlip(pScreen); + + info->want_vblank_interrupts = TRUE; + RADEONDRISetVBlankInterrupt(pScrn, TRUE); if (info->cursor) xf86ForceHWCursor (pScreen, TRUE); @@ -2062,10 +2120,40 @@ static void RADEONDRITransitionTo2d(ScreenPtr pScreen) RADEONChangeSurfaces(pScrn); + info->want_vblank_interrupts = FALSE; + RADEONDRISetVBlankInterrupt(pScrn, FALSE); + if (info->cursor) xf86ForceHWCursor (pScreen, FALSE); } +#if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && \ + DRIINFO_MINOR_VERSION >= 1)) +static void +RADEONDRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + REGION_UNINIT(pScreen, &info->driRegion); + REGION_NULL(pScreen, &info->driRegion); + + if (num > 0) { + int i; + + for (i = 0; i < num; i++) { + WindowPtr pWin = ppWin[i]; + + if (pWin) { + REGION_UNION(pScreen, &info->driRegion, &pWin->clipList, + &info->driRegion); + } + } + } +} +#endif + void RADEONDRIAllocatePCIGARTTable(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; diff --git a/src/radeon_driver.c b/src/radeon_driver.c index ca0b2016..158e1e46 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -74,7 +74,6 @@ #include "radeon_macros.h" #include "radeon_probe.h" #include "radeon_version.h" -#include "radeon_mergedfb.h" #ifdef XF86DRI #define _XF86DRI_SERVER_ @@ -94,15 +93,15 @@ #include "xf86_ansic.h" /* For xf86getsecs() */ #include "xf86_OSproc.h" #include "xf86RAC.h" +#include "xf86RandR12.h" #include "xf86Resources.h" #include "xf86cmap.h" #include "vbe.h" - /* fbdevhw * vgaHW definitions */ + /* vgaHW definitions */ #ifdef WITH_VGAHW #include "vgaHW.h" #endif -#include "fbdevhw.h" #define DPMS_SERVER #include <X11/extensions/dpms.h> @@ -116,10 +115,7 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode); static void RADEONSave(ScrnInfoPtr pScrn); -static void RADEONRestore(ScrnInfoPtr pScrn); -static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); -static void RADEONGetMergedFBOptions(ScrnInfoPtr pScrn); static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode); static void RADEONForceSomeClocks(ScrnInfoPtr pScrn); static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); @@ -128,9 +124,11 @@ static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); #endif -/* psuedo xinerama support */ +DisplayModePtr +RADEONCrtcFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode); -extern Bool RADEONnoPanoramiXExtension; +static void RADEONWaitPLLLock(ScrnInfoPtr pScrn, unsigned nTests, + unsigned nWaitLoops, unsigned cntThreshold); static const OptionInfoRec RADEONOptions[] = { { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, @@ -159,19 +157,7 @@ static const OptionInfoRec RADEONOptions[] = { #endif #endif { OPTION_DDC_MODE, "DDCMode", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR, {0}, FALSE }, { OPTION_IGNORE_EDID, "IgnoreEDID", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_MERGEDFB, "MergedFB", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_CRT2HSYNC, "CRT2HSync", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_CRT2VREFRESH, "CRT2VRefresh", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_CRT2POS, "CRT2Position", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_METAMODES, "MetaModes", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_MERGEDDPI, "MergedDPI", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_RADEONXINERAMA, "MergedXinerama", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_CRT2ISSCRN0, "MergedXineramaCRT2IsScreen0", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_MERGEDFBNONRECT, "MergedNonRectangular", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_MERGEDFBMOUSER, "MergedMouseRestriction", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DISP_PRIORITY, "DisplayPriority", OPTV_ANYSTR, {0}, FALSE }, { OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE }, { OPTION_MIN_DOTCLOCK, "ForceMinDotClock", OPTV_FREQ, {0}, FALSE }, @@ -198,12 +184,13 @@ static const OptionInfoRec RADEONOptions[] = { { OPTION_LVDS_PROBE_PLL, "LVDSProbePLL", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, { OPTION_CONSTANTDPI, "ConstantDPI", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_REVERSE_DISPLAY,"ReverseDisplay", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CONNECTORTABLE, "ConnectorTable", OPTV_STRING, {0}, FALSE }, + { OPTION_DEFAULT_CONNECTOR_TABLE, "DefaultConnectorTable", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; -_X_EXPORT const OptionInfoRec *RADEONOptionsWeak(void) { return RADEONOptions; } +const OptionInfoRec *RADEONOptionsWeak(void) { return RADEONOptions; } #ifdef WITH_VGAHW static const char *vgahwSymbols[] = { @@ -219,34 +206,6 @@ static const char *vgahwSymbols[] = { }; #endif -static const char *fbdevHWSymbols[] = { - "fbdevHWInit", - "fbdevHWUseBuildinMode", - - "fbdevHWGetVidmem", - - "fbdevHWDPMSSet", - - /* colormap */ - "fbdevHWLoadPalette", - /* ScrnInfo hooks */ - "fbdevHWAdjustFrame", - "fbdevHWEnterVT", - "fbdevHWLeaveVT", - "fbdevHWModeInit", - "fbdevHWRestore", - "fbdevHWSave", - "fbdevHWSwitchMode", - "fbdevHWValidModeWeak", - - "fbdevHWMapMMIO", - "fbdevHWMapVidmem", - "fbdevHWUnmapMMIO", - "fbdevHWUnmapVidmem", - - NULL -}; - static const char *ddcSymbols[] = { "xf86PrintEDID", "xf86DoEDID_DDC1", @@ -407,7 +366,6 @@ void RADEONLoaderRefSymLists(void) drmSymbols, driSymbols, #endif - fbdevHWSymbols, vbeSymbols, int10Symbols, i2cSymbols, @@ -441,6 +399,24 @@ struct RADEONInt10Save { static Bool RADEONMapMMIO(ScrnInfoPtr pScrn); static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn); +#if 0 +static Bool +RADEONCreateScreenResources (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + pScreen->CreateScreenResources = info->CreateScreenResources; + if (!(*pScreen->CreateScreenResources)(pScreen)) + return FALSE; + + if (!xf86RandR12CreateScreenResources(pScreen)) + return FALSE; + + return TRUE; +} +#endif + RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn) { DevUnion *pPriv; @@ -534,48 +510,6 @@ static Bool RADEONGetRec(ScrnInfoPtr pScrn) /* Free our private RADEONInfoRec */ static void RADEONFreeRec(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - if(info->CRT2HSync) xfree(info->CRT2HSync); - info->CRT2HSync = NULL; - if(info->CRT2VRefresh) xfree(info->CRT2VRefresh); - info->CRT2VRefresh = NULL; - if(info->MetaModes) xfree(info->MetaModes); - info->MetaModes = NULL; - if(info->CRT2pScrn) { - if(info->CRT2pScrn->modes) { - while(info->CRT2pScrn->modes) - xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); - } - if(info->CRT2pScrn->monitor) { - if(info->CRT2pScrn->monitor->Modes) { - while(info->CRT2pScrn->monitor->Modes) - xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); - } - if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); - xfree(info->CRT2pScrn->monitor); - } - xfree(info->CRT2pScrn); - info->CRT2pScrn = NULL; - } - if(info->CRT1Modes) { - if(info->CRT1Modes != pScrn->modes) { - if(pScrn->modes) { - pScrn->currentMode = pScrn->modes; - do { - DisplayModePtr p = pScrn->currentMode->next; - if(pScrn->currentMode->Private) - xfree(pScrn->currentMode->Private); - xfree(pScrn->currentMode); - pScrn->currentMode = p; - } while(pScrn->currentMode != pScrn->modes); - } - pScrn->currentMode = info->CRT1CurrentMode; - pScrn->modes = info->CRT1Modes; - info->CRT1CurrentMode = NULL; - info->CRT1Modes = NULL; - } - } - if (!pScrn || !pScrn->driverPrivate) return; xfree(pScrn->driverPrivate); pScrn->driverPrivate = NULL; @@ -588,15 +522,11 @@ static Bool RADEONMapMMIO(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->FBDev) { - info->MMIO = fbdevHWMapMMIO(pScrn); - } else { - info->MMIO = xf86MapPciMem(pScrn->scrnIndex, - VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, - info->PciTag, - info->MMIOAddr, - info->MMIOSize); - } + info->MMIO = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, + info->PciTag, + info->MMIOAddr, + info->MMIOSize); if (!info->MMIO) return FALSE; return TRUE; @@ -609,11 +539,8 @@ static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->FBDev) - fbdevHWUnmapMMIO(pScrn); - else { - xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, info->MMIOSize); - } + xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, info->MMIOSize); + info->MMIO = NULL; return TRUE; } @@ -623,16 +550,13 @@ static Bool RADEONMapFB(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->FBDev) { - info->FB = fbdevHWMapVidmem(pScrn); - } else { - RADEONTRACE(("Map: 0x%08lx, 0x%08lx\n", info->LinearAddr, info->FbMapSize)); - info->FB = xf86MapPciMem(pScrn->scrnIndex, - VIDMEM_FRAMEBUFFER, - info->PciTag, - info->LinearAddr, - info->FbMapSize); - } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Map: 0x%08lx, 0x%08lx\n", info->LinearAddr, info->FbMapSize); + info->FB = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_FRAMEBUFFER, + info->PciTag, + info->LinearAddr, + info->FbMapSize); if (!info->FB) return FALSE; return TRUE; @@ -643,10 +567,7 @@ static Bool RADEONUnmapFB(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->FBDev) - fbdevHWUnmapVidmem(pScrn); - else - xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize); + xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize); info->FB = NULL; return TRUE; } @@ -758,7 +679,7 @@ void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 crtc_gen_cntl; - int i; + struct timeval timeout; crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || @@ -769,10 +690,10 @@ void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn) OUTREG(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); /* Wait for it to go back up */ - for (i = 0; i < RADEON_TIMEOUT/1000; i++) { - if (INREG(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_SAVE) break; - usleep(1); - } + radeon_init_timeout(&timeout, RADEON_VSYNC_TIMEOUT); + while (!(INREG(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_SAVE) && + !radeon_timedout(&timeout)) + usleep(100); } /* Wait for vertical sync on secondary CRTC */ @@ -781,7 +702,7 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 crtc2_gen_cntl; - int i; + struct timeval timeout; crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || @@ -792,10 +713,10 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn) OUTREG(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); /* Wait for it to go back up */ - for (i = 0; i < RADEON_TIMEOUT/1000; i++) { - if (INREG(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_SAVE) break; - usleep(1); - } + radeon_init_timeout(&timeout, RADEON_VSYNC_TIMEOUT); + while (!(INREG(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_SAVE) && + !radeon_timedout(&timeout)) + usleep(100); } @@ -953,7 +874,8 @@ static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn) if (ref_div < 2) { CARD32 tmp; tmp = INPLL(pScrn, RADEON_PPLL_REF_DIV); - if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RS300)) + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RS300) + || (info->ChipFamily == CHIP_FAMILY_RS400)) ref_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; else @@ -1033,7 +955,8 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn) CARD32 tmp; tmp = INPLL(pScrn, RADEON_PPLL_REF_DIV); if (IS_R300_VARIANT || - (info->ChipFamily == CHIP_FAMILY_RS300)) { + (info->ChipFamily == CHIP_FAMILY_RS300) || + (info->ChipFamily == CHIP_FAMILY_RS400)) { pll->reference_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; } else { pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK; @@ -1083,10 +1006,11 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn) } xf86DrvMsg (pScrn->scrnIndex, X_INFO, - "PLL parameters: rf=%d rd=%d min=%ld max=%ld; xclk=%d\n", + "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n", pll->reference_freq, pll->reference_div, - pll->min_pll_freq, pll->max_pll_freq, pll->xclk); + (unsigned)pll->min_pll_freq, (unsigned)pll->max_pll_freq, + pll->xclk); /* (Some?) Radeon BIOSes seem too lie about their minimum dot * clocks. Allow users to override the detected minimum dot clock @@ -1200,7 +1124,7 @@ static Bool RADEONPreInitWeight(ScrnInfoPtr pScrn) return TRUE; } -static void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, +void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, RADEONInfoPtr info) { save->mc_fb_location = info->mc_fb_location; @@ -1214,7 +1138,7 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - unsigned long mem_size; + CARD32 mem_size; CARD32 aper_size; /* Default to existing values */ @@ -1242,8 +1166,7 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn) } #endif - /* We won't try to change MC_FB_LOCATION when using fbdev */ - if (!info->FBDev) { + { if (info->IsIGP) info->mc_fb_location = INREG(RADEON_NB_TOM); else @@ -1283,10 +1206,15 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn) */ info->mc_agp_location = 0xffffffc0; - RADEONTRACE(("RADEONInitMemoryMap() : \n")); - RADEONTRACE((" mem_size : 0x%08lx\n", mem_size)); - RADEONTRACE((" MC_FB_LOCATION : 0x%08lx\n", info->mc_fb_location)); - RADEONTRACE((" MC_AGP_LOCATION : 0x%08lx\n", info->mc_agp_location)); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "RADEONInitMemoryMap() : \n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " mem_size : 0x%08x\n", (unsigned)mem_size); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " MC_FB_LOCATION : 0x%08x\n", (unsigned)info->mc_fb_location); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " MC_AGP_LOCATION : 0x%08x\n", + (unsigned)info->mc_agp_location); } static void RADEONGetVRamType(ScrnInfoPtr pScrn) @@ -1349,8 +1277,8 @@ static CARD32 RADEONGetAccessibleVRAM(ScrnInfoPtr pScrn) if (info->directRenderingEnabled && info->pKernelDRMVersion->version_minor < 23) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "[dri] limiting video memory to one aperture of %ldK\n", - aper_size); + "[dri] limiting video memory to one aperture of %uK\n", + (unsigned)aper_size); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "[dri] detected radeon kernel module version 1.%d but" " 1.23 or newer is required for full memory mapping.\n", @@ -1406,9 +1334,7 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) MessageType from = X_PROBED; CARD32 accessible, bar_size; - if (info->FBDev) - pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024; - else if ((info->IsIGP)) { + if ((info->IsIGP)) { CARD32 tom = INREG(RADEON_NB_TOM); pScrn->videoRam = (((tom >> 16) - @@ -1437,8 +1363,8 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) accessible = bar_size; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected total video RAM=%dK, accessible=%ldK (PCI BAR=%ldK)\n", - pScrn->videoRam, accessible, bar_size); + "Detected total video RAM=%dK, accessible=%uK (PCI BAR=%uK)\n", + pScrn->videoRam, (unsigned)accessible, (unsigned)bar_size); if (pScrn->videoRam > accessible) pScrn->videoRam = accessible; @@ -1459,24 +1385,6 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, from, "Mapped VideoRAM: %d kByte (%d bit %s SDRAM)\n", pScrn->videoRam, info->RamWidth, info->IsDDR?"DDR":"SDR"); - /* FIXME: For now, split FB into two equal sections. This should - * be able to be adjusted by user with a config option. */ - if (info->IsPrimary) { - pScrn->videoRam /= 2; - info->MergedFB = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %dk of videoram for primary head\n", - pScrn->videoRam); - } - - if (info->IsSecondary) { - pScrn->videoRam /= 2; - info->LinearAddr += pScrn->videoRam * 1024; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %dk of videoram for secondary head\n", - pScrn->videoRam); - } - pScrn->videoRam &= ~1023; info->FbMapSize = pScrn->videoRam * 1024; @@ -1543,6 +1451,7 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) info->IsIGP = FALSE; info->IsDellServer = FALSE; info->HasSingleDAC = FALSE; + info->InternalTVOut = TRUE; switch (info->Chipset) { case PCI_CHIP_RADEON_LY: case PCI_CHIP_RADEON_LZ: @@ -1602,6 +1511,7 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) case PCI_CHIP_R200_QL: case PCI_CHIP_R200_QM: info->ChipFamily = CHIP_FAMILY_R200; + info->InternalTVOut = FALSE; break; case PCI_CHIP_RADEON_LW: @@ -1713,7 +1623,7 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) case PCI_CHIP_RS482_5974: info->ChipFamily = CHIP_FAMILY_RS400; info->IsIGP = TRUE; - /*info->HasSingleDAC = TRUE;*/ /* ??? */ + info->HasSingleDAC = TRUE; break; case PCI_CHIP_RV410_564A: @@ -1784,6 +1694,7 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) /* Original Radeon/7200 */ info->ChipFamily = CHIP_FAMILY_RADEON; pRADEONEnt->HasCRTC2 = FALSE; + info->InternalTVOut = FALSE; } @@ -1903,10 +1814,15 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) } } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s card detected\n", (info->cardType==CARD_PCI) ? "PCI" : (info->cardType==CARD_PCIE) ? "PCIE" : "AGP"); + /* treat PCIE IGP cards as PCI */ + if (info->cardType == CARD_PCIE && info->IsIGP) + info->cardType = CARD_PCI; + if ((s = xf86GetOptValString(info->Options, OPTION_BUS_TYPE))) { if (strcmp(s, "AGP") == 0) { info->cardType = CARD_AGP; @@ -1957,9 +1873,7 @@ static void RADEONPreInitDDC(ScrnInfoPtr pScrn) if (info->ddc2) { if (xf86LoadSubModule(pScrn, "i2c")) { xf86LoaderReqSymLists(i2cSymbols,NULL); - info->ddc2 = RADEONI2cInit(pScrn); } - else info->ddc2 = FALSE; } } @@ -1972,398 +1886,6 @@ static Bool RADEONPreInitGamma(ScrnInfoPtr pScrn) return TRUE; } -/* This is called by RADEONPreInit to validate modes and compute - * parameters for all of the valid modes. - */ -static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - ClockRangePtr clockRanges; - int modesFound; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - char *s; - RADEONConnector *connector; - /* This option has two purposes: - * - * 1. For CRT, if this option is on, xf86ValidateModes (to - * LOOKUP_BEST_REFRESH) is not going to be used for mode - * validation. Instead, we'll validate modes by matching exactly - * the modes supported from the DDC data. This option can be - * used (a) to enable non-standard modes listed in the Detailed - * Timings block of EDID, like 2048x1536 (not included in - * xf86DefModes), (b) to avoid unstable modes for some flat - * panels working in analog mode (some modes validated by - * xf86ValidateModes don't really work with these panels). - * - * 2. For DFP on primary head, with this option on, the validation - * routine will try to use supported modes from DDC data first - * before trying on-chip RMX streching. By default, native mode - * + RMX streching is used for all non-native modes, it appears - * more reliable. Some non-native modes listed in the DDC data - * may not work properly if they are used directly. This seems to - * only happen to a few panels (haven't nailed this down yet, it - * may related to the incorrect setting in TMDS_PLL_CNTL when - * pixel clock is changed). Use this option may give you better - * refresh rate for some non-native modes. The 2nd DVI port will - * always use DDC modes directly (only have one on-chip RMX - * unit). - * - * Note: This option will be dismissed if no DDC data is available. - */ - - if (info->MergedFB) { - if (!(pScrn->display->virtualX)) - info->NoVirtual = TRUE; - else - info->NoVirtual = FALSE; - } - - info->ddc_mode = - xf86ReturnOptValBool(info->Options, OPTION_DDC_MODE, FALSE); - - /* don't use RMX if we have a dual-tmds panels */ - - if ((connector = RADEONGetCrtcConnector(pScrn, 2))) - if (connector->MonType == MT_DFP) - info->ddc_mode = TRUE; - /* don't use RMX if we are Dell Server */ - if (info->IsDellServer) - { - info->ddc_mode = TRUE; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Validating modes on %s head ---------\n", - info->IsSecondary ? "Secondary" : "Primary"); - - if (!pRADEONEnt->PortInfo[0]->MonInfo && !pRADEONEnt->PortInfo[1]->MonInfo && info->ddc_mode) { - info->ddc_mode = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No DDC data available, DDCMode option is dismissed\n"); - } - - if ((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) { - if ((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { - int PanelX, PanelY; - DisplayModePtr tmp_mode = NULL; - if (sscanf(s, "%dx%d", &PanelX, &PanelY) == 2) { - info->PanelXRes = PanelX; - info->PanelYRes = PanelY; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Panel size is forced to: %s\n", s); - - /* We can't trust BIOS or DDC timings anymore, - Use whatever specified in the Modeline. - If no Modeline specified, we'll just pick the VESA mode at - 60Hz refresh rate which is likely to be the best for a flat panel. - */ - info->ddc_mode = FALSE; - pScrn->monitor->DDC = NULL; - tmp_mode = pScrn->monitor->Modes; - while(tmp_mode) { - if ((tmp_mode->HDisplay == PanelX) && - (tmp_mode->VDisplay == PanelY)) { - - float refresh = - (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; - if ((abs(60.0 - refresh) < 1.0) || - (tmp_mode->type == 0)) { - info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; - info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; - info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; - info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; - info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; - info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; - info->DotClock = tmp_mode->Clock; - info->Flags = 0; - break; - } - } - tmp_mode = tmp_mode->next; - } - if (info->DotClock == 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid timing info for specified panel size.\n" - "Please specify the Modeline for this panel\n"); - return FALSE; - } - } else { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Invalid PanelSize value: %s\n", s); - } - } else - RADEONGetPanelInfo(pScrn); - } - - if (pScrn->monitor->DDC) { - /* If we still don't know sync range yet, let's try EDID. - * - * Note that, since we can have dual heads, Xconfigurator - * may not be able to probe both monitors correctly through - * vbe probe function (RADEONProbeDDC). Here we provide an - * additional way to auto-detect sync ranges if they haven't - * been added to XF86Config manually. - */ - if (pScrn->monitor->nHsync <= 0) - RADEONSetSyncRangeFromEdid(pScrn, 1); - if (pScrn->monitor->nVrefresh <= 0) - RADEONSetSyncRangeFromEdid(pScrn, 0); - } - - /* Get mode information */ - pScrn->progClock = TRUE; - clockRanges = xnfcalloc(sizeof(*clockRanges), 1); - clockRanges->next = NULL; - clockRanges->minClock = info->pll.min_pll_freq; - clockRanges->maxClock = info->pll.max_pll_freq * 10; - clockRanges->clockIndex = -1; - clockRanges->interlaceAllowed = (info->DisplayType == MT_CRT); - clockRanges->doubleScanAllowed = (info->DisplayType == MT_CRT); - - /* We'll use our own mode validation routine for DFP/LCD, since - * xf86ValidateModes does not work correctly with the DFP/LCD modes - * 'stretched' from their native mode. - */ - if (info->DisplayType == MT_CRT && !info->ddc_mode) { - - modesFound = - xf86ValidateModes(pScrn, - pScrn->monitor->Modes, - pScrn->display->modes, - clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ - info->allowColorTiling ? 2048 : - 64 * pScrn->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - info->MaxLines, /* maxHeight */ - pScrn->display->virtualX, - pScrn->display->virtualY, - info->FbMapSize, - LOOKUP_BEST_REFRESH); - - if (modesFound < 1 && info->FBDev) { - fbdevHWUseBuildinMode(pScrn); - pScrn->displayWidth = fbdevHWGetLineLength(pScrn) - / info->CurrentLayout.pixel_bytes; - modesFound = 1; - } - - if (modesFound == -1) return FALSE; - - xf86PruneDriverModes(pScrn); - if (!modesFound || !pScrn->modes) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); - return FALSE; - } - - } else { - /* First, free any allocated modes during configuration, since - * we don't need them - */ - while (pScrn->modes) - xf86DeleteMode(&pScrn->modes, pScrn->modes); - while (pScrn->modePool) - xf86DeleteMode(&pScrn->modePool, pScrn->modePool); - - /* Next try to add DDC modes */ - modesFound = RADEONValidateDDCModes(pScrn, pScrn->display->modes, - info->DisplayType, 0); - - /* If that fails and we're connect to a flat panel, then try to - * add the flat panel modes - */ - if (info->DisplayType != MT_CRT) { - - /* some panels have DDC, but don't have internal scaler. - * in this case, we need to validate additional modes - * by using on-chip RMX. - */ - int user_modes_asked = 0, user_modes_found = 0, i; - DisplayModePtr tmp_mode = pScrn->modes; - while (pScrn->display->modes[user_modes_asked]) user_modes_asked++; - if (tmp_mode) { - for (i = 0; i < modesFound; i++) { - if (tmp_mode->type & M_T_USERDEF) user_modes_found++; - tmp_mode = tmp_mode->next; - } - } - - if ((modesFound <= 1) || (user_modes_found < user_modes_asked)) { - /* when panel size is not valid, try to validate - * mode using xf86ValidateModes routine - * This can happen when DDC is disabled. - */ - if (info->PanelXRes < 320 || info->PanelYRes < 200) - modesFound = - xf86ValidateModes(pScrn, - pScrn->monitor->Modes, - pScrn->display->modes, - clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ - info->allowColorTiling ? 2048 : - 64 * pScrn->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - info->MaxLines, /* maxHeight */ - pScrn->display->virtualX, - pScrn->display->virtualY, - info->FbMapSize, - LOOKUP_BEST_REFRESH); - else if (!info->IsSecondary) - modesFound = RADEONValidateFPModes(pScrn, pScrn->display->modes); - } - } - - /* Setup the screen's clockRanges for the VidMode extension */ - if (!pScrn->clockRanges) { - pScrn->clockRanges = xnfcalloc(sizeof(*(pScrn->clockRanges)), 1); - memcpy(pScrn->clockRanges, clockRanges, sizeof(*clockRanges)); - pScrn->clockRanges->strategy = LOOKUP_BEST_REFRESH; - } - - /* Fail if we still don't have any valid modes */ - if (modesFound < 1) { - if (info->DisplayType == MT_CRT) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid DDC modes found for this CRT\n"); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Try turning off the \"DDCMode\" option\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid mode found for this DFP/LCD\n"); - } - return FALSE; - } - } - - xf86SetCrtcForModes(pScrn, 0); - - if (pRADEONEnt->HasCRTC2) { - if (pRADEONEnt->Controller[1]->binding == 1) { - - /* If we have 2 screens from the config file, we don't need - * to do clone thing, let each screen handles one head. - */ - if (!pRADEONEnt->HasSecondary) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Validating CRTC2 modes for MergedFB ------------ \n"); - - modesFound = RADEONValidateMergeModes(pScrn); - if (modesFound < 1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid mode found for CRTC2, disabling MergedFB\n"); - info->MergedFB = FALSE; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total of %d CRTC2 modes found for MergedFB------------ \n", - modesFound); - } - } - } - - pScrn->currentMode = pScrn->modes; - if(info->MergedFB) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Modes for CRT1: ********************\n"); - } - xf86PrintModes(pScrn); - - - if (pRADEONEnt->HasCRTC2) { - if(pRADEONEnt->Controller[1]->binding == 1) { - - xf86SetCrtcForModes(info->CRT2pScrn, INTERLACE_HALVE_V); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Modes for CRT2: ********************\n"); - - xf86PrintModes(info->CRT2pScrn); - - info->CRT1Modes = pScrn->modes; - info->CRT1CurrentMode = pScrn->currentMode; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Generating MergedFB mode list\n"); - - if (info->NoVirtual) { - pScrn->display->virtualX = 0; - pScrn->display->virtualY = 0; - } - pScrn->modes = RADEONGenerateModeList(pScrn, info->MetaModes, - info->CRT1Modes, info->CRT2pScrn->modes, - info->CRT2Position); - - if(!pScrn->modes) { - - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to parse MetaModes or no modes found. MergeFB mode disabled.\n"); - if(info->CRT2pScrn) { - if(info->CRT2pScrn->modes) { - while(info->CRT2pScrn->modes) - xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); - } - if(info->CRT2pScrn->monitor) { - if(info->CRT2pScrn->monitor->Modes) { - while(info->CRT2pScrn->monitor->Modes) - xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); - } - if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); - xfree(info->CRT2pScrn->monitor); - } - xfree(info->CRT2pScrn); - info->CRT2pScrn = NULL; - } - pScrn->modes = info->CRT1Modes; - info->CRT1Modes = NULL; - info->MergedFB = FALSE; - - } - } - } - - if (info->MergedFB) { - /* If no virtual dimension was given by the user, - * calculate a sane one now. Adapts pScrn->virtualX, - * pScrn->virtualY and pScrn->displayWidth. - */ - RADEONRecalcDefaultVirtualSize(pScrn); - info->CRT2pScrn->virtualX = pScrn->virtualX; - info->CRT2pScrn->virtualY = pScrn->virtualY; - RADEONSetPitch(pScrn); - RADEONSetPitch(info->CRT2pScrn); - - pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList() */ - pScrn->currentMode = pScrn->modes; - - /* Update CurrentLayout */ - info->CurrentLayout.mode = pScrn->currentMode; - info->CurrentLayout.displayWidth = pScrn->displayWidth; - } - - /* Set DPI */ - /* xf86SetDpi(pScrn, 0, 0); */ - - if (info->MergedFB) { - RADEONMergedFBSetDpi(pScrn, info->CRT2pScrn, info->CRT2Position); - } else { - xf86SetDpi(pScrn, 0, 0); - info->RADEONDPIVX = pScrn->virtualX; - info->RADEONDPIVY = pScrn->virtualY; - } - - /* Get ScreenInit function */ - if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; - - xf86LoaderReqSymLists(fbSymbols, NULL); - - info->CurrentLayout.displayWidth = pScrn->displayWidth; - info->CurrentLayout.mode = pScrn->currentMode; - - return TRUE; -} - /* This is called by RADEONPreInit to initialize the hardware cursor */ static Bool RADEONPreInitCursor(ScrnInfoPtr pScrn) { @@ -2500,18 +2022,6 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) info->pLibDRMVersion = NULL; info->pKernelDRMVersion = NULL; - if (xf86IsEntityShared(info->pEnt->index)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Direct Rendering Disabled -- " - "Dual-head configuration is not working with " - "DRI at present.\n" - "Please use the radeon MergedFB option if you " - "want Dual-head with DRI.\n"); - return FALSE; - } - if (info->IsSecondary) - return FALSE; - if (info->Chipset == PCI_CHIP_RN50_515E || info->Chipset == PCI_CHIP_RN50_5969) { if (xf86ReturnOptValBool(info->Options, OPTION_DRI, FALSE)) { @@ -2526,18 +2036,6 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) } } - if (info->Chipset == PCI_CHIP_RS400_5A41 || - info->Chipset == PCI_CHIP_RS400_5A42 || - info->Chipset == PCI_CHIP_RC410_5A61 || - info->Chipset == PCI_CHIP_RC410_5A62 || - info->Chipset == PCI_CHIP_RS480_5954 || - info->Chipset == PCI_CHIP_RS480_5955 || - info->Chipset == PCI_CHIP_RS482_5974 || - info->Chipset == PCI_CHIP_RS482_5975) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Direct rendering broken on XPRESS 200 and 200M\n"); - return FALSE; - } if (!xf86ReturnOptValBool(info->Options, OPTION_DRI, TRUE)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -2564,6 +2062,24 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) info->pKernelDRMVersion->version_minor, info->pKernelDRMVersion->version_patchlevel); + if (info->Chipset == PCI_CHIP_RS400_5A41 || + info->Chipset == PCI_CHIP_RS400_5A42 || + info->Chipset == PCI_CHIP_RC410_5A61 || + info->Chipset == PCI_CHIP_RC410_5A62 || + info->Chipset == PCI_CHIP_RS480_5954 || + info->Chipset == PCI_CHIP_RS480_5955 || + info->Chipset == PCI_CHIP_RS482_5974 || + info->Chipset == PCI_CHIP_RS482_5975) { + + if (info->pKernelDRMVersion->version_minor < 27) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Direct rendering broken on XPRESS 200 and 200M with DRI less than 1.27\n"); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Direct rendering experimental on RS400/Xpress 200 enabled\n"); + } + if (xf86ReturnOptValBool(info->Options, OPTION_CP_PIO, FALSE)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CP into PIO mode\n"); info->CPMode = RADEON_DEFAULT_CP_PIO_MODE; @@ -2702,6 +2218,7 @@ static void RADEONPreInitColorTiling(ScrnInfoPtr pScrn) info->allowColorTiling = xf86ReturnOptValBool(info->Options, OPTION_COLOR_TILING, TRUE); if (IS_R300_VARIANT) { + /* this may be 4096 on r4xx -- need to double check */ info->MaxSurfaceWidth = 3968; /* one would have thought 4096...*/ info->MaxLines = 4096; } else { @@ -2728,19 +2245,7 @@ static void RADEONPreInitColorTiling(ScrnInfoPtr pScrn) } #endif /* XF86DRI */ - if ((info->allowColorTiling) && (info->IsSecondary)) { - /* can't have tiling on the 2nd head (as long as it can't use drm). - * We'd never get the surface save/restore (vt switching) right... - */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled for 2nd head\n"); - info->allowColorTiling = FALSE; - } - else if ((info->allowColorTiling) && (info->FBDev)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Color tiling not supported with UseFBDev option\n"); - info->allowColorTiling = FALSE; - } - else if (info->allowColorTiling) { + if (info->allowColorTiling) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling enabled by default\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled\n"); @@ -2935,28 +2440,39 @@ static Bool RADEONPreInitXv(ScrnInfoPtr pScrn) return TRUE; } -static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) +static void RADEONPreInitBIOS(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONGetBIOSInfo(pScrn, pInt10); +#if 0 + RADEONGetBIOSInitTableOffsets(pScrn); + RADEONPostCardFromBIOSTables(pScrn); +#endif +} - if (!info->IsSecondary) { - if (!RADEONAllocateConnectors(pScrn)) - return FALSE; +static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; - if (!RADEONAllocateControllers(pScrn)) + if (!RADEONAllocateControllers(pScrn)) return FALSE; - - } - RADEONGetBIOSInfo(pScrn, pInt10); + RADEONGetClockInfo(pScrn); - RADEONSetupConnectors(pScrn); - RADEONMapControllers(pScrn); + if (!RADEONSetupConnectors(pScrn)) { + return FALSE; + } + + RADEONPrintPortMap(pScrn); - RADEONGetClockInfo(pScrn); - RADEONGetPanelInfo(pScrn); - RADEONGetTVDacAdjInfo(pScrn); - + for (i = 0; i < config->num_output; i++) + { + xf86OutputPtr output = config->output[i]; + + output->status = (*output->funcs->detect) (output); + ErrorF("finished output detect: %d\n", i); + } + ErrorF("finished all detect\n"); return TRUE; } @@ -2971,24 +2487,36 @@ RADEONProbeDDC(ScrnInfoPtr pScrn, int indx) } } +static Bool +RADEONCRTCResize(ScrnInfoPtr scrn, int width, int height) +{ + scrn->virtualX = width; + scrn->virtualY = height; + /* RADEONSetPitch(scrn); */ + return TRUE; +} + +static const xf86CrtcConfigFuncsRec RADEONCRTCResizeFuncs = { + RADEONCRTCResize +}; + _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) { + xf86CrtcConfigPtr xf86_config; RADEONInfoPtr info; xf86Int10InfoPtr pInt10 = NULL; void *int10_save = NULL; const char *s; MessageType from; + int crtc_max_X, crtc_max_Y; - RADEONTRACE(("RADEONPreInit\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONPreInit\n"); if (pScrn->numEntities != 1) return FALSE; if (!RADEONGetRec(pScrn)) return FALSE; info = RADEONPTR(pScrn); - info->IsSecondary = FALSE; - info->IsPrimary = FALSE; - info->MergedFB = FALSE; - info->IsSwitching = FALSE; info->MMIO = NULL; info->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); @@ -3032,30 +2560,6 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) RADEONPreInt10Save(pScrn, &int10_save); #endif - if (xf86IsEntityShared(info->pEnt->index)) { - if (xf86IsPrimInitDone(info->pEnt->index)) { - - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - info->IsSecondary = TRUE; - if (!pRADEONEnt->HasSecondary) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Only one monitor detected, Second screen " - "will NOT be created\n"); - goto fail2; - } - pRADEONEnt->pSecondaryScrn = pScrn; - } else { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - info->IsPrimary = TRUE; - - xf86SetPrimInitDone(info->pEnt->index); - - pRADEONEnt->pPrimaryScrn = pScrn; - } - } - if (flags & PROBE_DETECT) { RADEONProbeDDC(pScrn, info->pEnt->index); RADEONPostInt10Check(pScrn, int10_save); @@ -3079,6 +2583,11 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR; pScrn->monitor = pScrn->confScreen->monitor; + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit (pScrn, &RADEONCRTCResizeFuncs); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + if (!RADEONPreInitVisual(pScrn)) goto fail; @@ -3153,63 +2662,94 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) "X server will %skeep DPI constant for all screen sizes\n", info->constantDPI ? "" : "not "); - if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) { - /* check for Linux framebuffer device */ - - if (xf86LoadSubModule(pScrn, "fbdevhw")) { - xf86LoaderReqSymLists(fbdevHWSymbols, NULL); - - if (fbdevHWInit(pScrn, info->PciInfo, NULL)) { - pScrn->ValidMode = fbdevHWValidModeWeak(); - info->FBDev = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Using framebuffer device\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "fbdevHWInit failed, not using framebuffer device\n"); - } - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Couldn't load fbdevhw module, not using framebuffer device\n"); - } - } - - if (!info->FBDev) - if (!RADEONPreInitInt10(pScrn, &pInt10)) - goto fail; + if (!RADEONPreInitInt10(pScrn, &pInt10)) + goto fail; RADEONPostInt10Check(pScrn, int10_save); if (!RADEONPreInitChipType(pScrn)) goto fail; + RADEONPreInitBIOS(pScrn, pInt10); + #ifdef XF86DRI /* PreInit DRI first of all since we need that for getting a proper * memory map */ info->directRenderingEnabled = RADEONPreInitDRI(pScrn); #endif - if (!RADEONPreInitVRAM(pScrn)) goto fail; RADEONPreInitColorTiling(pScrn); + /* we really need an FB manager... */ + if (pScrn->display->virtualX) { + crtc_max_X = pScrn->display->virtualX; + crtc_max_Y = pScrn->display->virtualY; + if (info->allowColorTiling) { + if (crtc_max_X > info->MaxSurfaceWidth) + crtc_max_X = info->MaxSurfaceWidth; + if (crtc_max_Y > info->MaxLines) + crtc_max_Y = info->MaxLines; + } else { + if (crtc_max_X > 8192) + crtc_max_X = 8192; + if (crtc_max_Y > 8192) + crtc_max_Y = 8192; + } + } else { + if (pScrn->videoRam < 16384) { + crtc_max_X = 1600; + crtc_max_Y = 1200; + } else if (pScrn->videoRam <= 32768) { + crtc_max_X = 2048; + crtc_max_Y = 1200; + } else if (pScrn->videoRam > 32768) { + if (IS_R300_VARIANT) { + crtc_max_X = 2560; + crtc_max_Y = 2048; + } else { + crtc_max_X = 2048; + crtc_max_Y = 2048; + } + } + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Max desktop size set to %dx%d\n", + crtc_max_X, crtc_max_Y); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "For a larger or smaller max desktop size, add a Virtual line to your xorg.conf\n"); + + /*xf86CrtcSetSizeRange (pScrn, 320, 200, info->MaxSurfaceWidth, info->MaxLines);*/ + xf86CrtcSetSizeRange (pScrn, 320, 200, crtc_max_X, crtc_max_Y); + RADEONPreInitDDC(pScrn); - if (!RADEONPreInitControllers(pScrn, pInt10)) + if (!RADEONPreInitControllers(pScrn)) goto fail; - /* collect MergedFB options */ - /* only parse mergedfb options on the primary head. - Mergedfb is already disabled in xinerama/screen based - multihead */ - if (!info->IsSecondary) - RADEONGetMergedFBOptions(pScrn); - if (!RADEONPreInitGamma(pScrn)) goto fail; + ErrorF("before xf86InitialConfiguration\n"); + + if (!xf86InitialConfiguration (pScrn, FALSE)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + goto fail; + } + + ErrorF("after xf86InitialConfiguration\n"); - if (!RADEONPreInitModes(pScrn, pInt10)) goto fail; + RADEONSetPitch(pScrn); + + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); + + /* Get ScreenInit function */ + if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; + + xf86LoaderReqSymLists(fbSymbols, NULL); + + if (!RADEONPreInitGamma(pScrn)) goto fail; if (!RADEONPreInitCursor(pScrn)) goto fail; @@ -3217,6 +2757,17 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) if (!RADEONPreInitXv(pScrn)) goto fail; + if (!xf86RandR12PreInit (pScrn)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); + goto fail; + } + + if (pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); + goto fail; + } + /* Free the video bios (if applicable) */ if (info->VBIOS) { xfree(info->VBIOS); @@ -3238,10 +2789,6 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) fail: /* Pre-init failed. */ - if (info->IsSecondary) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - pRADEONEnt->HasSecondary = FALSE; - } /* Free the video bios (if applicable) */ if (info->VBIOS) { xfree(info->VBIOS); @@ -3257,7 +2804,6 @@ fail: vgaHWFreeHWRec(pScrn); #endif - fail2: if(info->MMIO) RADEONUnmapMMIO(pScrn); info->MMIO = NULL; @@ -3272,10 +2818,11 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) { RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; - int idx, j; - unsigned char r, g, b; + int index, j; + CARD16 lut_r[256], lut_g[256], lut_b[256]; + int c; #ifdef XF86DRI if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); @@ -3284,112 +2831,60 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, if (info->accelOn && pScrn->pScreen) RADEON_SYNC(info, pScrn); - if (info->FBDev) { - fbdevHWLoadPalette(pScrn, numColors, indices, colors, pVisual); - } else { - /* If the second monitor is connected, we also need to deal with - * the secondary palette - */ - if (info->IsSecondary) j = 1; - else j = 0; - - PAL_SELECT(j); - - if (info->CurrentLayout.depth == 15) { - /* 15bpp mode. This sends 32 values. */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx].red; - g = colors[idx].green; - b = colors[idx].blue; - OUTPAL(idx * 8, r, g, b); - } - } else if (info->CurrentLayout.depth == 16) { - /* 16bpp mode. This sends 64 values. - * - * There are twice as many green values as there are values - * for red and blue. So, we take each red and blue pair, - * and combine it with each of the two green values. - */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx / 2].red; - g = colors[idx].green; - b = colors[idx / 2].blue; - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL(idx * 4, r, g, b); - - /* AH - Added to write extra green data - How come this isn't - * needed on R128? We didn't load the extra green data in the - * other routine - */ - if (idx <= 31) { - r = colors[idx].red; - g = colors[(idx * 2) + 1].green; - b = colors[idx].blue; - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL(idx * 8, r, g, b); - } - } - } else { - /* 8bpp mode. This sends 256 values. */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx].red; - b = colors[idx].blue; - g = colors[idx].green; - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL(idx, r, g, b); - } - } + { - if (info->MergedFB) { - PAL_SELECT(1); - if (info->CurrentLayout.depth == 15) { - /* 15bpp mode. This sends 32 values. */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx].red; - g = colors[idx].green; - b = colors[idx].blue; - OUTPAL(idx * 8, r, g, b); - } - } else if (info->CurrentLayout.depth == 16) { - /* 16bpp mode. This sends 64 values. - * - * There are twice as many green values as there are values - * for red and blue. So, we take each red and blue pair, - * and combine it with each of the two green values. - */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx / 2].red; - g = colors[idx].green; - b = colors[idx / 2].blue; - OUTPAL(idx * 4, r, g, b); - - /* AH - Added to write extra green data - How come - * this isn't needed on R128? We didn't load the - * extra green data in the other routine. - */ - if (idx <= 31) { - r = colors[idx].red; - g = colors[(idx * 2) + 1].green; - b = colors[idx].blue; - OUTPAL(idx * 8, r, g, b); - } - } - } else { - /* 8bpp mode. This sends 256 values. */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx].red; - b = colors[idx].blue; - g = colors[idx].green; - OUTPAL(idx, r, g, b); - } - } - } + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + for (i = 0 ; i < 256; i++) { + lut_r[i] = radeon_crtc->lut_r[i] << 8; + lut_g[i] = radeon_crtc->lut_g[i] << 8; + lut_b[i] = radeon_crtc->lut_b[i] << 8; + } + + switch (info->CurrentLayout.depth) { + case 15: + for (i = 0; i < numColors; i++) { + index = indices[i]; + for (j = 0; j < 8; j++) { + lut_r[index * 8 + j] = colors[index].red << 8; + lut_g[index * 8 + j] = colors[index].green << 8; + lut_b[index * 8 + j] = colors[index].blue << 8; + } + } + case 16: + for (i = 0; i < numColors; i++) { + index = indices[i]; + + if (i <= 31) { + for (j = 0; j < 8; j++) { + lut_r[index * 8 + j] = colors[index].red << 8; + lut_b[index * 8 + j] = colors[index].blue << 8; + } + } + + for (j = 0; j < 4; j++) { + lut_g[index * 4 + j] = colors[index].green << 8; + } + } + default: + for (i = 0; i < numColors; i++) { + index = indices[i]; + lut_r[index] = colors[index].red << 8; + lut_g[index] = colors[index].green << 8; + lut_b[index] = colors[index].blue << 8; + } + break; + } + + /* Make the change through RandR */ +#ifdef RANDR_12_INTERFACE + RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); +#else + crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); +#endif + } } #ifdef XF86DRI @@ -3404,14 +2899,6 @@ static void RADEONBlockHandler(int i, pointer blockData, ScrnInfoPtr pScrn = xf86Screens[i]; RADEONInfoPtr info = RADEONPTR(pScrn); -#ifdef XF86DRI - if (info->directRenderingInited) { - FLUSH_RING(); - } -#endif -#ifdef USE_EXA - info->engineMode = EXA_ENGINEMODE_UNKNOWN; -#endif pScreen->BlockHandler = info->BlockHandler; (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); pScreen->BlockHandler = RADEONBlockHandler; @@ -3423,6 +2910,10 @@ static void RADEONBlockHandler(int i, pointer blockData, if(info->RenderCallback) (*info->RenderCallback)(pScrn); #endif + +#ifdef USE_EXA + info->engineMode = EXA_ENGINEMODE_UNKNOWN; +#endif } @@ -3682,8 +3173,8 @@ Bool RADEONSetupMemXAA_DRI(int scrnIndex, ScreenPtr pScreen) info->depthOffset); if (info->cardType==CARD_PCIE) xf86DrvMsg(scrnIndex, X_INFO, - "Will use %d kb for PCI GART table at offset 0x%lx\n", - info->pciGartSize/1024, info->pciGartOffset); + "Will use %d kb for PCI GART table at offset 0x%x\n", + info->pciGartSize/1024, (unsigned)info->pciGartOffset); xf86DrvMsg(scrnIndex, X_INFO, "Will use %d kb for textures at offset 0x%x\n", info->textureSize/1024, info->textureOffset); @@ -3762,27 +3253,65 @@ Bool RADEONSetupMemXAA(int scrnIndex, ScreenPtr pScreen) } #endif /* USE_XAA */ +static void +RADEONPointerMoved(int index, int x, int y) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + RADEONInfoPtr info = RADEONPTR(pScrn); + int newX = x, newY = y; + + switch (info->rotation) { + case RR_Rotate_0: + break; + case RR_Rotate_90: + newX = y; + newY = pScrn->pScreen->width - x - 1; + break; + case RR_Rotate_180: + newX = pScrn->pScreen->width - x - 1; + newY = pScrn->pScreen->height - y - 1; + break; + case RR_Rotate_270: + newX = pScrn->pScreen->height - y - 1; + newY = x; + break; + } + + (*info->PointerMoved)(index, newX, newY); +} + /* Called at the start of each server generation. */ -_X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, +Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int hasDRI = 0; + int i; #ifdef RENDER int subPixelOrder = SubPixelUnknown; char* s; #endif - RADEONTRACE(("RADEONScreenInit %lx %ld %d\n", - pScrn->memPhysBase, pScrn->fbOffset, info->frontOffset)); +#ifdef XF86DRI + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONScreenInit %lx %ld %d\n", + pScrn->memPhysBase, pScrn->fbOffset, info->frontOffset); +#else + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONScreenInit %lx %ld\n", + pScrn->memPhysBase, pScrn->fbOffset); +#endif info->accelOn = FALSE; #ifdef USE_XAA info->accel = NULL; #endif +#ifdef XF86DRI pScrn->fbOffset = info->frontOffset; - if (info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024; +#endif + if (!RADEONMapMem(pScrn)) return FALSE; #ifdef XF86DRI @@ -3792,9 +3321,14 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->PaletteSavedOnVT = FALSE; + info->crtc_on = FALSE; + info->crtc2_on = FALSE; + RADEONSave(pScrn); - if ((!info->IsSecondary) && info->IsMobility) { + RADEONDisableDisplays(pScrn); + + if (info->IsMobility) { if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { RADEONSetDynamicClock(pScrn, 1); } else { @@ -3802,8 +3336,8 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } - if ((!info->IsSecondary) && (IS_R300_VARIANT || IS_RV100_VARIANT)) - RADEONForceSomeClocks(pScrn); + if (IS_R300_VARIANT || IS_RV100_VARIANT) + RADEONForceSomeClocks(pScrn); if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -3812,17 +3346,7 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->allowColorTiling = FALSE; } if (info->allowColorTiling) { - if (info->MergedFB) { - if ((((RADEONMergedDisplayModePtr)pScrn->currentMode->Private)->CRT1->Flags & - (V_DBLSCAN | V_INTERLACE)) || - (((RADEONMergedDisplayModePtr)pScrn->currentMode->Private)->CRT2->Flags & - (V_DBLSCAN | V_INTERLACE))) - info->tilingEnabled = FALSE; - else info->tilingEnabled = TRUE; - } - else { - info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; - } + info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; } /* Visual setup */ @@ -3863,15 +3387,13 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, */ RADEONInitMemoryMap(pScrn); - if (!info->IsSecondary) { - /* empty the surfaces */ - unsigned char *RADEONMMIO = info->MMIO; - unsigned int i; - for (i = 0; i < 8; i++) { - OUTREG(RADEON_SURFACE0_INFO + 16 * i, 0); - OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * i, 0); - OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * i, 0); - } + /* empty the surfaces */ + unsigned char *RADEONMMIO = info->MMIO; + unsigned int j; + for (j = 0; j < 8; j++) { + OUTREG(RADEON_SURFACE0_INFO + 16 * j, 0); + OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * j, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * j, 0); } #ifdef XF86DRI @@ -3891,14 +3413,14 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, #endif /* Initial setup of surfaces */ - if (!info->IsSecondary) { - RADEONTRACE(("Setting up initial surfaces\n")); - RADEONChangeSurfaces(pScrn); - } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Setting up initial surfaces\n"); + RADEONChangeSurfaces(pScrn); /* Memory manager setup */ - RADEONTRACE(("Setting up accel memmap\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Setting up accel memmap\n"); #ifdef USE_EXA if (info->useEXA) { @@ -3969,6 +3491,7 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, /* Setup DRI after visuals have been established, but before fbScreenInit is * called. fbScreenInit will eventually call the driver's InitGLXVisuals * call back. */ +#ifdef XF86DRI if (info->directRenderingEnabled) { /* FIXME: When we move to dynamic allocation of back and depth * buffers, we will want to revisit the following check for 3 @@ -3992,7 +3515,6 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } -#if defined(XF86DRI) /* Tell DRI about new memory map */ if (info->directRenderingEnabled && info->newMemoryMap) { if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) { @@ -4003,7 +3525,8 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } #endif - RADEONTRACE(("Initializing fb layer\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing fb layer\n"); /* Init fb layer */ if (!fbScreenInit(pScreen, info->FB + pScrn->fbOffset, @@ -4040,38 +3563,34 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, else if (strcmp(s, "NONE") == 0) subPixelOrder = SubPixelNone; PictureSetSubpixelOrder (pScreen, subPixelOrder); } +#endif - if (PictureGetSubpixelOrder (pScreen) == SubPixelUnknown) { - switch (info->DisplayType) { - case MT_NONE: subPixelOrder = SubPixelUnknown; break; - case MT_LCD: subPixelOrder = SubPixelHorizontalRGB; break; - case MT_DFP: subPixelOrder = SubPixelHorizontalRGB; break; - default: subPixelOrder = SubPixelNone; break; + pScrn->vtSema = TRUE; + + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + /* Mark that we'll need to re-set the mode for sure */ + memset(&crtc->mode, 0, sizeof(crtc->mode)); + if (!crtc->desiredMode.CrtcHDisplay) { + crtc->desiredMode = *RADEONCrtcFindClosestMode (crtc, pScrn->currentMode); + crtc->desiredRotation = RR_Rotate_0; + crtc->desiredX = 0; + crtc->desiredY = 0; } - PictureSetSubpixelOrder (pScreen, subPixelOrder); - } -#endif - if (info->FBDev) { - unsigned char *RADEONMMIO = info->MMIO; + if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation, crtc->desiredX, crtc->desiredY)) + return FALSE; - if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; - pScrn->displayWidth = fbdevHWGetLineLength(pScrn) - / info->CurrentLayout.pixel_bytes; - RADEONSaveMemMapRegisters(pScrn, &info->ModeReg); - info->fbLocation = (info->ModeReg.mc_fb_location & 0xffff) << 16; - info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); - info->ModeReg.surface_cntl &= ~RADEON_SURF_TRANSLATION_DIS; - } else { - if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; } RADEONSaveScreen(pScreen, SCREEN_SAVER_ON); - pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + // pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); /* Backing store setup */ - RADEONTRACE(("Initializing backing store\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing backing store\n"); miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); @@ -4091,7 +3610,8 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } if (info->directRenderingEnabled) { - RADEONTRACE(("DRI Finishing init !\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "DRI Finishing init !\n"); info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen); } if (info->directRenderingEnabled) { @@ -4120,18 +3640,15 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, #endif /* Make sure surfaces are allright since DRI setup may have changed them */ - if (!info->IsSecondary) { - RADEONTRACE(("Setting up final surfaces\n")); - RADEONChangeSurfaces(pScrn); - } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Setting up final surfaces\n"); - if(info->MergedFB) - /* need this here to fix up sarea values */ - RADEONAdjustFrameMerged(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + RADEONChangeSurfaces(pScrn); /* Enable aceleration */ if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { - RADEONTRACE(("Initializing Acceleration\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing Acceleration\n"); if (RADEONAccelInit(pScreen)) { xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n"); info->accelOn = TRUE; @@ -4147,10 +3664,12 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } /* Init DPMS */ - RADEONTRACE(("Initializing DPMS\n")); - xf86DPMSInit(pScreen, RADEONDisplayPowerManagementSet, 0); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing DPMS\n"); + xf86DPMSInit(pScreen, xf86DPMSSet, 0); - RADEONTRACE(("Initializing Cursor\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing Cursor\n"); /* Set Silken Mouse */ xf86SetSilkenMouse(pScreen); @@ -4166,9 +3685,9 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int width, height; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using hardware cursor (scanline %ld)\n", - info->cursor_offset / pScrn->displayWidth - / info->CurrentLayout.pixel_bytes); + "Using hardware cursor (scanline %u)\n", + (unsigned)(info->cursor_offset / pScrn->displayWidth + / info->CurrentLayout.pixel_bytes)); if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0)) { xf86DrvMsg(scrnIndex, X_INFO, @@ -4187,42 +3706,16 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n"); } - /* Colormap setup */ - RADEONTRACE(("Initializing color map\n")); - if (!miCreateDefColormap(pScreen)) return FALSE; - if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8, - RADEONLoadPalette, NULL, - CMAP_PALETTED_TRUECOLOR -#if 0 /* This option messes up text mode! (eich@suse.de) */ - | CMAP_LOAD_EVEN_IF_OFFSCREEN -#endif - | CMAP_RELOAD_ON_MODE_SWITCH)) return FALSE; - /* DGA setup */ - RADEONTRACE(("Initializing DGA\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing DGA\n"); RADEONDGAInit(pScreen); - /* Wrap some funcs for MergedFB */ - if(info->MergedFB) { - info->PointerMoved = pScrn->PointerMoved; - pScrn->PointerMoved = RADEONMergePointerMoved; - /* Psuedo xinerama */ - if(info->UseRADEONXinerama) { - RADEONnoPanoramiXExtension = FALSE; - RADEONXineramaExtensionInit(pScrn); - } else { - info->MouseRestrictions = FALSE; - } - } - /* Init Xv */ - RADEONTRACE(("Initializing Xv\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing Xv\n"); RADEONInitVideo(pScreen); - if(info->MergedFB) - /* need this here to fix up sarea values */ - RADEONAdjustFrameMerged(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - /* Provide SaveScreen & wrap BlockHandler and CloseScreen */ /* Wrap CloseScreen */ info->CloseScreen = pScreen->CloseScreen; @@ -4231,17 +3724,37 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = RADEONBlockHandler; + if (!xf86CrtcScreenInit (pScreen)) + return FALSE; + + /* Wrap pointer motion to flip touch screen around */ + info->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = RADEONPointerMoved; + + /* Colormap setup */ + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing color map\n"); + if (!miCreateDefColormap(pScreen)) return FALSE; + if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8, + RADEONLoadPalette, NULL, + CMAP_PALETTED_TRUECOLOR +#if 0 /* This option messes up text mode! (eich@suse.de) */ + | CMAP_LOAD_EVEN_IF_OFFSCREEN +#endif + | CMAP_RELOAD_ON_MODE_SWITCH)) return FALSE; + /* Note unused options */ if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); - RADEONTRACE(("RADEONScreenInit finished\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONScreenInit finished\n"); return TRUE; } /* Write memory mapping registers */ -static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, +void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -4249,9 +3762,14 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, unsigned char *RADEONMMIO = info->MMIO; int timeout; - RADEONTRACE(("RADEONRestoreMemMapRegisters() : \n")); - RADEONTRACE((" MC_FB_LOCATION : 0x%08lx\n", restore->mc_fb_location)); - RADEONTRACE((" MC_AGP_LOCATION : 0x%08lx\n", restore->mc_agp_location)); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "RADEONRestoreMemMapRegisters() : \n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " MC_FB_LOCATION : 0x%08x\n", + (unsigned)restore->mc_fb_location); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " MC_AGP_LOCATION : 0x%08x\n", + (unsigned)restore->mc_agp_location); /* Write memory mapping registers only if their value change * since we must ensure no access is done while they are @@ -4262,7 +3780,8 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, CARD32 crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl=0, ov0_scale_cntl; CARD32 old_mc_status, status_idle; - RADEONTRACE((" Map Changed ! Applying ...\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + " Map Changed ! Applying ...\n"); /* Make sure engine is idle. We assume the CCE is stopped * at this point @@ -4335,7 +3854,8 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, /* Make sure map fully reached the chip */ (void)INREG(RADEON_MC_FB_LOCATION); - RADEONTRACE((" Map applied, resetting engine ...\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + " Map applied, resetting engine ...\n"); /* Reset the engine and HDP */ RADEONEngineReset(pScrn); @@ -4372,7 +3892,8 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, } } - RADEONTRACE(("Updating display base addresses...\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Updating display base addresses...\n"); OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->display_base_addr); if (pRADEONEnt->HasCRTC2) @@ -4383,7 +3904,8 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, /* More paranoia delays, wait 100ms */ usleep(100000); - RADEONTRACE(("Memory map updated.\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Memory map updated.\n"); } #ifdef XF86DRI @@ -4392,21 +3914,19 @@ static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 fb, agp; - int fb_loc_changed; fb = INREG(RADEON_MC_FB_LOCATION); agp = INREG(RADEON_MC_AGP_LOCATION); - fb_loc_changed = (fb != info->mc_fb_location); - if (fb_loc_changed || agp != info->mc_agp_location) { + if (fb != info->mc_fb_location || agp != info->mc_agp_location) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI init changed memory map, adjusting ...\n"); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - " MC_FB_LOCATION was: 0x%08lx is: 0x%08lx\n", - info->mc_fb_location, fb); + " MC_FB_LOCATION was: 0x%08x is: 0x%08x\n", + (unsigned)info->mc_fb_location, (unsigned)fb); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - " MC_AGP_LOCATION was: 0x%08lx is: 0x%08lx\n", - info->mc_agp_location, agp); + " MC_AGP_LOCATION was: 0x%08x is: 0x%08x\n", + (unsigned)info->mc_agp_location, (unsigned)agp); info->mc_fb_location = fb; info->mc_agp_location = agp; info->fbLocation = (save->mc_fb_location & 0xffff) << 16; @@ -4417,9 +3937,8 @@ static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) RADEONInitMemMapRegisters(pScrn, save, info); - /* If MC_FB_LOCATION was changed, adjust the various offsets */ - if (fb_loc_changed) - RADEONRestoreMemMapRegisters(pScrn, save); + /* Adjust the various offsets */ + RADEONRestoreMemMapRegisters(pScrn, save); } #ifdef USE_EXA @@ -4447,7 +3966,7 @@ static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) #endif /* Write common registers */ -static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, +void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -4472,55 +3991,62 @@ static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, * CRT are connected. */ if (pRADEONEnt->HasCRTC2 && - !info->IsSwitching && info->ChipFamily != CHIP_FAMILY_R200 && !IS_R300_VARIANT) { CARD32 tmp; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - if (pRADEONEnt->HasSecondary || info->MergedFB) { - tmp = INREG(RADEON_DAC_CNTL2); - OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL); - usleep(100000); - } + tmp = INREG(RADEON_DAC_CNTL2); + OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL); + usleep(100000); } } -/* Write miscellaneous registers which might have been destroyed by an fbdevHW - * call - */ -static void RADEONRestoreFBDevRegisters(ScrnInfoPtr pScrn, - RADEONSavePtr restore) +void RADEONRestoreDACRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore) { -#ifdef XF86DRI RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; - /* Restore register for vertical blank interrupts */ - if (info->irq) { - OUTREG(RADEON_GEN_INT_CNTL, restore->gen_int_cntl); - } + if (IS_R300_VARIANT) + OUTREGP(RADEON_GPIOPAD_A, restore->gpiopad_a, ~1); - /* Restore registers for page flipping */ - if (info->allowPageFlip) { - OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); - if (pRADEONEnt->HasCRTC2) { - OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); - } + OUTREGP(RADEON_DAC_CNTL, + restore->dac_cntl, + RADEON_DAC_RANGE_CNTL | + RADEON_DAC_BLANKING); + + OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); + + if ((info->ChipFamily != CHIP_FAMILY_RADEON) && + (info->ChipFamily != CHIP_FAMILY_R200)) + OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); + + OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); + + if ((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) { + OUTREG(RADEON_DISP_TV_OUT_CNTL, restore->disp_tv_out_cntl); + } else { + OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); } -#endif + + OUTREG(RADEON_DAC_MACRO_CNTL, restore->dac_macro_cntl); + + /* R200 DAC connected via DVO */ + if (info->ChipFamily == CHIP_FAMILY_R200) + OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); } /* Write CRTC registers */ -static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, +void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - RADEONTRACE(("Programming CRTC1, offset: 0x%08lx\n", - restore->crtc_offset)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Programming CRTC1, offset: 0x%08x\n", + (unsigned)restore->crtc_offset); /* We prevent the CRTC from hitting the memory controller until * fully programmed @@ -4534,11 +4060,6 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_DISPLAY_DIS); - OUTREGP(RADEON_DAC_CNTL, - restore->dac_cntl, - RADEON_DAC_RANGE_CNTL | - RADEON_DAC_BLANKING); - OUTREG(RADEON_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); OUTREG(RADEON_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); OUTREG(RADEON_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); @@ -4549,8 +4070,11 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, OUTREG(RADEON_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp); OUTREG(RADEON_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp); - OUTREG(RADEON_CRTC_OFFSET, restore->crtc_offset); + if (IS_R300_VARIANT) + OUTREG(R300_CRTC_TILE_X0_Y0, restore->crtc_tile_x0_y0); OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); + OUTREG(RADEON_CRTC_OFFSET, restore->crtc_offset); + OUTREG(RADEON_CRTC_PITCH, restore->crtc_pitch); OUTREG(RADEON_DISP_MERGE_CNTL, restore->disp_merge_cntl); OUTREG(RADEON_CRTC_MORE_CNTL, restore->crtc_more_cntl); @@ -4566,42 +4090,24 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, } /* Write CRTC2 registers */ -static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, +void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - CARD32 crtc2_gen_cntl; + /* CARD32 crtc2_gen_cntl;*/ - RADEONTRACE(("Programming CRTC2, offset: 0x%08lx\n", - restore->crtc2_offset)); - - crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL) & - (RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS | - RADEON_CRTC2_DISP_DIS); - crtc2_gen_cntl |= restore->crtc2_gen_cntl; + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Programming CRTC2, offset: 0x%08x\n", + (unsigned)restore->crtc2_offset); /* We prevent the CRTC from hitting the memory controller until * fully programmed */ OUTREG(RADEON_CRTC2_GEN_CNTL, - crtc2_gen_cntl | RADEON_CRTC2_DISP_REQ_EN_B); - - OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); - - //OUTREG(RADEON_TV_DAC_CNTL, 0x00280203); - if ((info->ChipFamily != CHIP_FAMILY_RADEON) && - (info->ChipFamily != CHIP_FAMILY_R200)) - OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); - - if ((info->ChipFamily == CHIP_FAMILY_R200) || - IS_R300_VARIANT) { - OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); - OUTREG(RADEON_DISP_TV_OUT_CNTL, restore->disp_tv_out_cntl); - } else { - OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); - } + restore->crtc2_gen_cntl | RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_DISP_REQ_EN_B); OUTREG(RADEON_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); @@ -4611,17 +4117,26 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp_h2_sync_strt_wid); OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp_v2_sync_strt_wid); - OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset); + if (IS_R300_VARIANT) + OUTREG(R300_CRTC2_TILE_X0_Y0, restore->crtc2_tile_x0_y0); OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); + OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset); + OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch); OUTREG(RADEON_DISP2_MERGE_CNTL, restore->disp2_merge_cntl); - OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + if (info->ChipFamily == CHIP_FAMILY_RS400) { + OUTREG(RADEON_RS480_UNK_e30, restore->rs480_unk_e30); + OUTREG(RADEON_RS480_UNK_e34, restore->rs480_unk_e34); + OUTREG(RADEON_RS480_UNK_e38, restore->rs480_unk_e38); + OUTREG(RADEON_RS480_UNK_e3c, restore->rs480_unk_e3c); + } + OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); } -/* Write flat panel registers */ -static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +/* Write TMDS registers */ +void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); @@ -4629,8 +4144,6 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) OUTREG(RADEON_TMDS_PLL_CNTL, restore->tmds_pll_cntl); OUTREG(RADEON_TMDS_TRANSMITTER_CNTL,restore->tmds_transmitter_cntl); - OUTREG(RADEON_FP_HORZ_STRETCH, restore->fp_horz_stretch); - OUTREG(RADEON_FP_VERT_STRETCH, restore->fp_vert_stretch); OUTREG(RADEON_FP_GEN_CNTL, restore->fp_gen_cntl); /* old AIW Radeon has some BIOS initialization problem @@ -4640,7 +4153,38 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) OUTREG(RADEON_GRPH_BUFFER_CNTL, INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000); +} + +/* Write FP2 registers */ +void RADEONRestoreFP2Registers(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); + +} + +/* Write RMX registers */ +void RADEONRestoreRMXRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG(RADEON_FP_HORZ_STRETCH, restore->fp_horz_stretch); + OUTREG(RADEON_FP_VERT_STRETCH, restore->fp_vert_stretch); + +} + +/* Write LVDS registers */ +void RADEONRestoreLVDSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + if (info->IsMobility) { + OUTREG(RADEON_LVDS_GEN_CNTL, restore->lvds_gen_cntl); + /*OUTREG(RADEON_LVDS_PLL_CNTL, restore->lvds_pll_cntl);*/ OUTREG(RADEON_BIOS_4_SCRATCH, restore->bios_4_scratch); OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch); OUTREG(RADEON_BIOS_6_SCRATCH, restore->bios_6_scratch); @@ -4648,6 +4192,262 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) } +/* Write to TV FIFO RAM */ +static void RADEONWriteTVFIFO(ScrnInfoPtr pScrn, CARD16 addr, + CARD32 value) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp; + int i = 0; + + OUTREG(RADEON_TV_HOST_WRITE_DATA, value); + + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr); + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT); + + do { + tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL); + if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0) + break; + i++; + } + while (i < 10000); + /*while ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0);*/ + + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0); +} + +/* Read from TV FIFO RAM */ +static CARD32 RADEONReadTVFIFO(ScrnInfoPtr pScrn, CARD16 addr) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp; + int i = 0; + + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr); + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD); + + do { + tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL); + if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0) + break; + i++; + } + while (i < 10000); + /*while ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0);*/ + + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0); + + return INREG(RADEON_TV_HOST_READ_DATA); +} + +/* Get FIFO addresses of horizontal & vertical code timing tables from + * settings of uv_adr register. + */ +static CARD16 RADEONGetHTimingTablesAddr(CARD32 tv_uv_adr) +{ + CARD16 hTable; + + switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) { + case 0: + hTable = RADEON_TV_MAX_FIFO_ADDR_INTERNAL; + break; + case 1: + hTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2; + break; + case 2: + hTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2; + break; + default: + /* Of course, this should never happen */ + hTable = 0; + break; + } + return hTable; +} + +static CARD16 RADEONGetVTimingTablesAddr(CARD32 tv_uv_adr) +{ + CARD16 vTable; + + switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) { + case 0: + vTable = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1; + break; + case 1: + vTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1; + break; + case 2: + vTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1; + break; + default: + /* Of course, this should never happen */ + vTable = 0; + break; + } + return vTable; +} + +/* Restore horizontal/vertical timing code tables */ +void RADEONRestoreTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD16 hTable; + CARD16 vTable; + CARD32 tmp; + unsigned i; + + OUTREG(RADEON_TV_UV_ADR, restore->tv_uv_adr); + hTable = RADEONGetHTimingTablesAddr(restore->tv_uv_adr); + vTable = RADEONGetVTimingTablesAddr(restore->tv_uv_adr); + + for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, hTable--) { + tmp = ((CARD32)restore->h_code_timing[ i ] << 14) | ((CARD32)restore->h_code_timing[ i + 1 ]); + RADEONWriteTVFIFO(pScrn, hTable, tmp); + if (restore->h_code_timing[ i ] == 0 || restore->h_code_timing[ i + 1 ] == 0) + break; + } + + for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, vTable++) { + tmp = ((CARD32)restore->v_code_timing[ i + 1 ] << 14) | ((CARD32)restore->v_code_timing[ i ]); + RADEONWriteTVFIFO(pScrn, vTable, tmp); + if (restore->v_code_timing[ i ] == 0 || restore->v_code_timing[ i + 1 ] == 0) + break; + } +} + +/* restore TV PLLs */ +static void RADEONRestoreTVPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL); + OUTPLL(pScrn, RADEON_TV_PLL_CNTL, restore->tv_pll_cntl); + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET); + + RADEONWaitPLLLock(pScrn, 200, 800, 135); + + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET); + + RADEONWaitPLLLock(pScrn, 300, 160, 27); + RADEONWaitPLLLock(pScrn, 200, 800, 135); + + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~0xf); + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL); + + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK); + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP); +} + +/* Restore TV horizontal/vertical settings */ +static void RADEONRestoreTVHVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG(RADEON_TV_RGB_CNTL, restore->tv_rgb_cntl); + + OUTREG(RADEON_TV_HTOTAL, restore->tv_htotal); + OUTREG(RADEON_TV_HDISP, restore->tv_hdisp); + OUTREG(RADEON_TV_HSTART, restore->tv_hstart); + + OUTREG(RADEON_TV_VTOTAL, restore->tv_vtotal); + OUTREG(RADEON_TV_VDISP, restore->tv_vdisp); + + OUTREG(RADEON_TV_FTOTAL, restore->tv_ftotal); + + OUTREG(RADEON_TV_VSCALER_CNTL1, restore->tv_vscaler_cntl1); + OUTREG(RADEON_TV_VSCALER_CNTL2, restore->tv_vscaler_cntl2); + + OUTREG(RADEON_TV_Y_FALL_CNTL, restore->tv_y_fall_cntl); + OUTREG(RADEON_TV_Y_RISE_CNTL, restore->tv_y_rise_cntl); + OUTREG(RADEON_TV_Y_SAW_TOOTH_CNTL, restore->tv_y_saw_tooth_cntl); +} + +/* restore TV RESTART registers */ +void RADEONRestoreTVRestarts(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG(RADEON_TV_FRESTART, restore->tv_frestart); + OUTREG(RADEON_TV_HRESTART, restore->tv_hrestart); + OUTREG(RADEON_TV_VRESTART, restore->tv_vrestart); +} + +/* restore tv standard & output muxes */ +static void RADEONRestoreTVOutputStd(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG(RADEON_TV_SYNC_CNTL, restore->tv_sync_cntl); + + OUTREG(RADEON_TV_TIMING_CNTL, restore->tv_timing_cntl); + + OUTREG(RADEON_TV_MODULATOR_CNTL1, restore->tv_modulator_cntl1); + OUTREG(RADEON_TV_MODULATOR_CNTL2, restore->tv_modulator_cntl2); + + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, restore->tv_pre_dac_mux_cntl); + + OUTREG(RADEON_TV_CRC_CNTL, restore->tv_crc_cntl); +} + +/* Restore TV out regs */ +void RADEONRestoreTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + ErrorF("Entering Restore TV\n"); + + OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl + | RADEON_TV_ASYNC_RST + | RADEON_CRT_ASYNC_RST + | RADEON_TV_FIFO_ASYNC_RST)); + + /* Temporarily turn the TV DAC off */ + OUTREG(RADEON_TV_DAC_CNTL, ((restore->tv_dac_cntl & ~RADEON_TV_DAC_NBLANK) + | RADEON_TV_DAC_BGSLEEP + | RADEON_TV_DAC_RDACPD + | RADEON_TV_DAC_GDACPD + | RADEON_TV_DAC_BDACPD)); + + ErrorF("Restore TV PLL\n"); + RADEONRestoreTVPLLRegisters(pScrn, restore); + + ErrorF("Restore TVHV\n"); + RADEONRestoreTVHVRegisters(pScrn, restore); + + OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl + | RADEON_TV_ASYNC_RST + | RADEON_CRT_ASYNC_RST)); + + ErrorF("Restore TV Restarts\n"); + RADEONRestoreTVRestarts(pScrn, restore); + + ErrorF("Restore Timing Tables\n"); + RADEONRestoreTVTimingTables(pScrn, restore); + + + OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl + | RADEON_TV_ASYNC_RST)); + + ErrorF("Restore TV standard\n"); + RADEONRestoreTVOutputStd(pScrn, restore); + + OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl); + + OUTREG(RADEON_TV_GAIN_LIMIT_SETTINGS, restore->tv_gain_limit_settings); + OUTREG(RADEON_TV_LINEAR_GAIN_SETTINGS, restore->tv_linear_gain_settings); + + OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); + + ErrorF("Leaving Restore TV\n"); +} + static void RADEONPLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn) { int i = 0; @@ -4694,12 +4494,81 @@ static void RADEONPLL2WriteUpdate(ScrnInfoPtr pScrn) ~(RADEON_P2PLL_ATOMIC_UPDATE_W)); } +static CARD8 RADEONComputePLLGain(CARD16 reference_freq, CARD16 ref_div, + CARD16 fb_div) +{ + unsigned vcoFreq; + + if (!ref_div) + return 1; + + vcoFreq = ((unsigned)reference_freq * fb_div) / ref_div; + + /* + * This is horribly crude: the VCO frequency range is divided into + * 3 parts, each part having a fixed PLL gain value. + */ + if (vcoFreq >= 30000) + /* + * [300..max] MHz : 7 + */ + return 7; + else if (vcoFreq >= 18000) + /* + * [180..300) MHz : 4 + */ + return 4; + else + /* + * [0..180) MHz : 1 + */ + return 1; +} + +/* Wait for PLLs to lock */ +static void RADEONWaitPLLLock(ScrnInfoPtr pScrn, unsigned nTests, + unsigned nWaitLoops, unsigned cntThreshold) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 savePLLTest; + unsigned i; + unsigned j; + + OUTREG(RADEON_TEST_DEBUG_MUX, (INREG(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100); + + savePLLTest = INPLL(pScrn, RADEON_PLL_TEST_CNTL); + + OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest & ~RADEON_PLL_MASK_READ_B); + + /* XXX: these should probably be OUTPLL to avoid various PLL errata */ + + OUTREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL); + + for (i = 0; i < nTests; i++) { + OUTREG8(RADEON_CLOCK_CNTL_DATA + 3, 0); + + for (j = 0; j < nWaitLoops; j++) + if (INREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cntThreshold) + break; + } + + OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest); + + OUTREG(RADEON_TEST_DEBUG_MUX, INREG(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff); +} + /* Write PLL registers */ -static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, - RADEONSavePtr restore) +void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + CARD8 pllGain; + + pllGain = RADEONComputePLLGain(info->pll.reference_freq, + restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, + restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK); if (info->IsMobility) { /* A temporal workaround for the occational blanking on certain laptop panels. @@ -4727,10 +4596,12 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, RADEON_PPLL_CNTL, RADEON_PPLL_RESET | RADEON_PPLL_ATOMIC_UPDATE_EN - | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN, + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN + | ((CARD32)pllGain << RADEON_PPLL_PVG_SHIFT), ~(RADEON_PPLL_RESET | RADEON_PPLL_ATOMIC_UPDATE_EN - | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN + | RADEON_PPLL_PVG_MASK)); OUTREGP(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_DIV_SEL, @@ -4738,7 +4609,8 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, RADEONPllErrataAfterIndex(info); if (IS_R300_VARIANT || - (info->ChipFamily == CHIP_FAMILY_RS300)) { + (info->ChipFamily == CHIP_FAMILY_RS300) || + (info->ChipFamily == CHIP_FAMILY_RS400)) { if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { /* When restoring console mode, use saved PPLL_REF_DIV * setting. @@ -4778,28 +4650,42 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, | RADEON_PPLL_ATOMIC_UPDATE_EN | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); - RADEONTRACE(("Wrote: 0x%08x 0x%08x 0x%08lx (0x%08x)\n", - restore->ppll_ref_div, - restore->ppll_div_3, - restore->htotal_cntl, - INPLL(pScrn, RADEON_PPLL_CNTL))); - RADEONTRACE(("Wrote: rd=%d, fd=%d, pd=%d\n", - restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, - restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, - (restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + restore->ppll_ref_div, + restore->ppll_div_3, + (unsigned)restore->htotal_cntl, + INPLL(pScrn, RADEON_PPLL_CNTL)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Wrote: rd=%d, fd=%d, pd=%d\n", + restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, + restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, + (restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16); usleep(50000); /* Let the clock to lock */ - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, + /* OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, RADEON_VCLK_SRC_SEL_PPLLCLK, - ~(RADEON_VCLK_SRC_SEL_MASK)); + ~(RADEON_VCLK_SRC_SEL_MASK));*/ + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, restore->vclk_ecp_cntl); + + ErrorF("finished PLL1\n"); + } /* Write PLL2 registers */ -static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, - RADEONSavePtr restore) +void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, + RADEONSavePtr restore) { + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD8 pllGain; + + pllGain = RADEONComputePLLGain(info->pll.reference_freq, + restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, + restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK); + + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, RADEON_PIX2CLK_SRC_SEL_CPUCLK, ~(RADEON_PIX2CLK_SRC_SEL_MASK)); @@ -4808,10 +4694,11 @@ static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, RADEON_P2PLL_CNTL, RADEON_P2PLL_RESET | RADEON_P2PLL_ATOMIC_UPDATE_EN - | RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN, + | ((CARD32)pllGain << RADEON_P2PLL_PVG_SHIFT), ~(RADEON_P2PLL_RESET | RADEON_P2PLL_ATOMIC_UPDATE_EN - | RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN)); + | RADEON_P2PLL_PVG_MASK)); + OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV, restore->p2pll_ref_div, @@ -4834,24 +4721,30 @@ static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, 0, ~(RADEON_P2PLL_RESET | RADEON_P2PLL_SLEEP - | RADEON_P2PLL_ATOMIC_UPDATE_EN - | RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN)); - - RADEONTRACE(("Wrote: 0x%08lx 0x%08lx 0x%08lx (0x%08x)\n", - restore->p2pll_ref_div, - restore->p2pll_div_0, - restore->htotal_cntl2, - INPLL(pScrn, RADEON_P2PLL_CNTL))); - RADEONTRACE(("Wrote: rd=%ld, fd=%ld, pd=%ld\n", - restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, - restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, - (restore->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) >>16)); + | RADEON_P2PLL_ATOMIC_UPDATE_EN)); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + (unsigned)restore->p2pll_ref_div, + (unsigned)restore->p2pll_div_0, + (unsigned)restore->htotal_cntl2, + INPLL(pScrn, RADEON_P2PLL_CNTL)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Wrote2: rd=%u, fd=%u, pd=%u\n", + (unsigned)restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, + (unsigned)restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, + (unsigned)((restore->p2pll_div_0 & + RADEON_P2PLL_POST0_DIV_MASK) >>16)); usleep(5000); /* Let the clock to lock */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, + /*OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, - ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + ~(RADEON_PIX2CLK_SRC_SEL_MASK));*/ + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl); + + ErrorF("finished PLL2\n"); + } @@ -5018,156 +4911,24 @@ void RADEONChangeSurfaces(ScrnInfoPtr pScrn) unsigned int surf_info = swap_pattern; unsigned char *RADEONMMIO = info->MMIO; /* we don't need anything like WaitForFifo, no? */ - if (!info->IsSecondary) { - if (info->tilingEnabled) { - if (IS_R300_VARIANT) - surf_info |= (width_bytes / 8) | color_pattern; - else - surf_info |= (width_bytes / 16) | color_pattern; - } - OUTREG(RADEON_SURFACE0_INFO, surf_info); - OUTREG(RADEON_SURFACE0_LOWER_BOUND, 0); - OUTREG(RADEON_SURFACE0_UPPER_BOUND, bufferSize - 1); + if (info->tilingEnabled) { + if (IS_R300_VARIANT) + surf_info |= (width_bytes / 8) | color_pattern; + else + surf_info |= (width_bytes / 16) | color_pattern; + } + OUTREG(RADEON_SURFACE0_INFO, surf_info); + OUTREG(RADEON_SURFACE0_LOWER_BOUND, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND, bufferSize - 1); /* xf86DrvMsg(pScrn->scrnIndex, X_INFO, "surface0 set to %x, LB 0x%x UB 0x%x\n", surf_info, 0, bufferSize - 1024);*/ - } } /* Update surface images */ RADEONSaveSurfaces(pScrn, &info->ModeReg); } -#if 0 -/* Write palette data */ -static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int i; - - if (!restore->palette_valid) return; - - PAL_SELECT(1); - OUTPAL_START(0); - for (i = 0; i < 256; i++) { - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL_NEXT_CARD32(restore->palette2[i]); - } - - PAL_SELECT(0); - OUTPAL_START(0); - for (i = 0; i < 256; i++) { - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL_NEXT_CARD32(restore->palette[i]); - } -} -#endif - -/* Write out state to define a new video mode */ -static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONController* pCRTC1 = pRADEONEnt->Controller[0]; - RADEONController* pCRTC2 = pRADEONEnt->Controller[1]; - RADEONConnector *pPort; - RADEONTRACE(("RADEONRestoreMode(%p)\n", restore)); - - /* For Non-dual head card, we don't have private field in the Entity */ - if (!pRADEONEnt->HasCRTC2) { - RADEONRestoreMemMapRegisters(pScrn, restore); - RADEONRestoreCommonRegisters(pScrn, restore); - RADEONRestoreCrtcRegisters(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - RADEONRestorePLLRegisters(pScrn, restore); - return; - } - - /* Disable all outputs at initial mode set. the ones we want will - get set by RADEONEnableDisplay() - */ - if (!info->IsSwitching && !info->IsSecondary) - RADEONDisableDisplays(pScrn); - - /* When changing mode with Dual-head card, care must be taken for - * the special order in setting registers. CRTC2 has to be set - * before changing CRTC_EXT register. In the dual-head setup, X - * server calls this routine twice with primary and secondary pScrn - * pointers respectively. The calls can come with different - * order. Regardless the order of X server issuing the calls, we - * have to ensure we set registers in the right order!!! Otherwise - * we may get a blank screen. - * - * We always restore MemMap first, the saverec should be up to date - * in all cases - */ - if (info->IsSwitching) { - if (info->IsSecondary) { - RADEONRestoreMemMapRegisters(pScrn, restore); - RADEONRestoreCommonRegisters(pScrn, restore); - RADEONRestoreCrtc2Registers(pScrn, restore); - RADEONRestorePLL2Registers(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) { - RADEONEnableDisplay(pScrn, pPort, TRUE); - pCRTC2->IsActive = TRUE; - } - } else { - RADEONRestoreMemMapRegisters(pScrn, restore); - RADEONRestoreCommonRegisters(pScrn, restore); - if (pCRTC2->binding == 1) { - RADEONRestoreCrtc2Registers(pScrn, restore); - RADEONRestorePLL2Registers(pScrn, restore); - } - - RADEONRestoreCrtcRegisters(pScrn, restore); - RADEONRestorePLLRegisters(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - pPort = RADEONGetCrtcConnector(pScrn, 1); - if (pPort) { - RADEONEnableDisplay(pScrn, pPort, TRUE); - pCRTC1->IsActive = TRUE; - } - if (pCRTC2->binding == 1) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) { - RADEONEnableDisplay(pScrn, pPort, TRUE); - pCRTC2->IsActive = TRUE; - } - } - } - } else { - RADEONRestoreMemMapRegisters(pScrn, restore); - RADEONRestoreCommonRegisters(pScrn, restore); - if ((pCRTC2->binding == 1) || pRADEONEnt->HasSecondary) { - RADEONRestoreCrtc2Registers(pScrn, restore); - RADEONRestorePLL2Registers(pScrn, restore); - } - - RADEONRestoreCrtcRegisters(pScrn, restore); - RADEONRestorePLLRegisters(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - pPort = RADEONGetCrtcConnector(pScrn, 1); - if (pPort) { - RADEONEnableDisplay(pScrn, pPort, TRUE); - pCRTC1->IsActive = TRUE; - } - if ((pCRTC2->binding == 1) || pRADEONEnt->HasSecondary) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) { - RADEONEnableDisplay(pScrn, pPort, TRUE); - pCRTC2->IsActive = TRUE; - } - } - } - -#if 0 - RADEONRestorePalette(pScrn, &info->SavedReg); -#endif -} - /* Read memory map */ static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) { @@ -5203,29 +4964,6 @@ static void RADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->grph2_buffer_cntl = INREG(RADEON_GRPH2_BUFFER_CNTL); } -/* Read miscellaneous registers which might be destroyed by an fbdevHW call */ -static void RADEONSaveFBDevRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) -{ -#ifdef XF86DRI - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - /* Save register for vertical blank interrupts */ - if (info->irq) { - save->gen_int_cntl = INREG(RADEON_GEN_INT_CNTL); - } - - /* Save registers for page flipping */ - if (info->allowPageFlip) { - save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); - if (pRADEONEnt->HasCRTC2) { - save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); - } - } -#endif -} - /* Read CRTC registers */ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) { @@ -5234,7 +4972,6 @@ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); save->crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); - save->dac_cntl = INREG(RADEON_DAC_CNTL); save->crtc_h_total_disp = INREG(RADEON_CRTC_H_TOTAL_DISP); save->crtc_h_sync_strt_wid = INREG(RADEON_CRTC_H_SYNC_STRT_WID); save->crtc_v_total_disp = INREG(RADEON_CRTC_V_TOTAL_DISP); @@ -5251,12 +4988,39 @@ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->disp_merge_cntl = INREG(RADEON_DISP_MERGE_CNTL); save->crtc_more_cntl = INREG(RADEON_CRTC_MORE_CNTL); + if (IS_R300_VARIANT) + save->crtc_tile_x0_y0 = INREG(R300_CRTC_TILE_X0_Y0); + if (info->IsDellServer) { save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); save->dac2_cntl = INREG(RADEON_DAC_CNTL2); save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG); save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); } + + /* track if the crtc is enabled for text restore */ + if (save->crtc_ext_cntl & RADEON_CRTC_DISPLAY_DIS) + info->crtc_on = FALSE; + else + info->crtc_on = TRUE; + +} + +/* Read DAC registers */ +static void RADEONSaveDACRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + save->dac_cntl = INREG(RADEON_DAC_CNTL); + save->dac2_cntl = INREG(RADEON_DAC_CNTL2); + save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + save->disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); + save->disp_tv_out_cntl = INREG(RADEON_DISP_TV_OUT_CNTL); + save->disp_hw_debug = INREG(RADEON_DISP_HW_DEBUG); + save->dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); + save->gpiopad_a = INREG(RADEON_GPIOPAD_A); + } /* Read flat panel registers */ @@ -5289,12 +5053,6 @@ static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - save->dac2_cntl = INREG(RADEON_DAC_CNTL2); - save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); - save->disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); - save->disp_tv_out_cntl = INREG(RADEON_DISP_TV_OUT_CNTL); - save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG); - save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); save->crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP); save->crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); @@ -5304,10 +5062,120 @@ static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); save->crtc2_pitch = INREG(RADEON_CRTC2_PITCH); + if (IS_R300_VARIANT) + save->crtc2_tile_x0_y0 = INREG(R300_CRTC2_TILE_X0_Y0); + save->fp_h2_sync_strt_wid = INREG (RADEON_FP_H2_SYNC_STRT_WID); save->fp_v2_sync_strt_wid = INREG (RADEON_FP_V2_SYNC_STRT_WID); + if (info->ChipFamily == CHIP_FAMILY_RS400) { + save->rs480_unk_e30 = INREG(RADEON_RS480_UNK_e30); + save->rs480_unk_e34 = INREG(RADEON_RS480_UNK_e34); + save->rs480_unk_e38 = INREG(RADEON_RS480_UNK_e38); + save->rs480_unk_e3c = INREG(RADEON_RS480_UNK_e3c); + } + save->disp2_merge_cntl = INREG(RADEON_DISP2_MERGE_CNTL); + + /* track if the crtc is enabled for text restore */ + if (save->crtc2_gen_cntl & RADEON_CRTC2_DISP_DIS) + info->crtc2_on = FALSE; + else + info->crtc2_on = TRUE; + +} + +/* Save horizontal/vertical timing code tables */ +static void RADEONSaveTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD16 hTable; + CARD16 vTable; + CARD32 tmp; + unsigned i; + + save->tv_uv_adr = INREG(RADEON_TV_UV_ADR); + hTable = RADEONGetHTimingTablesAddr(save->tv_uv_adr); + vTable = RADEONGetVTimingTablesAddr(save->tv_uv_adr); + + /* + * Reset FIFO arbiter in order to be able to access FIFO RAM + */ + + OUTREG(RADEON_TV_MASTER_CNTL, (RADEON_TV_ASYNC_RST + | RADEON_CRT_ASYNC_RST + | RADEON_RESTART_PHASE_FIX + | RADEON_CRT_FIFO_CE_EN + | RADEON_TV_FIFO_CE_EN + | RADEON_TV_ON)); + + /*OUTREG(RADEON_TV_MASTER_CNTL, save->tv_master_cntl | RADEON_TV_ON);*/ + + ErrorF("saveTimingTables: reading timing tables\n"); + + for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2) { + tmp = RADEONReadTVFIFO(pScrn, hTable--); + save->h_code_timing[ i ] = (CARD16)((tmp >> 14) & 0x3fff); + save->h_code_timing[ i + 1 ] = (CARD16)(tmp & 0x3fff); + + if (save->h_code_timing[ i ] == 0 || save->h_code_timing[ i + 1 ] == 0) + break; + } + + for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2) { + tmp = RADEONReadTVFIFO(pScrn, vTable++); + save->v_code_timing[ i ] = (CARD16)(tmp & 0x3fff); + save->v_code_timing[ i + 1 ] = (CARD16)((tmp >> 14) & 0x3fff); + + if (save->v_code_timing[ i ] == 0 || save->v_code_timing[ i + 1 ] == 0) + break; + } +} + +/* read TV regs */ +static void RADEONSaveTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + ErrorF("Entering TV Save\n"); + + save->tv_crc_cntl = INREG(RADEON_TV_CRC_CNTL); + save->tv_frestart = INREG(RADEON_TV_FRESTART); + save->tv_hrestart = INREG(RADEON_TV_HRESTART); + save->tv_vrestart = INREG(RADEON_TV_VRESTART); + save->tv_gain_limit_settings = INREG(RADEON_TV_GAIN_LIMIT_SETTINGS); + save->tv_hdisp = INREG(RADEON_TV_HDISP); + save->tv_hstart = INREG(RADEON_TV_HSTART); + save->tv_htotal = INREG(RADEON_TV_HTOTAL); + save->tv_linear_gain_settings = INREG(RADEON_TV_LINEAR_GAIN_SETTINGS); + save->tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL); + save->tv_rgb_cntl = INREG(RADEON_TV_RGB_CNTL); + save->tv_modulator_cntl1 = INREG(RADEON_TV_MODULATOR_CNTL1); + save->tv_modulator_cntl2 = INREG(RADEON_TV_MODULATOR_CNTL2); + save->tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); + save->tv_sync_cntl = INREG(RADEON_TV_SYNC_CNTL); + save->tv_timing_cntl = INREG(RADEON_TV_TIMING_CNTL); + save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + save->tv_upsamp_and_gain_cntl = INREG(RADEON_TV_UPSAMP_AND_GAIN_CNTL); + save->tv_vdisp = INREG(RADEON_TV_VDISP); + save->tv_ftotal = INREG(RADEON_TV_FTOTAL); + save->tv_vscaler_cntl1 = INREG(RADEON_TV_VSCALER_CNTL1); + save->tv_vscaler_cntl2 = INREG(RADEON_TV_VSCALER_CNTL2); + save->tv_vtotal = INREG(RADEON_TV_VTOTAL); + save->tv_y_fall_cntl = INREG(RADEON_TV_Y_FALL_CNTL); + save->tv_y_rise_cntl = INREG(RADEON_TV_Y_RISE_CNTL); + save->tv_y_saw_tooth_cntl = INREG(RADEON_TV_Y_SAW_TOOTH_CNTL); + + save->tv_pll_cntl = INPLL(pScrn, RADEON_TV_PLL_CNTL); + save->tv_pll_cntl1 = INPLL(pScrn, RADEON_TV_PLL_CNTL1); + + ErrorF("Save TV timing tables\n"); + + RADEONSaveTVTimingTables(pScrn, save); + + ErrorF("TV Save done\n"); } /* Read PLL registers */ @@ -5316,16 +5184,18 @@ static void RADEONSavePLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->ppll_ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV); save->ppll_div_3 = INPLL(pScrn, RADEON_PPLL_DIV_3); save->htotal_cntl = INPLL(pScrn, RADEON_HTOTAL_CNTL); - save->vclk_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - - RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08lx\n", - save->ppll_ref_div, - save->ppll_div_3, - save->htotal_cntl)); - RADEONTRACE(("Read: rd=%d, fd=%d, pd=%d\n", - save->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, - save->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, - (save->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16)); + save->vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Read: 0x%08x 0x%08x 0x%08x\n", + save->ppll_ref_div, + save->ppll_div_3, + (unsigned)save->htotal_cntl); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Read: rd=%d, fd=%d, pd=%d\n", + save->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, + save->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, + (save->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16); } /* Read PLL registers */ @@ -5336,14 +5206,17 @@ static void RADEONSavePLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) save->htotal_cntl2 = INPLL(pScrn, RADEON_HTOTAL2_CNTL); save->pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - RADEONTRACE(("Read: 0x%08lx 0x%08lx 0x%08lx\n", - save->p2pll_ref_div, - save->p2pll_div_0, - save->htotal_cntl2)); - RADEONTRACE(("Read: rd=%ld, fd=%ld, pd=%ld\n", - save->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, - save->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, - (save->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) >> 16)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Read: 0x%08x 0x%08x 0x%08x\n", + (unsigned)save->p2pll_ref_div, + (unsigned)save->p2pll_div_0, + (unsigned)save->htotal_cntl2); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Read: rd=%u, fd=%u, pd=%u\n", + (unsigned)(save->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK), + (unsigned)(save->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK), + (unsigned)((save->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) + >> 16)); } /* Read palette data */ @@ -5369,27 +5242,25 @@ static void RADEONSavePalette(ScrnInfoPtr pScrn, RADEONSavePtr save) /* Save state that defines current video mode */ static void RADEONSaveMode(ScrnInfoPtr pScrn, RADEONSavePtr save) { - RADEONInfoPtr info = RADEONPTR(pScrn); - - RADEONTRACE(("RADEONSaveMode(%p)\n", save)); + RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->IsSecondary) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONInfoPtr info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn); - memcpy(&info->SavedReg, &info0->SavedReg, sizeof(RADEONSaveRec)); - } else { - RADEONSaveMemMapRegisters(pScrn, save); - RADEONSaveCommonRegisters(pScrn, save); - RADEONSavePLLRegisters (pScrn, save); - RADEONSaveCrtcRegisters (pScrn, save); - RADEONSaveFPRegisters (pScrn, save); - RADEONSaveCrtc2Registers (pScrn, save); - RADEONSavePLL2Registers (pScrn, save); - /*RADEONSavePalette(pScrn, save);*/ - /*memcpy(&info->ModeReg, &info->SavedReg, sizeof(RADEONSaveRec));*/ - } - - RADEONTRACE(("RADEONSaveMode returns %p\n", save)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONSaveMode(%p)\n", save); + + RADEONSaveMemMapRegisters(pScrn, save); + RADEONSaveCommonRegisters(pScrn, save); + RADEONSavePLLRegisters(pScrn, save); + RADEONSaveCrtcRegisters(pScrn, save); + RADEONSaveFPRegisters(pScrn, save); + RADEONSaveDACRegisters(pScrn, save); + RADEONSaveCrtc2Registers(pScrn, save); + RADEONSavePLL2Registers(pScrn, save); + if (info->InternalTVOut) + RADEONSaveTVRegisters(pScrn, save); + /*RADEONSavePalette(pScrn, save);*/ + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONSaveMode returns %p\n", save); } /* Save everything needed to restore the original VC state */ @@ -5399,62 +5270,55 @@ static void RADEONSave(ScrnInfoPtr pScrn) unsigned char *RADEONMMIO = info->MMIO; RADEONSavePtr save = &info->SavedReg; - RADEONTRACE(("RADEONSave\n")); - if (info->FBDev) { - RADEONSaveMemMapRegisters(pScrn, save); - fbdevHWSave(pScrn); - return; - } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONSave\n"); - if (!info->IsSecondary) { #ifdef WITH_VGAHW - if (info->VGAAccess) { - vgaHWPtr hwp = VGAHWPTR(pScrn); + if (info->VGAAccess) { + vgaHWPtr hwp = VGAHWPTR(pScrn); - vgaHWUnlock(hwp); + vgaHWUnlock(hwp); # if defined(__powerpc__) - /* temporary hack to prevent crashing on PowerMacs when trying to - * read VGA fonts and colormap, will find a better solution - * in the future. TODO: Check if there's actually some VGA stuff - * setup in the card at all !! - */ - vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */ + /* temporary hack to prevent crashing on PowerMacs when trying to + * read VGA fonts and colormap, will find a better solution + * in the future. TODO: Check if there's actually some VGA stuff + * setup in the card at all !! + */ + vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */ # else - /* Save mode * & fonts & cmap */ - vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); + /* Save mode * & fonts & cmap */ + vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); # endif - vgaHWLock(hwp); - } -#endif - save->dp_datatype = INREG(RADEON_DP_DATATYPE); - save->rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); - save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); - RADEONPllErrataAfterIndex(info); + vgaHWLock(hwp); } +#endif + save->dp_datatype = INREG(RADEON_DP_DATATYPE); + save->rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); + save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); + RADEONPllErrataAfterIndex(info); RADEONSaveMode(pScrn, save); - if (!info->IsSecondary) - RADEONSaveSurfaces(pScrn, save); + RADEONSaveSurfaces(pScrn, save); } /* Restore the original (text) mode */ -static void RADEONRestore(ScrnInfoPtr pScrn) +void RADEONRestore(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; RADEONSavePtr restore = &info->SavedReg; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc; - RADEONTRACE(("RADEONRestore\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONRestore\n"); #if X_BYTE_ORDER == X_BIG_ENDIAN RADEONWaitForFifo(pScrn, 1); OUTREG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE); #endif - if (info->FBDev) { - fbdevHWRestore(pScrn); - return; - } RADEONBlank(pScrn); OUTREG(RADEON_CLOCK_CNTL_INDEX, restore->clock_cntl_index); @@ -5473,11 +5337,27 @@ static void RADEONRestore(ScrnInfoPtr pScrn) OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); #endif - RADEONRestoreMode(pScrn, restore); - if (!info->IsSecondary) - RADEONRestoreSurfaces(pScrn, restore); + RADEONRestoreMemMapRegisters(pScrn, restore); + RADEONRestoreCommonRegisters(pScrn, restore); -#if 0 + if (pRADEONEnt->HasCRTC2) { + RADEONRestoreCrtc2Registers(pScrn, restore); + RADEONRestorePLL2Registers(pScrn, restore); + } + + RADEONRestoreCrtcRegisters(pScrn, restore); + RADEONRestorePLLRegisters(pScrn, restore); + RADEONRestoreRMXRegisters(pScrn, restore); + RADEONRestoreFPRegisters(pScrn, restore); + RADEONRestoreFP2Registers(pScrn, restore); + RADEONRestoreLVDSRegisters(pScrn, restore); + + if (info->InternalTVOut) + RADEONRestoreTVRegisters(pScrn, restore); + + RADEONRestoreSurfaces(pScrn, restore); + +#if 1 /* Temp fix to "solve" VT switch problems. When switching VTs on * some systems, the console can either hang or the fonts can be * corrupted. This hack solves the problem 99% of the time. A @@ -5489,830 +5369,36 @@ static void RADEONRestore(ScrnInfoPtr pScrn) #ifdef WITH_VGAHW if (info->VGAAccess) { vgaHWPtr hwp = VGAHWPTR(pScrn); - if (!info->IsSecondary) { - vgaHWUnlock(hwp); + vgaHWUnlock(hwp); # if defined(__powerpc__) - /* Temporary hack to prevent crashing on PowerMacs when trying to - * write VGA fonts, will find a better solution in the future - */ - vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE ); + /* Temporary hack to prevent crashing on PowerMacs when trying to + * write VGA fonts, will find a better solution in the future + */ + vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE ); # else - vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); + vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); # endif - vgaHWLock(hwp); - } else { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - ScrnInfoPtr pScrn0 = pRADEONEnt->pPrimaryScrn; - RADEONInfoPtr info0 = RADEONPTR(pScrn0); - vgaHWPtr hwp0; - - if (info0->VGAAccess) { - hwp0 = VGAHWPTR(pScrn0); - vgaHWUnlock(hwp0); -#if defined(__powerpc__) - vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE); -#else - vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); -#endif - vgaHWLock(hwp0); - } - } - } -#endif - RADEONUnblank(pScrn); - -#if 0 - RADEONWaitForVerticalSync(pScrn); -#endif -} - -/* Define common registers for requested video mode */ -static void RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) -{ - save->ovr_clr = 0; - save->ovr_wid_left_right = 0; - save->ovr_wid_top_bottom = 0; - save->ov0_scale_cntl = 0; - save->subpic_cntl = 0; - save->viph_control = 0; - save->i2c_cntl_1 = 0; - save->rbbm_soft_reset = 0; - save->cap0_trig_cntl = 0; - save->cap1_trig_cntl = 0; - save->bus_cntl = info->BusCntl; - /* - * If bursts are enabled, turn on discards - * Radeon doesn't have write bursts - */ - if (save->bus_cntl & (RADEON_BUS_READ_BURST)) - save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; -} - -/* XXX: fix me */ -static void RADEONInitTvDacCntl(ScrnInfoPtr pScrn, RADEONSavePtr save) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->ChipFamily == CHIP_FAMILY_R420 || - info->ChipFamily == CHIP_FAMILY_RV410) { - save->tv_dac_cntl = info->SavedReg.tv_dac_cntl & - ~(RADEON_TV_DAC_STD_MASK | - RADEON_TV_DAC_BGADJ_MASK | - R420_TV_DAC_DACADJ_MASK | - R420_TV_DAC_RDACPD | - R420_TV_DAC_GDACPD | - R420_TV_DAC_GDACPD | - R420_TV_DAC_TVENABLE); - } else { - save->tv_dac_cntl = info->SavedReg.tv_dac_cntl & - ~(RADEON_TV_DAC_STD_MASK | - RADEON_TV_DAC_BGADJ_MASK | - RADEON_TV_DAC_DACADJ_MASK | - RADEON_TV_DAC_RDACPD | - RADEON_TV_DAC_GDACPD | - RADEON_TV_DAC_GDACPD); - } - /* FIXME: doesn't make sense, this just replaces the previous value... */ - save->tv_dac_cntl = (RADEON_TV_DAC_NBLANK | - RADEON_TV_DAC_NHOLD | - RADEON_TV_DAC_STD_PS2 | - info->tv_dac_adj); -} - -static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - int i; - CARD32 tmp = info->SavedReg.tmds_pll_cntl & 0xfffff; - - for (i=0; i<4; i++) { - if (info->tmds_pll[i].freq == 0) break; - if ((CARD32)(mode->Clock/10) < info->tmds_pll[i].freq) { - tmp = info->tmds_pll[i].value ; - break; - } - } - - if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) { - if (tmp & 0xfff00000) - save->tmds_pll_cntl = tmp; - else { - save->tmds_pll_cntl = info->SavedReg.tmds_pll_cntl & 0xfff00000; - save->tmds_pll_cntl |= tmp; - } - } else save->tmds_pll_cntl = tmp; - - save->tmds_transmitter_cntl = info->SavedReg.tmds_transmitter_cntl & - ~(RADEON_TMDS_TRANSMITTER_PLLRST); - - if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !pRADEONEnt->HasCRTC2) - save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); - else /* weird, RV chips got this bit reversed? */ - save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); - - save->fp_gen_cntl = info->SavedReg.fp_gen_cntl | - (RADEON_FP_CRTC_DONT_SHADOW_VPAR | - RADEON_FP_CRTC_DONT_SHADOW_HEND ); - - if (pScrn->rgbBits == 8) - save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ - else - save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ - - - if (IsPrimary) { - if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { - save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; - if (mode->Flags & RADEON_USE_RMX) - save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; - else - save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; - } else - save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1; - } else { - if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { - save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; - save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; - } else - save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2; - } - -} - -static void RADEONInitFP2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (pScrn->rgbBits == 8) - save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl | - RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ - else - save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl & - ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ - - if (IsPrimary) { - if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { - save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | - RADEON_FP2_DVO_EN | - RADEON_FP2_DVO_RATE_SEL_SDR); - if (mode->Flags & RADEON_USE_RMX) - save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; - } else { - save->fp2_gen_cntl &= ~(RADEON_FP2_SRC_SEL_CRTC2 | - RADEON_FP2_DVO_RATE_SEL_SDR); - } - /*save->fp2_gen_cntl |= ( RADEON_FP2_ON | - RADEON_FP2_BLANK_EN | - RADEON_FP2_DVO_EN);*/ - } else { - if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { - save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | - RADEON_FP2_DVO_RATE_SEL_SDR); - save->fp2_gen_cntl |= (R200_FP2_SOURCE_SEL_CRTC2 /*| - RADEON_FP2_PANEL_FORMAT | - RADEON_FP2_BLANK_EN | - RADEON_FP2_ON | - RADEON_FP2_DVO_EN*/); - } else { - save->fp2_gen_cntl &= ~(RADEON_FP2_DVO_RATE_SEL_SDR); - save->fp2_gen_cntl |= (RADEON_FP2_SRC_SEL_CRTC2 /*| - RADEON_FP2_PANEL_FORMAT | - RADEON_FP2_BLANK_EN | - RADEON_FP2_ON | - RADEON_FP2_DVO_EN*/); - } - } - -} - -static void RADEONInitLVDSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); -/* XXX saved but never used??? */ - if (IsPrimary) - save->lvds_gen_cntl = info->SavedReg.lvds_gen_cntl & - ~RADEON_LVDS_SEL_CRTC2; - else - save->lvds_gen_cntl = info->SavedReg.lvds_gen_cntl | - RADEON_LVDS_SEL_CRTC2; - -} - -static void RADEONInitRMXRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - int xres = mode->HDisplay; - int yres = mode->VDisplay; - float Hratio, Vratio; - - - if (info->PanelXRes == 0 || info->PanelYRes == 0) { - Hratio = 1.0; - Vratio = 1.0; - } else { - if (xres > info->PanelXRes) xres = info->PanelXRes; - if (yres > info->PanelYRes) yres = info->PanelYRes; - - Hratio = (float)xres/(float)info->PanelXRes; - Vratio = (float)yres/(float)info->PanelYRes; - } - - save->fp_vert_stretch = info->SavedReg.fp_vert_stretch & - RADEON_VERT_STRETCH_RESERVED; - save->fp_horz_stretch = info->SavedReg.fp_horz_stretch & - (RADEON_HORZ_FP_LOOP_STRETCH | - RADEON_HORZ_AUTO_RATIO_INC); - - if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { - save->fp_horz_stretch |= ((xres/8-1)<<16); - } else { - save->fp_horz_stretch |= ((((unsigned long)(Hratio * RADEON_HORZ_STRETCH_RATIO_MAX + - 0.5)) & RADEON_HORZ_STRETCH_RATIO_MASK) | - RADEON_HORZ_STRETCH_BLEND | - RADEON_HORZ_STRETCH_ENABLE | - ((info->PanelXRes/8-1)<<16)); - } - - if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { - save->fp_vert_stretch |= ((yres-1)<<12); - } else { - save->fp_vert_stretch |= ((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX + - 0.5)) & RADEON_VERT_STRETCH_RATIO_MASK) | - RADEON_VERT_STRETCH_ENABLE | - RADEON_VERT_STRETCH_BLEND | - ((info->PanelYRes-1)<<12)); - } - -} - -static void RADEONInitDACRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (IsPrimary) { - if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { - save->disp_output_cntl = info->SavedReg.disp_output_cntl & - ~RADEON_DISP_DAC_SOURCE_MASK; - } else { - save->dac2_cntl = info->SavedReg.dac2_cntl & ~(RADEON_DAC2_DAC_CLK_SEL); - } - save->dac_cntl = (RADEON_DAC_MASK_ALL - | RADEON_DAC_VGA_ADR_EN - | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN)); - - } else { - if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { - save->disp_output_cntl = info->SavedReg.disp_output_cntl & - ~RADEON_DISP_DAC_SOURCE_MASK; - save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; - } else { - save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC_CLK_SEL; - } - } -} - -static void RADEONInitDAC2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - /*0x0028023;*/ - RADEONInitTvDacCntl(pScrn, save); - - if (IsPrimary) { - /*save->crtc2_gen_cntl = info->SavedReg.crtc2_gen_cntl | RADEON_CRTC2_CRT2_ON;*/ - save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; - if (IS_R300_VARIANT) { - save->disp_output_cntl = info->SavedReg.disp_output_cntl & - ~RADEON_DISP_TVDAC_SOURCE_MASK; - save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; - } else if (info->ChipFamily == CHIP_FAMILY_R200) { - save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl & - ~(R200_FP2_SOURCE_SEL_MASK | - RADEON_FP2_DVO_RATE_SEL_SDR); - /*save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl | - (RADEON_FP2_ON | - RADEON_FP2_BLANK_EN | - RADEON_FP2_DVO_EN);*/ - } else { - save->disp_hw_debug = info->SavedReg.disp_hw_debug | RADEON_CRT2_DISP1_SEL; - } - } else { - save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; - if (IS_R300_VARIANT) { - save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; - save->disp_output_cntl = info->SavedReg.disp_output_cntl & - ~RADEON_DISP_TVDAC_SOURCE_MASK; - save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; - } else if (info->ChipFamily == CHIP_FAMILY_R200) { - save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl & - ~(R200_FP2_SOURCE_SEL_MASK | - RADEON_FP2_DVO_RATE_SEL_SDR); - save->fp2_gen_cntl |= (R200_FP2_SOURCE_SEL_CRTC2 /*| - RADEON_FP2_BLANK_EN | - RADEON_FP2_ON | - RADEON_FP2_DVO_EN*/); - /*save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; - save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid;*/ - } else { - save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; - save->disp_hw_debug = info->SavedReg.disp_hw_debug & - ~RADEON_CRT2_DISP1_SEL; - } - } -} - -static void RADEONInitOutputRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, DisplayModePtr mode, RADEONConnector *pPort, int crtc_num) -{ - Bool IsPrimary = crtc_num == 1 ? TRUE : FALSE; - - if (pPort->MonType == MT_CRT) { - if (pPort->DACType == DAC_PRIMARY) { - RADEONInitDACRegisters(pScrn, save, mode, IsPrimary); - } else { - RADEONInitDAC2Registers(pScrn, save, mode, IsPrimary); - } - } else if (pPort->MonType == MT_LCD) { - if (crtc_num == 1) - RADEONInitRMXRegisters(pScrn, save, mode); - RADEONInitLVDSRegisters(pScrn, save, mode, IsPrimary); - } else if (pPort->MonType == MT_DFP) { - if (crtc_num == 1) - RADEONInitRMXRegisters(pScrn, save, mode); - if (pPort->TMDSType == TMDS_INT) { - RADEONInitFPRegisters(pScrn, save, mode, IsPrimary); - } else { - RADEONInitFP2Registers(pScrn, save, mode, IsPrimary); - } - } -} - -/* Define CRTC registers for requested video mode */ -static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, RADEONInfoPtr info) -{ - int format; - int hsync_start; - int hsync_wid; - int vsync_wid; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - pRADEONEnt->Controller[0]->IsUsed = TRUE; - pRADEONEnt->Controller[0]->IsActive = TRUE; - pRADEONEnt->Controller[0]->pCurMode = mode; - - switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; break; - case 8: format = 2; break; - case 15: format = 3; break; /* 555 */ - case 16: format = 4; break; /* 565 */ - case 24: format = 5; break; /* RGB */ - case 32: format = 6; break; /* xRGB */ - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unsupported pixel depth (%d)\n", - info->CurrentLayout.bitsPerPixel); - return FALSE; - } - - save->bios_4_scratch = info->SavedReg.bios_4_scratch; - save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN - | RADEON_CRTC_EN - | (format << 8) - | ((mode->Flags & V_DBLSCAN) - ? RADEON_CRTC_DBL_SCAN_EN - : 0) - | ((mode->Flags & V_CSYNC) - ? RADEON_CRTC_CSYNC_EN - : 0) - | ((mode->Flags & V_INTERLACE) - ? RADEON_CRTC_INTERLACE_EN - : 0)); - - save->crtc_ext_cntl |= (RADEON_CRTC_CRT_ON | - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS | - RADEON_CRTC_DISPLAY_DIS); - - save->surface_cntl = 0; - save->disp_merge_cntl = info->SavedReg.disp_merge_cntl; - save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; - -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* We must set both apertures as they can be both used to map the entire - * video memory. -BenH. - */ - switch (pScrn->bitsPerPixel) { - case 16: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; - break; - - case 32: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; - break; + vgaHWLock(hwp); } #endif - save->crtc_more_cntl = 0; - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200)) { - /* This is to workaround the asic bug for RMX, some versions - of BIOS dosen't have this register initialized correctly. - */ - save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; + /* need to make sure we don't enable a crtc by accident or we may get a hang */ + if (info->crtc2_on) { + crtc = xf86_config->crtc[1]; + crtc->funcs->dpms(crtc, DPMSModeOn); } - - if (mode->Flags & RADEON_USE_RMX) { - mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank; - mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus; - mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth; - mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank; - mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus; - mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth; - mode->Clock = info->DotClock; - mode->Flags = info->Flags | RADEON_USE_RMX; + if (info->crtc_on) { + crtc = xf86_config->crtc[0]; + crtc->funcs->dpms(crtc, DPMSModeOn); } - - - - save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) - | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) - << 16)); - - hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; - if (!hsync_wid) hsync_wid = 1; - if (hsync_wid > 0x3f) hsync_wid = 0x3f; - hsync_start = mode->CrtcHSyncStart - 8; - - save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) - | (hsync_wid << 16) - | ((mode->Flags & V_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); - - /* This works for double scan mode. */ - save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - 1) << 16)); - - vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; - if (!vsync_wid) vsync_wid = 1; - if (vsync_wid > 0x1f) vsync_wid = 0x1f; - - save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) - | (vsync_wid << 16) - | ((mode->Flags & V_NVSYNC) - ? RADEON_CRTC_V_SYNC_POL - : 0)); - - save->crtc_offset = pScrn->fbOffset; - if (info->tilingEnabled) { - if (IS_R300_VARIANT) - save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; - } - else { - if (IS_R300_VARIANT) - save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; - } - - save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + - ((pScrn->bitsPerPixel * 8) -1)) / - (pScrn->bitsPerPixel * 8)); - save->crtc_pitch |= save->crtc_pitch << 16; - - save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; - save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; - save->fp_crtc_h_total_disp = save->crtc_h_total_disp; - save->fp_crtc_v_total_disp = save->crtc_v_total_disp; - - /* Set following registers for all cases first, if a DFP/LCD is connected on - internal TMDS/LVDS port, they will be set by RADEONInitFPRegister - */ - if (!info->IsSwitching) { - save->fp_gen_cntl = 0; - save->fp_vert_stretch = info->SavedReg.fp_vert_stretch & - RADEON_VERT_STRETCH_RESERVED; - save->fp_horz_stretch = info->SavedReg.fp_horz_stretch & - (RADEON_HORZ_FP_LOOP_STRETCH | - RADEON_HORZ_AUTO_RATIO_INC); - } - - /* get the output connected to this CRTC */ - if (pRADEONEnt->PortInfo[0]->crtc_num == 1) { - RADEONInitOutputRegisters(pScrn, save, mode, pRADEONEnt->PortInfo[0], 1); - } else if (pRADEONEnt->PortInfo[1]->crtc_num == 1) { - RADEONInitOutputRegisters(pScrn, save, mode, pRADEONEnt->PortInfo[1], 1); - } - - if (info->IsDellServer) { - save->dac2_cntl = info->SavedReg.dac2_cntl; - save->tv_dac_cntl = info->SavedReg.tv_dac_cntl; - save->crtc2_gen_cntl = info->SavedReg.crtc2_gen_cntl; - save->disp_hw_debug = info->SavedReg.disp_hw_debug; - - save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; - save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; - - /* For CRT on DAC2, don't turn it on if BIOS didn't - enable it, even it's detected. - */ - save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; - save->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16)); - save->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16)); - } - - return TRUE; -} - -/* Define CRTC2 registers for requested video mode */ -static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, RADEONInfoPtr info) -{ - int format; - int hsync_start; - int hsync_wid; - int vsync_wid; - - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONInfoPtr info0 = NULL; - if (info->IsSecondary) - info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn); - - pRADEONEnt->Controller[1]->IsUsed = TRUE; - pRADEONEnt->Controller[1]->IsActive = TRUE; - pRADEONEnt->Controller[1]->pCurMode = mode; - - switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; break; - case 8: format = 2; break; - case 15: format = 3; break; /* 555 */ - case 16: format = 4; break; /* 565 */ - case 24: format = 5; break; /* RGB */ - case 32: format = 6; break; /* xRGB */ - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unsupported pixel depth (%d)\n", - info->CurrentLayout.bitsPerPixel); - return FALSE; - } - - save->crtc2_h_total_disp = - ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) - | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); - - hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; - if (!hsync_wid) hsync_wid = 1; - if (hsync_wid > 0x3f) hsync_wid = 0x3f; - hsync_start = mode->CrtcHSyncStart - 8; - - save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) - | (hsync_wid << 16) - | ((mode->Flags & V_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); - - /* This works for double scan mode. */ - save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - 1) << 16)); - - vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; - if (!vsync_wid) vsync_wid = 1; - if (vsync_wid > 0x1f) vsync_wid = 0x1f; - - save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) - | (vsync_wid << 16) - | ((mode->Flags & V_NVSYNC) - ? RADEON_CRTC2_V_SYNC_POL - : 0)); - - /* It seems all fancy options apart from pflip can be safely disabled - */ - save->crtc2_offset = pScrn->fbOffset; - save->crtc2_offset_cntl &= RADEON_CRTC_OFFSET_FLIP_CNTL; - if (info->tilingEnabled) { - if (IS_R300_VARIANT) - save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN; - } - else { - if (IS_R300_VARIANT) - save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN; - } - - save->crtc2_pitch = ((pScrn->displayWidth * pScrn->bitsPerPixel) + - ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); - save->crtc2_pitch |= save->crtc2_pitch << 16; - - save->crtc2_gen_cntl = (RADEON_CRTC2_EN - | RADEON_CRTC2_CRT2_ON - | (format << 8) - | RADEON_CRTC2_VSYNC_DIS - | RADEON_CRTC2_HSYNC_DIS - | RADEON_CRTC2_DISP_DIS - | ((mode->Flags & V_DBLSCAN) - ? RADEON_CRTC2_DBL_SCAN_EN - : 0) - | ((mode->Flags & V_CSYNC) - ? RADEON_CRTC2_CSYNC_EN - : 0) - | ((mode->Flags & V_INTERLACE) - ? RADEON_CRTC2_INTERLACE_EN - : 0)); - - save->disp2_merge_cntl = info->SavedReg.disp2_merge_cntl; - save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); - - save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; - save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid; - - /* get the output connected to this CRTC */ - if (pRADEONEnt->PortInfo[0]->crtc_num == 2) { - RADEONInitOutputRegisters(pScrn, save, mode, pRADEONEnt->PortInfo[0], 2); - } else if (pRADEONEnt->PortInfo[1]->crtc_num == 2) { - RADEONInitOutputRegisters(pScrn, save, mode, pRADEONEnt->PortInfo[1], 2); - } - - /* We must set SURFACE_CNTL properly on the second screen too */ - save->surface_cntl = 0; -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* We must set both apertures as they can be both used to map the entire - * video memory. -BenH. + /* to restore console mode, DAC registers should be set after every other registers are set, + * otherwise,we may get blank screen */ - switch (pScrn->bitsPerPixel) { - case 16: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; - break; + RADEONRestoreDACRegisters(pScrn, restore); - case 32: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; - break; - } +#if 0 + RADEONWaitForVerticalSync(pScrn); #endif - - return TRUE; -} - - -/* Define PLL registers for requested video mode */ -static void RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info, - RADEONSavePtr save, RADEONPLLPtr pll, - double dot_clock) -{ - unsigned long freq = dot_clock * 100; - - struct { - int divider; - int bitvalue; - } *post_div, post_divs[] = { - /* From RAGE 128 VR/RAGE 128 GL Register - * Reference Manual (Technical Reference - * Manual P/N RRG-G04100-C Rev. 0.04), page - * 3-17 (PLL_DIV_[3:0]). - */ - { 1, 0 }, /* VCLK_SRC */ - { 2, 1 }, /* VCLK_SRC/2 */ - { 4, 2 }, /* VCLK_SRC/4 */ - { 8, 3 }, /* VCLK_SRC/8 */ - { 3, 4 }, /* VCLK_SRC/3 */ - { 16, 5 }, /* VCLK_SRC/16 */ - { 6, 6 }, /* VCLK_SRC/6 */ - { 12, 7 }, /* VCLK_SRC/12 */ - { 0, 0 } - }; - - if (info->UseBiosDividers) { - save->ppll_ref_div = info->RefDivider; - save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); - save->htotal_cntl = 0; - return; - } - - if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; - if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; - - for (post_div = &post_divs[0]; post_div->divider; ++post_div) { - save->pll_output_freq = post_div->divider * freq; - - if (save->pll_output_freq >= pll->min_pll_freq - && save->pll_output_freq <= pll->max_pll_freq) break; - } - - if (!post_div->divider) { - save->pll_output_freq = freq; - post_div = &post_divs[0]; - } - - save->dot_clock_freq = freq; - save->feedback_div = RADEONDiv(pll->reference_div - * save->pll_output_freq, - pll->reference_freq); - save->post_div = post_div->divider; - - RADEONTRACE(("dc=%ld, of=%ld, fd=%d, pd=%d\n", - save->dot_clock_freq, - save->pll_output_freq, - save->feedback_div, - save->post_div)); - - save->ppll_ref_div = pll->reference_div; - save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); - save->htotal_cntl = 0; - - save->vclk_cntl = (info->SavedReg.vclk_cntl & - ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; - -} - -/* Define PLL2 registers for requested video mode */ -static void RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, - RADEONPLLPtr pll, double dot_clock, - int no_odd_postdiv) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long freq = dot_clock * 100; - - struct { - int divider; - int bitvalue; - } *post_div, post_divs[] = { - /* From RAGE 128 VR/RAGE 128 GL Register - * Reference Manual (Technical Reference - * Manual P/N RRG-G04100-C Rev. 0.04), page - * 3-17 (PLL_DIV_[3:0]). - */ - { 1, 0 }, /* VCLK_SRC */ - { 2, 1 }, /* VCLK_SRC/2 */ - { 4, 2 }, /* VCLK_SRC/4 */ - { 8, 3 }, /* VCLK_SRC/8 */ - { 3, 4 }, /* VCLK_SRC/3 */ - { 6, 6 }, /* VCLK_SRC/6 */ - { 12, 7 }, /* VCLK_SRC/12 */ - { 0, 0 } - }; - - if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; - if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; - - for (post_div = &post_divs[0]; post_div->divider; ++post_div) { - /* Odd post divider value don't work properly on the second digital - * output - */ - if (no_odd_postdiv && (post_div->divider & 1)) - continue; - save->pll_output_freq_2 = post_div->divider * freq; - if (save->pll_output_freq_2 >= pll->min_pll_freq - && save->pll_output_freq_2 <= pll->max_pll_freq) break; - } - - if (!post_div->divider) { - save->pll_output_freq_2 = freq; - post_div = &post_divs[0]; - } - - save->dot_clock_freq_2 = freq; - save->feedback_div_2 = RADEONDiv(pll->reference_div - * save->pll_output_freq_2, - pll->reference_freq); - save->post_div_2 = post_div->divider; - - RADEONTRACE(("dc=%ld, of=%ld, fd=%d, pd=%d\n", - save->dot_clock_freq_2, - save->pll_output_freq_2, - save->feedback_div_2, - save->post_div_2)); - - save->p2pll_ref_div = pll->reference_div; - save->p2pll_div_0 = (save->feedback_div_2 | - (post_div->bitvalue << 16)); - save->htotal_cntl2 = 0; - - save->pixclks_cntl = ((info->SavedReg.pixclks_cntl & - ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | - RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); - } #if 0 @@ -6325,177 +5411,22 @@ static void RADEONInitPalette(RADEONSavePtr save) } #endif -/* Define registers for a requested video mode */ -static Bool RADEONInit2(ScrnInfoPtr pScrn, DisplayModePtr crtc1, - DisplayModePtr crtc2, int crtc_mask, - RADEONSavePtr save) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - double dot_clock = crtc1->Clock/1000.0; - RADEONInfoPtr info0 = NULL; - ScrnInfoPtr pScrn0 = NULL; - -#if RADEON_DEBUG - ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", - crtc1->name, - dot_clock, - - crtc1->HDisplay, - crtc1->HSyncStart, - crtc1->HSyncEnd, - crtc1->HTotal, - - crtc1->VDisplay, - crtc1->VSyncStart, - crtc1->VSyncEnd, - crtc1->VTotal, - pScrn->depth, - pScrn->bitsPerPixel); - if (crtc1->Flags & V_DBLSCAN) ErrorF(" D"); - if (crtc1->Flags & V_CSYNC) ErrorF(" C"); - if (crtc1->Flags & V_INTERLACE) ErrorF(" I"); - if (crtc1->Flags & V_PHSYNC) ErrorF(" +H"); - if (crtc1->Flags & V_NHSYNC) ErrorF(" -H"); - if (crtc1->Flags & V_PVSYNC) ErrorF(" +V"); - if (crtc1->Flags & V_NVSYNC) ErrorF(" -V"); - ErrorF("\n"); - ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", - crtc1->name, - dot_clock, - - crtc1->CrtcHDisplay, - crtc1->CrtcHSyncStart, - crtc1->CrtcHSyncEnd, - crtc1->CrtcHTotal, - - crtc1->CrtcVDisplay, - crtc1->CrtcVSyncStart, - crtc1->CrtcVSyncEnd, - crtc1->CrtcVTotal, - pScrn->depth, - pScrn->bitsPerPixel); - if (crtc1->Flags & V_DBLSCAN) ErrorF(" D"); - if (crtc1->Flags & V_CSYNC) ErrorF(" C"); - if (crtc1->Flags & V_INTERLACE) ErrorF(" I"); - if (crtc1->Flags & V_PHSYNC) ErrorF(" +H"); - if (crtc1->Flags & V_NHSYNC) ErrorF(" -H"); - if (crtc1->Flags & V_PVSYNC) ErrorF(" +V"); - if (crtc1->Flags & V_NVSYNC) ErrorF(" -V"); - ErrorF("\n"); -#endif - - info->Flags = crtc1->Flags; - - RADEONInitMemMapRegisters(pScrn, save, info); - RADEONInitCommonRegisters(save, info); - - switch(crtc_mask) { - case 1: - if (!RADEONInitCrtcRegisters(pScrn, save, crtc1, info)) - return FALSE; - dot_clock = crtc1->Clock/1000.0; - if (dot_clock) { - RADEONInitPLLRegisters(pScrn, info, save, &info->pll, dot_clock); - } else { - save->ppll_ref_div = info->SavedReg.ppll_ref_div; - save->ppll_div_3 = info->SavedReg.ppll_div_3; - save->htotal_cntl = info->SavedReg.htotal_cntl; - } - if (pRADEONEnt->HasSecondary) { - pScrn0 = pRADEONEnt->pSecondaryScrn; - info0 = RADEONPTR(pScrn0); - /* carry over to secondary screen */ - memcpy(&info0->ModeReg, save, sizeof(RADEONSaveRec)); - } - - /* Not used for now: */ - /* if (!info->PaletteSavedOnVT) RADEONInitPalette(save); */ - break; - case 2: - pScrn0 = pRADEONEnt->pPrimaryScrn; - info0 = RADEONPTR(pScrn0); - dot_clock = crtc2->Clock/1000.0; - if (!RADEONInitCrtc2Registers(pScrn, save, crtc2, info)) - return FALSE; - RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->DisplayType != MT_CRT); - /* Make sure primary has the same copy */ - memcpy(&info0->ModeReg, save, sizeof(RADEONSaveRec)); - break; - case 3: - if (!RADEONInitCrtcRegisters(pScrn, save, - crtc1, info)) - return FALSE; - dot_clock = crtc1->Clock / 1000.0; - if (dot_clock) { - RADEONInitPLLRegisters(pScrn, info, save, &info->pll, dot_clock); - } else { - save->ppll_ref_div = info->SavedReg.ppll_ref_div; - save->ppll_div_3 = info->SavedReg.ppll_div_3; - save->htotal_cntl = info->SavedReg.htotal_cntl; - } - RADEONInitCrtc2Registers(pScrn, save, crtc2, info); - dot_clock = crtc2->Clock / 1000.0; - RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->MergeType != MT_CRT); - break; - default: - return FALSE; - } - - RADEONTRACE(("RADEONInit returns %p\n", save)); - return TRUE; -} - -static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode, - RADEONSavePtr save) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (info->IsSecondary) { - return RADEONInit2(pScrn, NULL, mode, 2, save); - } else if (info->MergedFB) { - return RADEONInit2(pScrn, ((RADEONMergedDisplayModePtr)mode->Private)->CRT1, - ((RADEONMergedDisplayModePtr)mode->Private)->CRT2, 3, save); - } else { - return RADEONInit2(pScrn, mode, NULL, 1, save); - } -} - -/* Initialize a new mode */ -static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - RADEONTRACE(("RADEONModeInit()\n")); - - if (!RADEONInit(pScrn, mode, &info->ModeReg)) return FALSE; - - pScrn->vtSema = TRUE; - RADEONBlank(pScrn); - RADEONRestoreMode(pScrn, &info->ModeReg); - RADEONUnblank(pScrn); - - info->CurrentLayout.mode = mode; - - if (info->DispPriority) - RADEONInitDispBandwidth(pScrn); - - return TRUE; -} - static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; Bool unblank; - RADEONTRACE(("RADEONSaveScreen(%d)\n", mode)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONSaveScreen(%d)\n", mode); unblank = xf86IsUnblank(mode); if (unblank) SetTimeSinceLastInputEvent(); if ((pScrn != NULL) && pScrn->vtSema) { - if (unblank) RADEONUnblank(pScrn); - else RADEONBlank(pScrn); + if (unblank) + RADEONUnblank(pScrn); + else + RADEONBlank(pScrn); } return TRUE; } @@ -6520,7 +5451,7 @@ RADEONResetDPI(ScrnInfoPtr pScrn, Bool force) } } -_X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); @@ -6535,20 +5466,11 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } #endif - RADEONTRACE(("RADEONSwitchMode() !n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONSwitchMode() !n"); if (info->allowColorTiling) { - if (info->MergedFB) { - if ((((RADEONMergedDisplayModePtr)mode->Private)->CRT1->Flags & - (V_DBLSCAN | V_INTERLACE)) || - (((RADEONMergedDisplayModePtr)mode->Private)->CRT2->Flags & - (V_DBLSCAN | V_INTERLACE))) - info->tilingEnabled = FALSE; - else info->tilingEnabled = TRUE; - } - else { - info->tilingEnabled = (mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; - } + info->tilingEnabled = (mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; #ifdef XF86DRI if (info->directRenderingEnabled && (info->tilingEnabled != tilingOld)) { RADEONSAREAPrivPtr pSAREAPriv; @@ -6564,19 +5486,7 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) if (info->accelOn) RADEON_SYNC(info, pScrn); - if (info->FBDev) { - RADEONSaveFBDevRegisters(pScrn, &info->ModeReg); - - ret = fbdevHWSwitchMode(scrnIndex, mode, flags); - pScrn->displayWidth = fbdevHWGetLineLength(pScrn) - / info->CurrentLayout.pixel_bytes; - - RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg); - } else { - info->IsSwitching = TRUE; - ret = RADEONModeInit(xf86Screens[scrnIndex], mode); - info->IsSwitching = FALSE; - } + ret = xf86SetSingleMode (pScrn, mode, RR_Rotate_0); if (info->tilingEnabled != tilingOld) { /* need to redraw front buffer, I guess this can be considered a hack ? */ @@ -6601,10 +5511,7 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) /* Since RandR (indirectly) uses SwitchMode(), we need to * update our Xinerama info here, too, in case of resizing */ - if (info->MergedFB) { - RADEONMergedFBResetDpi(pScrn, FALSE); - RADEONUpdateXineramaScreenInfo(pScrn); - } else if(info->constantDPI) { + if(info->constantDPI) { RADEONResetDPI(pScrn, FALSE); } @@ -6614,7 +5521,7 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } #ifdef X_XF86MiscPassMessage -_X_EXPORT Bool RADEONHandleMessage(int scrnIndex, const char* msgtype, +Bool RADEONHandleMessage(int scrnIndex, const char* msgtype, const char* msgval, char** retmsg) { ErrorF("RADEONHandleMessage(%d, \"%s\", \"%s\", retmsg)\n", scrnIndex, @@ -6625,7 +5532,7 @@ _X_EXPORT Bool RADEONHandleMessage(int scrnIndex, const char* msgtype, #endif /* Used to disallow modes that are not supported by the hardware */ -_X_EXPORT ModeStatus RADEONValidMode(int scrnIndex, DisplayModePtr mode, +ModeStatus RADEONValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flag) { /* There are problems with double scan mode at high clocks @@ -6642,18 +5549,19 @@ _X_EXPORT ModeStatus RADEONValidMode(int scrnIndex, DisplayModePtr mode, /* Adjust viewport into virtual desktop such that (0,0) in viewport * space is (x,y) in virtual space. */ -void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) +void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, Bool crtc2) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - int reg, Base, regcntl, crtcoffsetcntl, xytilereg, crtcxytile = 0; + int Base, reg, regcntl, crtcoffsetcntl, xytilereg, crtcxytile = 0; #ifdef XF86DRI RADEONSAREAPrivPtr pSAREAPriv; XF86DRISAREAPtr pSAREA; #endif #if 0 /* Verbose */ - RADEONTRACE(("RADEONDoAdjustFrame(%d,%d,%d)\n", x, y, clone)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONDoAdjustFrame(%d,%d,%d)\n", x, y, clone); #endif if (info->showCache && y) { @@ -6673,12 +5581,12 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) pick up the new offset value at the end of each scanline, but the new offset_cntl value only after a vsync. We'd probably need to wait (in drm) for vsync and only then update OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ - if (clone || info->IsSecondary) { - reg = RADEON_CRTC2_OFFSET; + if (crtc2) { + reg = RADEON_CRTC2_OFFSET; regcntl = RADEON_CRTC2_OFFSET_CNTL; xytilereg = R300_CRTC2_TILE_X0_Y0; } else { - reg = RADEON_CRTC_OFFSET; + reg = RADEON_CRTC_OFFSET; regcntl = RADEON_CRTC_OFFSET_CNTL; xytilereg = R300_CRTC_TILE_X0_Y0; } @@ -6730,7 +5638,7 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) /* can't get at sarea in a semi-sane way? */ pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); - if (clone || info->IsSecondary) { + if (crtc2) { pSAREAPriv->crtc2_base = Base; } else { @@ -6748,20 +5656,23 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) } #endif - OUTREG(reg, Base); - if (IS_R300_VARIANT) { - OUTREG(xytilereg, crtcxytile); + OUTREG(xytilereg, crtcxytile); } else { - OUTREG(regcntl, crtcoffsetcntl); + OUTREG(regcntl, crtcoffsetcntl); } + OUTREG(reg, Base); } -_X_EXPORT void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) +void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output = config->output[config->compat_output]; + xf86CrtcPtr crtc = output->crtc; #ifdef XF86DRI if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); @@ -6770,14 +5681,16 @@ _X_EXPORT void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) if (info->accelOn) RADEON_SYNC(info, pScrn); - if(info->MergedFB) { - RADEONAdjustFrameMerged(scrnIndex, x, y, flags); - } else if (info->FBDev) { - fbdevHWAdjustFrame(scrnIndex, x, y, flags); - } else { - RADEONDoAdjustFrame(pScrn, x, y, FALSE); + if (crtc && crtc->enabled) { + if (crtc == pRADEONEnt->pCrtc[0]) + RADEONDoAdjustFrame(pScrn, crtc->desiredX + x, crtc->desiredY + y, FALSE); + else + RADEONDoAdjustFrame(pScrn, crtc->desiredX + x, crtc->desiredY + y, TRUE); + crtc->x = output->initial_x + x; + crtc->y = output->initial_y + y; } + #ifdef XF86DRI if (info->CPStarted && pScrn->pScreen) DRIUnlock(pScrn->pScreen); #endif @@ -6786,15 +5699,18 @@ _X_EXPORT void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) /* Called when VT switching back to the X server. Reinitialize the * video mode. */ -_X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) +Bool RADEONEnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; - RADEONTRACE(("RADEONEnterVT\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONEnterVT\n"); - if (INREG(RADEON_CONFIG_MEMSIZE) == 0) { /* Softboot V_BIOS */ + if ((INREG(RADEON_CONFIG_MEMSIZE)) == 0) { /* Softboot V_BIOS */ xf86Int10InfoPtr pInt; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "zero MEMSIZE, probably at D3cold. Re-POSTing via int10.\n"); @@ -6809,18 +5725,25 @@ _X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) /* Makes sure the engine is idle before doing anything */ RADEONWaitForIdleMMIO(pScrn); - if (info->FBDev) { - unsigned char *RADEONMMIO = info->MMIO; - if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE; - info->PaletteSavedOnVT = FALSE; - info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); + pScrn->vtSema = TRUE; + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + /* Mark that we'll need to re-set the mode for sure */ + memset(&crtc->mode, 0, sizeof(crtc->mode)); + if (!crtc->desiredMode.CrtcHDisplay) { + crtc->desiredMode = *RADEONCrtcFindClosestMode (crtc, pScrn->currentMode); + crtc->desiredRotation = RR_Rotate_0; + crtc->desiredX = 0; + crtc->desiredY = 0; + } - RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg); - } else - if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; + if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation, + crtc->desiredX, crtc->desiredY)) + return FALSE; - if (!info->IsSecondary) - RADEONRestoreSurfaces(pScrn, &info->ModeReg); + } + + RADEONRestoreSurfaces(pScrn, &info->ModeReg); #ifdef XF86DRI if (info->directRenderingEnabled) { if (info->cardType == CARD_PCIE && info->pKernelDRMVersion->version_minor >= 19 && info->FbSecureSize) @@ -6830,8 +5753,10 @@ _X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) } /* get the DRI back into shape after resume */ + RADEONDRISetVBlankInterrupt (pScrn, TRUE); RADEONDRIResume(pScrn->pScreen); RADEONAdjustMemMapRegisters(pScrn, &info->ModeReg); + } #endif /* this will get XVideo going again, but only if XVideo was initialised @@ -6849,7 +5774,7 @@ _X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) } #endif - pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + // pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); return TRUE; } @@ -6857,15 +5782,17 @@ _X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) /* Called when VT switching away from the X server. Restore the * original text mode. */ -_X_EXPORT void RADEONLeaveVT(int scrnIndex, int flags) +void RADEONLeaveVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONSavePtr save = &info->ModeReg; - RADEONTRACE(("RADEONLeaveVT\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONLeaveVT\n"); #ifdef XF86DRI if (RADEONPTR(pScrn)->directRenderingInited) { + + RADEONDRISetVBlankInterrupt (pScrn, FALSE); DRILock(pScrn->pScreen, 0); RADEONCP_STOP(pScrn, info); @@ -6874,21 +5801,26 @@ _X_EXPORT void RADEONLeaveVT(int scrnIndex, int flags) /* we need to backup the PCIE GART TABLE from fb memory */ memcpy(info->pciGartBackup, (info->FB + info->pciGartOffset), info->pciGartSize); } - } -#endif - - if (info->FBDev) { - RADEONSavePalette(pScrn, save); - info->PaletteSavedOnVT = TRUE; - RADEONSaveFBDevRegisters(pScrn, &info->ModeReg); - - fbdevHWLeaveVT(scrnIndex,flags); + /* Make sure 3D clients will re-upload textures to video RAM */ + if (info->textureSize) { + RADEONSAREAPrivPtr pSAREAPriv = + (RADEONSAREAPrivPtr)DRIGetSAREAPrivate(pScrn->pScreen); + drmTextureRegionPtr list = pSAREAPriv->texList[0]; + int age = ++pSAREAPriv->texAge[0], i = 0; + + do { + list[i].age = age; + i = list[i].next; + } while (i != 0); + } } +#endif RADEONRestore(pScrn); - RADEONTRACE(("Ok, leaving now...\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Ok, leaving now...\n"); } /* Called at the end of each server generation. Restore the original @@ -6900,7 +5832,8 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONTRACE(("RADEONCloseScreen\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONCloseScreen\n"); /* Mark acceleration as stopped or we might try to access the engine at * wrong times, especially if we had DRI, after DRI has been stopped @@ -6929,11 +5862,11 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) #endif /* USE_XAA */ if (pScrn->vtSema) { - RADEONDisplayPowerManagementSet(pScrn, DPMSModeOn, 0); RADEONRestore(pScrn); } - RADEONTRACE(("Disposing accel...\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Disposing accel...\n"); #ifdef USE_EXA if (info->exa) { exaDriverFini(pScreen); @@ -6953,14 +5886,17 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) } #endif /* USE_XAA */ - RADEONTRACE(("Disposing cusor info\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Disposing cusor info\n"); if (info->cursor) xf86DestroyCursorInfoRec(info->cursor); info->cursor = NULL; - RADEONTRACE(("Disposing DGA\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Disposing DGA\n"); if (info->DGAModes) xfree(info->DGAModes); info->DGAModes = NULL; - RADEONTRACE(("Unmapping memory\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Unmapping memory\n"); RADEONUnmapMem(pScrn); pScrn->vtSema = FALSE; @@ -6972,50 +5908,17 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) return (*pScreen->CloseScreen)(scrnIndex, pScreen); } -_X_EXPORT void RADEONFreeScreen(int scrnIndex, int flags) +void RADEONFreeScreen(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONTRACE(("RADEONFreeScreen\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONFreeScreen\n"); /* when server quits at PreInit, we don't need do this anymore*/ if (!info) return; - if(info->MergedFB) { - if(pScrn->modes) { - pScrn->currentMode = pScrn->modes; - do { - DisplayModePtr p = pScrn->currentMode->next; - if(pScrn->currentMode->Private) - xfree(pScrn->currentMode->Private); - xfree(pScrn->currentMode); - pScrn->currentMode = p; - } while(pScrn->currentMode != pScrn->modes); - } - pScrn->currentMode = info->CRT1CurrentMode; - pScrn->modes = info->CRT1Modes; - info->CRT1CurrentMode = NULL; - info->CRT1Modes = NULL; - - if(info->CRT2pScrn) { - if(info->CRT2pScrn->modes) { - while(info->CRT2pScrn->modes) - xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); - } - if(info->CRT2pScrn->monitor) { - if(info->CRT2pScrn->monitor->Modes) { - while(info->CRT2pScrn->monitor->Modes) - xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); - } - if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); - xfree(info->CRT2pScrn->monitor); - } - xfree(info->CRT2pScrn); - info->CRT2pScrn = NULL; - } - } - #ifdef WITH_VGAHW if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec")) vgaHWFreeHWRec(pScrn); @@ -7023,235 +5926,6 @@ _X_EXPORT void RADEONFreeScreen(int scrnIndex, int flags) RADEONFreeRec(pScrn); } -static void -RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONConnector *connector; - char *strptr; - char *default_hsync = "28-33"; - char *default_vrefresh = "43-72"; - Bool val; - Bool default_range = FALSE; - static const char *mybadparm = "\"%s\" is is not a valid parameter for option \"%s\"\n"; - - if (info->FBDev == TRUE) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "MergedFB does not work with Option UseFBDev, MergedFB mode is disabled\n"); - info->MergedFB = FALSE; - return; - } - - /* collect MergedFB options */ - info->MergedFB = TRUE; - info->UseRADEONXinerama = TRUE; - info->CRT2IsScrn0 = FALSE; - info->CRT2Position = radeonClone; - info->MergedFBXDPI = info->MergedFBYDPI = 0; - info->CRT1XOffs = info->CRT1YOffs = info->CRT2XOffs = info->CRT2YOffs = 0; - info->NonRect = info->HaveNonRect = info->HaveOffsRegions = FALSE; - info->MBXNR1XMAX = info->MBXNR1YMAX = info->MBXNR2XMAX = info->MBXNR2YMAX = 65536; - info->MouseRestrictions = TRUE; - - if (info->MergeType == MT_NONE) { - info->MergedFB = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to detect secondary monitor, MergedFB/Clone mode disabled\n"); - } else if ((connector = RADEONGetCrtcConnector(pScrn, 2))) { - if (!connector->MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to detect secondary monitor DDC, default HSync and VRefresh used\n"); - default_range = TRUE; - } - } - - if (xf86GetOptValBool(info->Options, OPTION_MERGEDFB, &val)) { - if (val) { - info->MergedFB = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "MergedFB mode forced on.\n"); - } else { - info->MergedFB = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "MergedFB mode forced off.\n"); - } - } - - /* Do some MergedFB mode initialisation */ - if(info->MergedFB) { - info->CRT2pScrn = xalloc(sizeof(ScrnInfoRec)); - if(!info->CRT2pScrn) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate memory for merged pScrn, MergedFB mode is disabled\n"); - info->MergedFB = FALSE; - } else { - memcpy(info->CRT2pScrn, pScrn, sizeof(ScrnInfoRec)); - } - } - if(info->MergedFB) { - int result, ival; - Bool valid = FALSE; - char *tempstr; - strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2POS); - if (strptr) { - tempstr = xalloc(strlen(strptr) + 1); - result = sscanf(strptr, "%s %d", tempstr, &ival); - } else { /* Not specified - default is "Clone" */ - tempstr = NULL; - result = 0; - info->CRT2Position = radeonClone; - valid = TRUE; - } - if(result >= 1) { - if(!xf86NameCmp(tempstr,"LeftOf")) { - info->CRT2Position = radeonLeftOf; - valid = TRUE; - if(result == 2) { - if(ival < 0) info->CRT1YOffs = -ival; - else info->CRT2YOffs = ival; - } - info->CRT2IsScrn0 = TRUE; - } else if(!xf86NameCmp(tempstr,"RightOf")) { - info->CRT2Position = radeonRightOf; - valid = TRUE; - if(result == 2) { - if(ival < 0) info->CRT1YOffs = -ival; - else info->CRT2YOffs = ival; - } - info->CRT2IsScrn0 = FALSE; - } else if(!xf86NameCmp(tempstr,"Above")) { - info->CRT2Position = radeonAbove; - valid = TRUE; - if(result == 2) { - if(ival < 0) info->CRT1XOffs = -ival; - else info->CRT2XOffs = ival; - } - info->CRT2IsScrn0 = FALSE; - } else if(!xf86NameCmp(tempstr,"Below")) { - info->CRT2Position = radeonBelow; - valid = TRUE; - if(result == 2) { - if(ival < 0) info->CRT1XOffs = -ival; - else info->CRT2XOffs = ival; - } - info->CRT2IsScrn0 = TRUE; - } else if(!xf86NameCmp(tempstr,"Clone")) { - info->CRT2Position = radeonClone; - if(result == 1) valid = TRUE; - /*info->CRT2IsScrn0 = TRUE;*/ - } - } - if(!valid) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "\"%s\" is not a valid parameter for Option \"CRT2Position\"\n", strptr); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid parameters are \"RightOf\", \"LeftOf\", \"Above\", \"Below\", or \"Clone\"\n"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Except for \"Clone\", the parameter may be followed by an integer.\n"); - } - xfree(tempstr); - - strptr = (char *)xf86GetOptValString(info->Options, OPTION_METAMODES); - if(strptr) { - info->MetaModes = xalloc(strlen(strptr) + 1); - if(info->MetaModes) memcpy(info->MetaModes, strptr, strlen(strptr) + 1); - } - strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2HSYNC); - if(strptr) { - info->CRT2HSync = xalloc(strlen(strptr) + 1); - if(info->CRT2HSync) memcpy(info->CRT2HSync, strptr, strlen(strptr) + 1); - } - strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2VREFRESH); - if(strptr) { - info->CRT2VRefresh = xalloc(strlen(strptr) + 1); - if(info->CRT2VRefresh) memcpy(info->CRT2VRefresh, strptr, strlen(strptr) + 1); - } - - if(xf86GetOptValBool(info->Options, OPTION_RADEONXINERAMA, &val)) { - if (!val) - info->UseRADEONXinerama = FALSE; - } - if(info->UseRADEONXinerama) { - if(xf86GetOptValBool(info->Options, OPTION_CRT2ISSCRN0, &val)) { - if(val) info->CRT2IsScrn0 = TRUE; - else info->CRT2IsScrn0 = FALSE; - } - if(xf86GetOptValBool(info->Options, OPTION_MERGEDFBNONRECT, &val)) { - info->NonRect = val ? TRUE : FALSE; - } - if(xf86GetOptValBool(info->Options, OPTION_MERGEDFBMOUSER, &val)) { - info->MouseRestrictions = val ? TRUE : FALSE; - } - } - strptr = (char *)xf86GetOptValString(info->Options, OPTION_MERGEDDPI); - if(strptr) { - int val1 = 0, val2 = 0; - sscanf(strptr, "%d %d", &val1, &val2); - if(val1 && val2) { - info->MergedFBXDPI = val1; - info->MergedFBYDPI = val2; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, mybadparm, strptr, "MergedDPI"); - } - } - } - - if(info->MergedFB) { - /* fill in monitor */ - info->CRT2pScrn->monitor = xalloc(sizeof(MonRec)); - if(info->CRT2pScrn->monitor) { - DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL; - memcpy(info->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec)); - info->CRT2pScrn->monitor->DDC = NULL; - info->CRT2pScrn->monitor->Modes = NULL; - info->CRT2pScrn->monitor->id = "CRT2 Monitor"; - tempm = pScrn->monitor->Modes; - while(tempm) { - if(!(newm = xalloc(sizeof(DisplayModeRec)))) break; - memcpy(newm, tempm, sizeof(DisplayModeRec)); - if(!(newm->name = xalloc(strlen(tempm->name) + 1))) { - xfree(newm); - break; - } - strcpy(newm->name, tempm->name); - if(!info->CRT2pScrn->monitor->Modes) - info->CRT2pScrn->monitor->Modes = newm; - if(currentm) { - currentm->next = newm; - newm->prev = currentm; - } - currentm = newm; - tempm = tempm->next; - } - - /* xf86SetDDCproperties(info->CRT2pScrn, pRADEONEnt->MonInfo2); */ - - connector = RADEONGetCrtcConnector(pScrn, 2); - info->CRT2pScrn->monitor->DDC = connector ? connector->MonInfo : NULL; - - if (default_range) { - RADEONStrToRanges(info->CRT2pScrn->monitor->hsync, default_hsync, MAX_HSYNC); - RADEONStrToRanges(info->CRT2pScrn->monitor->vrefresh, default_vrefresh, MAX_VREFRESH); - } - if(info->CRT2HSync) { - info->CRT2pScrn->monitor->nHsync = - RADEONStrToRanges(info->CRT2pScrn->monitor->hsync, info->CRT2HSync, MAX_HSYNC); - } - if(info->CRT2VRefresh) { - info->CRT2pScrn->monitor->nVrefresh = - RADEONStrToRanges(info->CRT2pScrn->monitor->vrefresh, info->CRT2VRefresh, MAX_VREFRESH); - } - - } else { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate memory for CRT2 monitor, MergedFB mode disabled.\n"); - if(info->CRT2pScrn) xfree(info->CRT2pScrn); - info->CRT2pScrn = NULL; - info->MergedFB = FALSE; - } - } -} - static void RADEONForceSomeClocks(ScrnInfoPtr pScrn) { /* It appears from r300 and rv100 may need some clocks forced-on */ @@ -7610,21 +6284,3 @@ static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode) break; } } - -_X_EXPORT void RADEONFillInScreenInfo(ScrnInfoPtr pScrn) -{ - pScrn->driverVersion = RADEON_VERSION_CURRENT; - pScrn->driverName = RADEON_DRIVER_NAME; - pScrn->name = RADEON_NAME; - pScrn->PreInit = RADEONPreInit; - pScrn->ScreenInit = RADEONScreenInit; - pScrn->SwitchMode = RADEONSwitchMode; -#ifdef X_XF86MiscPassMessage - pScrn->HandleMessage = RADEONHandleMessage; -#endif - pScrn->AdjustFrame = RADEONAdjustFrame; - pScrn->EnterVT = RADEONEnterVT; - pScrn->LeaveVT = RADEONLeaveVT; - pScrn->FreeScreen = RADEONFreeScreen; - pScrn->ValidMode = RADEONValidMode; -} diff --git a/src/radeon_exa.c b/src/radeon_exa.c index f9bcaceb..d074f08a 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -496,3 +496,20 @@ Bool RADEONSetupMemEXA (ScreenPtr pScreen) return TRUE; } + +#ifdef XF86DRI + +#ifndef ExaOffscreenMarkUsed +extern void ExaOffscreenMarkUsed(PixmapPtr); +#endif + +unsigned long long +RADEONTexOffsetStart(PixmapPtr pPix) +{ + exaMoveInPixmap(pPix); + ExaOffscreenMarkUsed(pPix); + + return RADEONPTR(xf86Screens[pPix->drawable.pScreen->myNum])->fbLocation + + exaGetPixmapOffset(pPix); +} +#endif diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c index 0d847d1c..c356de7c 100644 --- a/src/radeon_exa_funcs.c +++ b/src/radeon_exa_funcs.c @@ -59,14 +59,30 @@ #include "exa.h" +static int +FUNC_NAME(RADEONMarkSync)(ScreenPtr pScreen) +{ + RINFO_FROM_SCREEN(pScreen); + + TRACE; + + return ++info->exaSyncMarker; +} + static void FUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + TRACE; - FUNC_NAME(RADEONWaitForIdle)(xf86Screens[pScreen->myNum]); + if (info->exaMarkerSynced != marker) { + FUNC_NAME(RADEONWaitForIdle)(pScrn); + info->exaMarkerSynced = marker; + } - RADEONPTR(xf86Screens[pScreen->myNum])->engineMode = EXA_ENGINEMODE_UNKNOWN; + RADEONPTR(pScrn)->engineMode = EXA_ENGINEMODE_UNKNOWN; } static Bool @@ -444,6 +460,8 @@ FUNC_NAME(RADEONDownloadFromScreen)(PixmapPtr pSrc, int x, int y, int w, int h, drmCommandWriteRead(info->drmFD, DRM_RADEON_INDIRECT, &indirect, sizeof(drmRadeonIndirect)); + info->exaMarkerSynced = info->exaSyncMarker; + return TRUE; } #endif @@ -504,6 +522,7 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) info->exa->Copy = FUNC_NAME(RADEONCopy); info->exa->DoneCopy = FUNC_NAME(RADEONDoneCopy); + info->exa->MarkSync = FUNC_NAME(RADEONMarkSync); info->exa->WaitMarker = FUNC_NAME(RADEONSync); info->exa->UploadToScreen = FUNC_NAME(RADEONUploadToScreen); info->exa->DownloadFromScreen = FUNC_NAME(RADEONDownloadFromScreen); diff --git a/src/radeon_mergedfb.c b/src/radeon_mergedfb.c deleted file mode 100644 index 820ba4ba..00000000 --- a/src/radeon_mergedfb.c +++ /dev/null @@ -1,2089 +0,0 @@ -/* - * Copyright 2003 Alex Deucher. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation on the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL ALEX DEUCHER, OR ANY OTHER - * CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* - * Authors: - * Alex Deucher <agd5f@yahoo.com> - * Based, in large part, on the sis driver by Thomas Winischhofer. - */ - -#include <string.h> -#include <stdio.h> - -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86Resources.h" -#include "xf86_OSproc.h" -#include "extnsionst.h" /* required */ -#include <X11/extensions/panoramiXproto.h> /* required */ -#include "dixstruct.h" -#include "vbe.h" - - -#include "radeon.h" -#include "radeon_reg.h" -#include "radeon_macros.h" -#include "radeon_mergedfb.h" - -/* psuedo xinerama support */ -static unsigned char RADEONXineramaReqCode = 0; -int RADEONXineramaPixWidth = 0; -int RADEONXineramaPixHeight = 0; -int RADEONXineramaNumScreens = 0; -RADEONXineramaData *RADEONXineramadataPtr = NULL; -static int RADEONXineramaGeneration; -Bool RADEONnoPanoramiXExtension = TRUE; - -int RADEONProcXineramaQueryVersion(ClientPtr client); -int RADEONProcXineramaGetState(ClientPtr client); -int RADEONProcXineramaGetScreenCount(ClientPtr client); -int RADEONProcXineramaGetScreenSize(ClientPtr client); -int RADEONProcXineramaIsActive(ClientPtr client); -int RADEONProcXineramaQueryScreens(ClientPtr client); -int RADEONSProcXineramaDispatch(ClientPtr client); - -static void -RADEONChooseCursorCRTC(ScrnInfoPtr pScrn1, int x, int y); - -/* mergedfb functions */ -/* Helper function for CRT2 monitor vrefresh/hsync options - * (Taken from mga, sis drivers) - */ -int -RADEONStrToRanges(range *r, char *s, int max) -{ - float num = 0.0; - int rangenum = 0; - Bool gotdash = FALSE; - Bool nextdash = FALSE; - char* strnum = NULL; - do { - switch(*s) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '.': - if(strnum == NULL) { - strnum = s; - gotdash = nextdash; - nextdash = FALSE; - } - break; - case '-': - case ' ': - case 0: - if(strnum == NULL) break; - sscanf(strnum, "%f", &num); - strnum = NULL; - if(gotdash) - r[rangenum - 1].hi = num; - else { - r[rangenum].lo = num; - r[rangenum].hi = num; - rangenum++; - } - if(*s == '-') nextdash = (rangenum != 0); - else if(rangenum >= max) return rangenum; - break; - default : - return 0; - } - } while(*(s++) != 0); - - return rangenum; -} - -/* Copy and link two modes (i, j) for merged-fb mode - * (Taken from mga, sis drivers) - * Copys mode i, merges j to copy of i, links the result to dest, and returns it. - * Links i and j in Private record. - * If dest is NULL, return value is copy of i linked to itself. - * For mergedfb auto-config, we only check the dimension - * against virtualX/Y, if they were user-provided. - */ -static DisplayModePtr -RADEONCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, - DisplayModePtr i, DisplayModePtr j, - RADEONScrn2Rel srel) -{ - DisplayModePtr mode; - int dx = 0,dy = 0; - RADEONInfoPtr info = RADEONPTR(pScrn); - - if(!((mode = xalloc(sizeof(DisplayModeRec))))) return dest; - memcpy(mode, i, sizeof(DisplayModeRec)); - if(!((mode->Private = xalloc(sizeof(RADEONMergedDisplayModeRec))))) { - xfree(mode); - return dest; - } - ((RADEONMergedDisplayModePtr)mode->Private)->CRT1 = i; - ((RADEONMergedDisplayModePtr)mode->Private)->CRT2 = j; - ((RADEONMergedDisplayModePtr)mode->Private)->CRT2Position = srel; - mode->PrivSize = 0; - - switch(srel) { - case radeonLeftOf: - case radeonRightOf: - if(!(pScrn->display->virtualX)) { - dx = i->HDisplay + j->HDisplay; - } else { - dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay); - } - dx -= mode->HDisplay; - if(!(pScrn->display->virtualY)) { - dy = max(i->VDisplay, j->VDisplay); - } else { - dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); - } - dy -= mode->VDisplay; - break; - case radeonAbove: - case radeonBelow: - if(!(pScrn->display->virtualY)) { - dy = i->VDisplay + j->VDisplay; - } else { - dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay); - } - dy -= mode->VDisplay; - if(!(pScrn->display->virtualX)) { - dx = max(i->HDisplay, j->HDisplay); - } else { - dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); - } - dx -= mode->HDisplay; - break; - case radeonClone: - if(!(pScrn->display->virtualX)) { - dx = max(i->HDisplay, j->HDisplay); - } else { - dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay)); - } - dx -= mode->HDisplay; - if(!(pScrn->display->virtualY)) { - dy = max(i->VDisplay, j->VDisplay); - } else { - dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay)); - } - dy -= mode->VDisplay; - break; - } - mode->HDisplay += dx; - mode->HSyncStart += dx; - mode->HSyncEnd += dx; - mode->HTotal += dx; - mode->VDisplay += dy; - mode->VSyncStart += dy; - mode->VSyncEnd += dy; - mode->VTotal += dy; - - /* Provide a fake VRefresh/DotClock in order to trick the vidmode - * extension to allow selecting among a number of modes whose merged result - * looks identical but consists of different modes for CRT1 and CRT2 - */ - mode->VRefresh = (float)((i->Clock * 1000.0 / i->HTotal / i->VTotal) * 100 + - (j->Clock * 1000.0 / j->HTotal / j->VTotal)); - - mode->Clock = (int)(mode->VRefresh * 0.001 * mode->HTotal * mode->VTotal); - - if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > - (pScrn->videoRam * 1024)) || - (mode->HDisplay > 8191) || - (mode->VDisplay > 8191) ) { - - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n", - mode->name, mode->HDisplay, mode->VDisplay); - xfree(mode->Private); - xfree(mode); - - return dest; - } - - if(srel != radeonClone) { - info->AtLeastOneNonClone = TRUE; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d%s\n", - i->name, i->HDisplay, i->VDisplay, j->name, j->HDisplay, j->VDisplay, - mode->HDisplay, mode->VDisplay, (srel == radeonClone) ? " (Clone)" : ""); - - mode->next = mode; - mode->prev = mode; - - if(dest) { - mode->next = dest->next; /* Insert node after "dest" */ - dest->next->prev = mode; - mode->prev = dest; - dest->next = mode; - } - - return mode; -} - -/* Helper function to find a mode from a given name - * (Taken from mga, sis drivers) - */ -static DisplayModePtr -RADEONGetModeFromName(char* str, DisplayModePtr i) -{ - DisplayModePtr c = i; - if(!i) return NULL; - do { - if(strcmp(str, c->name) == 0) return c; - c = c->next; - } while(c != i); - return NULL; -} - -static DisplayModePtr -RADEONFindWidestTallestMode(DisplayModePtr i, Bool tallest) -{ - DisplayModePtr c = i, d = NULL; - int max = 0; - if(!i) return NULL; - do { - if(tallest) { - if(c->VDisplay > max) { - max = c->VDisplay; - d = c; - } - } else { - if(c->HDisplay > max) { - max = c->HDisplay; - d = c; - } - } - c = c->next; - } while(c != i); - return d; -} - -static void -RADEONFindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, - DisplayModePtr *a, DisplayModePtr *b) -{ - DisplayModePtr c = i, d; - int max = 0; - Bool foundone; - - (*a) = (*b) = NULL; - - if(!i || !j) return; - - do { - d = j; - foundone = FALSE; - do { - if( (c->HDisplay == d->HDisplay) && - (c->VDisplay == d->VDisplay) ) { - foundone = TRUE; - break; - } - d = d->next; - } while(d != j); - if(foundone) { - if(tallest) { - if(c->VDisplay > max) { - max = c->VDisplay; - (*a) = c; - (*b) = d; - } - } else { - if(c->HDisplay > max) { - max = c->HDisplay; - (*a) = c; - (*b) = d; - } - } - } - c = c->next; - } while(c != i); -} - -static DisplayModePtr -RADEONGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, - DisplayModePtr i, DisplayModePtr j, - RADEONScrn2Rel srel) -{ - - RADEONInfoPtr info = RADEONPTR(pScrn); - DisplayModePtr mode1 = NULL; - DisplayModePtr mode2 = NULL; - DisplayModePtr mode3 = NULL; - DisplayModePtr mode4 = NULL; - DisplayModePtr result = NULL; - - info->AtLeastOneNonClone = FALSE; - - /* Now build a default list of MetaModes. - * - Non-clone: If the user enabled NonRectangular, we use the - * largest mode for each CRT1 and CRT2. If not, we use the largest - * common mode for CRT1 and CRT2 (if available). Additionally, and - * regardless if the above, we produce a clone mode consisting of - * the largest common mode (if available) in order to use DGA. - * - Clone: If the (global) CRT2Position is Clone, we use the - * largest common mode if available, otherwise the first two modes - * in each list. - */ - - switch(srel) { - case radeonLeftOf: - case radeonRightOf: - mode1 = RADEONFindWidestTallestMode(i, FALSE); - mode2 = RADEONFindWidestTallestMode(j, FALSE); - RADEONFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); - break; - case radeonAbove: - case radeonBelow: - mode1 = RADEONFindWidestTallestMode(i, TRUE); - mode2 = RADEONFindWidestTallestMode(j, TRUE); - RADEONFindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); - break; - case radeonClone: - RADEONFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); - if(mode3 && mode4) { - mode1 = mode3; - mode2 = mode4; - } else { - mode1 = i; - mode2 = j; - } - } - - if(srel != radeonClone) { - if(mode3 && mode4 && !info->NonRect) { - mode1 = mode3; - mode2 = mode2; - } - } - - if(mode1 && mode2) { - result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, srel); - } - - if(srel != radeonClone) { - if(mode3 && mode4) { - result = RADEONCopyModeNLink(pScrn, result, mode3, mode4, radeonClone); - } - } - return result; -} - -/* Generate the merged-fb mode modelist - * (Taken from mga, sis drivers) - */ -static DisplayModePtr -RADEONGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str, - DisplayModePtr i, DisplayModePtr j, - RADEONScrn2Rel srel) -{ - char* strmode = str; - char modename[256]; - Bool gotdash = FALSE; - char gotsep = 0; - RADEONScrn2Rel sr; - DisplayModePtr mode1 = NULL; - DisplayModePtr mode2 = NULL; - DisplayModePtr result = NULL; - int myslen; - RADEONInfoPtr info = RADEONPTR(pScrn); - - info->AtLeastOneNonClone = FALSE; - - do { - switch(*str) { - case 0: - case '-': - case '+': - case ' ': - case ',': - case ';': - if(strmode != str) { - - myslen = str - strmode; - if(myslen > 255) myslen = 255; - strncpy(modename, strmode, myslen); - modename[myslen] = 0; - - if(gotdash) { - if(mode1 == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Error parsing MetaModes parameter\n"); - return NULL; - } - mode2 = RADEONGetModeFromName(modename, j); - if(!mode2) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Mode \"%s\" is not a supported mode for CRT2\n", modename); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename); - mode1 = NULL; - gotsep = 0; - } - } else { - mode1 = RADEONGetModeFromName(modename, i); - if(!mode1) { - char* tmps = str; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Mode \"%s\" is not a supported mode for CRT1\n", modename); - while(*tmps == ' ' || *tmps == ';') tmps++; - /* skip the next mode */ - if(*tmps == '-' || *tmps == '+' || *tmps == ',') { - tmps++; - /* skip spaces */ - while(*tmps == ' ' || *tmps == ';') tmps++; - /* skip modename */ - while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++; - myslen = tmps - strmode; - if(myslen > 255) myslen = 255; - strncpy(modename,strmode,myslen); - modename[myslen] = 0; - str = tmps-1; - } - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "\t(Skipping metamode \"%s\")\n", modename); - mode1 = NULL; - gotsep = 0; - } - } - gotdash = FALSE; - } - strmode = str + 1; - gotdash |= (*str == '-' || *str == '+' || *str == ','); - if (*str == '-' || *str == '+' || *str == ',') - gotsep = *str; - - if(*str != 0) break; - /* Fall through otherwise */ - - default: - if(!gotdash && mode1) { - sr = srel; - if(gotsep == '+') sr = radeonClone; - if(!mode2) { - mode2 = RADEONGetModeFromName(mode1->name, j); - sr = radeonClone; - } - if(!mode2) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Mode \"%s\" is not a supported mode for CRT2\n", mode1->name); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "\t(Skipping metamode \"%s\")\n", modename); - mode1 = NULL; - } else { - result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, sr); - mode1 = NULL; - mode2 = NULL; - } - gotsep = 0; - } - break; - - } - - } while(*(str++) != 0); - - return result; -} - -DisplayModePtr -RADEONGenerateModeList(ScrnInfoPtr pScrn, char* str, - DisplayModePtr i, DisplayModePtr j, - RADEONScrn2Rel srel) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if(str != NULL) { - return(RADEONGenerateModeListFromMetaModes(pScrn, str, i, j, srel)); - } else { - if (srel == radeonClone ) { - DisplayModePtr p, q, result = NULL; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Clone mode, list all common modes\n"); - for (p = i; p->next != i; p = p->next) - for (q = j; q->next != j; q = q->next) - if ((p->HDisplay == q->HDisplay) && - (p->VDisplay == q->VDisplay)) - result = RADEONCopyModeNLink(pScrn, result, p, q, srel); - return result; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No MetaModes given, linking %s modes by default\n", - (info->NonRect ? - (((srel == radeonLeftOf) || (srel == radeonRightOf)) ? "widest" : "tallest") - : - (((srel == radeonLeftOf) || (srel == radeonRightOf)) ? "widest common" : "tallest common")) ); - return(RADEONGenerateModeListFromLargestModes(pScrn, i, j, srel)); - } - } -} - -void -RADEONRecalcDefaultVirtualSize(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - DisplayModePtr mode, bmode; - int maxh, maxv; - static const char *str = "MergedFB: Virtual %s %d\n"; - static const char *errstr = "Virtual %s to small for given CRT2Position offset\n"; - - mode = bmode = pScrn->modes; - maxh = maxv = 0; - do { - if(mode->HDisplay > maxh) maxh = mode->HDisplay; - if(mode->VDisplay > maxv) maxv = mode->VDisplay; - mode = mode->next; - } while(mode != bmode); - maxh += info->CRT1XOffs + info->CRT2XOffs; - maxv += info->CRT1YOffs + info->CRT2YOffs; - - if(!(pScrn->display->virtualX)) { - if(maxh > 8191) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Virtual width with CRT2Position offset beyond hardware specs\n"); - info->CRT1XOffs = info->CRT2XOffs = 0; - maxh -= (info->CRT1XOffs + info->CRT2XOffs); - } - pScrn->virtualX = maxh; - pScrn->displayWidth = maxh; - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); - } else { - if(maxh < pScrn->display->virtualX) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); - info->CRT1XOffs = info->CRT2XOffs = 0; - } - } - - if(!(pScrn->display->virtualY)) { - pScrn->virtualY = maxv; - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); - } else { - if(maxv < pScrn->display->virtualY) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); - info->CRT1YOffs = info->CRT2YOffs = 0; - } - } -} - -/* Pseudo-Xinerama extension for MergedFB mode */ -void -RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) -{ - RADEONInfoPtr info = RADEONPTR(pScrn1); - ScrnInfoPtr pScrn2 = NULL; - int crt1scrnnum = 0, crt2scrnnum = 1; - int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0; - int realvirtX, realvirtY; - DisplayModePtr currentMode, firstMode; - Bool infochanged = FALSE; - Bool usenonrect = info->NonRect; - const char *rectxine = "\t... setting up rectangular Xinerama layout\n"; - - info->MBXNR1XMAX = info->MBXNR1YMAX = info->MBXNR2XMAX = info->MBXNR2YMAX = 65536; - info->HaveNonRect = info->HaveOffsRegions = FALSE; - - if(!info->MergedFB) return; - - if(RADEONnoPanoramiXExtension) return; - - if(!RADEONXineramadataPtr) return; - - if(info->CRT2IsScrn0) { - crt1scrnnum = 1; - crt2scrnnum = 0; - } - - pScrn2 = info->CRT2pScrn; - - /* Attention: Usage of RandR may lead into virtual X and Y values - * actually smaller than our MetaModes! To avoid this, we calculate - * the maxCRT fields here (and not somewhere else, like in CopyNLink) - */ - - /* "Real" virtual: Virtual without the Offset */ - realvirtX = pScrn1->virtualX - info->CRT1XOffs - info->CRT2XOffs; - realvirtY = pScrn1->virtualY - info->CRT1YOffs - info->CRT2YOffs; - - if((info->RADEONXineramaVX != pScrn1->virtualX) || (info->RADEONXineramaVY != pScrn1->virtualY)) { - - if(!(pScrn1->modes)) { - xf86DrvMsg(pScrn1->scrnIndex, X_ERROR, - "Internal error: RADEONUpdateXineramaScreenInfo(): pScrn->modes is NULL\n"); - return; - } - - info->maxCRT1_X1 = info->maxCRT1_X2 = 0; - info->maxCRT1_Y1 = info->maxCRT1_Y2 = 0; - info->maxCRT2_X1 = info->maxCRT2_X2 = 0; - info->maxCRT2_Y1 = info->maxCRT2_Y2 = 0; - info->maxClone_X1 = info->maxClone_X2 = 0; - info->maxClone_Y1 = info->maxClone_Y2 = 0; - - currentMode = firstMode = pScrn1->modes; - - do { - - DisplayModePtr p = currentMode->next; - DisplayModePtr i = ((RADEONMergedDisplayModePtr)currentMode->Private)->CRT1; - DisplayModePtr j = ((RADEONMergedDisplayModePtr)currentMode->Private)->CRT2; - RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)currentMode->Private)->CRT2Position; - - if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && - (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && - (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { - - if(srel != radeonClone) { - if(info->maxCRT1_X1 == i->HDisplay) { - if(info->maxCRT1_X2 < j->HDisplay) { - info->maxCRT1_X2 = j->HDisplay; /* Widest CRT2 mode displayed with widest CRT1 mode */ - } - } else if(info->maxCRT1_X1 < i->HDisplay) { - info->maxCRT1_X1 = i->HDisplay; /* Widest CRT1 mode */ - info->maxCRT1_X2 = j->HDisplay; - } - if(info->maxCRT2_X2 == j->HDisplay) { - if(info->maxCRT2_X1 < i->HDisplay) { - info->maxCRT2_X1 = i->HDisplay; /* Widest CRT1 mode displayed with widest CRT2 mode */ - } - } else if(info->maxCRT2_X2 < j->HDisplay) { - info->maxCRT2_X2 = j->HDisplay; /* Widest CRT2 mode */ - info->maxCRT2_X1 = i->HDisplay; - } - if(info->maxCRT1_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ - if(info->maxCRT1_Y2 < j->VDisplay) { - info->maxCRT1_Y2 = j->VDisplay; - } - } else if(info->maxCRT1_Y1 < i->VDisplay) { - info->maxCRT1_Y1 = i->VDisplay; - info->maxCRT1_Y2 = j->VDisplay; - } - if(info->maxCRT2_Y2 == j->VDisplay) { - if(info->maxCRT2_Y1 < i->VDisplay) { - info->maxCRT2_Y1 = i->VDisplay; - } - } else if(info->maxCRT2_Y2 < j->VDisplay) { - info->maxCRT2_Y2 = j->VDisplay; - info->maxCRT2_Y1 = i->VDisplay; - } - } else { - if(info->maxClone_X1 < i->HDisplay) { - info->maxClone_X1 = i->HDisplay; - } - if(info->maxClone_X2 < j->HDisplay) { - info->maxClone_X2 = j->HDisplay; - } - if(info->maxClone_Y1 < i->VDisplay) { - info->maxClone_Y1 = i->VDisplay; - } - if(info->maxClone_Y2 < j->VDisplay) { - info->maxClone_Y2 = j->VDisplay; - } - } - } - currentMode = p; - - } while((currentMode) && (currentMode != firstMode)); - - info->RADEONXineramaVX = pScrn1->virtualX; - info->RADEONXineramaVY = pScrn1->virtualY; - infochanged = TRUE; - - } - - if((usenonrect) && (info->CRT2Position != radeonClone) && info->maxCRT1_X1) { - switch(info->CRT2Position) { - case radeonLeftOf: - case radeonRightOf: - if((info->maxCRT1_Y1 != realvirtY) && (info->maxCRT2_Y2 != realvirtY)) { - usenonrect = FALSE; - } - break; - case radeonAbove: - case radeonBelow: - if((info->maxCRT1_X1 != realvirtX) && (info->maxCRT2_X2 != realvirtX)) { - usenonrect = FALSE; - } - break; - case radeonClone: - break; - } - - if(infochanged && !usenonrect) { - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Virtual screen size does not match maximum display modes...\n"); - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); - - } - } else if(infochanged && usenonrect) { - usenonrect = FALSE; - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Only clone modes available for this virtual screen size...\n"); - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); - } - - if(info->maxCRT1_X1) { /* Means we have at least one non-clone mode */ - switch(info->CRT2Position) { - case radeonLeftOf: - x1 = min(info->maxCRT1_X2, pScrn1->virtualX - info->maxCRT1_X1); - if(x1 < 0) x1 = 0; - y1 = info->CRT1YOffs; - w1 = pScrn1->virtualX - x1; - h1 = realvirtY; - if((usenonrect) && (info->maxCRT1_Y1 != realvirtY)) { - h1 = info->MBXNR1YMAX = info->maxCRT1_Y1; - info->NonRectDead.x0 = x1; - info->NonRectDead.x1 = x1 + w1 - 1; - info->NonRectDead.y0 = y1 + h1; - info->NonRectDead.y1 = pScrn1->virtualY - 1; - info->HaveNonRect = TRUE; - } - x2 = 0; - y2 = info->CRT2YOffs; - w2 = max(info->maxCRT2_X2, pScrn1->virtualX - info->maxCRT2_X1); - if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; - h2 = realvirtY; - if((usenonrect) && (info->maxCRT2_Y2 != realvirtY)) { - h2 = info->MBXNR2YMAX = info->maxCRT2_Y2; - info->NonRectDead.x0 = x2; - info->NonRectDead.x1 = x2 + w2 - 1; - info->NonRectDead.y0 = y2 + h2; - info->NonRectDead.y1 = pScrn1->virtualY - 1; - info->HaveNonRect = TRUE; - } - break; - case radeonRightOf: - x1 = 0; - y1 = info->CRT1YOffs; - w1 = max(info->maxCRT1_X1, pScrn1->virtualX - info->maxCRT1_X2); - if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; - h1 = realvirtY; - if((usenonrect) && (info->maxCRT1_Y1 != realvirtY)) { - h1 = info->MBXNR1YMAX = info->maxCRT1_Y1; - info->NonRectDead.x0 = x1; - info->NonRectDead.x1 = x1 + w1 - 1; - info->NonRectDead.y0 = y1 + h1; - info->NonRectDead.y1 = pScrn1->virtualY - 1; - info->HaveNonRect = TRUE; - } - x2 = min(info->maxCRT2_X1, pScrn1->virtualX - info->maxCRT2_X2); - if(x2 < 0) x2 = 0; - y2 = info->CRT2YOffs; - w2 = pScrn1->virtualX - x2; - h2 = realvirtY; - if((usenonrect) && (info->maxCRT2_Y2 != realvirtY)) { - h2 = info->MBXNR2YMAX = info->maxCRT2_Y2; - info->NonRectDead.x0 = x2; - info->NonRectDead.x1 = x2 + w2 - 1; - info->NonRectDead.y0 = y2 + h2; - info->NonRectDead.y1 = pScrn1->virtualY - 1; - info->HaveNonRect = TRUE; - } - break; - case radeonAbove: - x1 = info->CRT1XOffs; - y1 = min(info->maxCRT1_Y2, pScrn1->virtualY - info->maxCRT1_Y1); - if(y1 < 0) y1 = 0; - w1 = realvirtX; - h1 = pScrn1->virtualY - y1; - if((usenonrect) && (info->maxCRT1_X1 != realvirtX)) { - w1 = info->MBXNR1XMAX = info->maxCRT1_X1; - info->NonRectDead.x0 = x1 + w1; - info->NonRectDead.x1 = pScrn1->virtualX - 1; - info->NonRectDead.y0 = y1; - info->NonRectDead.y1 = y1 + h1 - 1; - info->HaveNonRect = TRUE; - } - x2 = info->CRT2XOffs; - y2 = 0; - w2 = realvirtX; - h2 = max(info->maxCRT2_Y2, pScrn1->virtualY - info->maxCRT2_Y1); - if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; - if((usenonrect) && (info->maxCRT2_X2 != realvirtX)) { - w2 = info->MBXNR2XMAX = info->maxCRT2_X2; - info->NonRectDead.x0 = x2 + w2; - info->NonRectDead.x1 = pScrn1->virtualX - 1; - info->NonRectDead.y0 = y2; - info->NonRectDead.y1 = y2 + h2 - 1; - info->HaveNonRect = TRUE; - } - break; - case radeonBelow: - x1 = info->CRT1XOffs; - y1 = 0; - w1 = realvirtX; - h1 = max(info->maxCRT1_Y1, pScrn1->virtualY - info->maxCRT1_Y2); - if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; - if((usenonrect) && (info->maxCRT1_X1 != realvirtX)) { - w1 = info->MBXNR1XMAX = info->maxCRT1_X1; - info->NonRectDead.x0 = x1 + w1; - info->NonRectDead.x1 = pScrn1->virtualX - 1; - info->NonRectDead.y0 = y1; - info->NonRectDead.y1 = y1 + h1 - 1; - info->HaveNonRect = TRUE; - } - x2 = info->CRT2XOffs; - y2 = min(info->maxCRT2_Y1, pScrn1->virtualY - info->maxCRT2_Y2); - if(y2 < 0) y2 = 0; - w2 = realvirtX; - h2 = pScrn1->virtualY - y2; - if((usenonrect) && (info->maxCRT2_X2 != realvirtX)) { - w2 = info->MBXNR2XMAX = info->maxCRT2_X2; - info->NonRectDead.x0 = x2 + w2; - info->NonRectDead.x1 = pScrn1->virtualX - 1; - info->NonRectDead.y0 = y2; - info->NonRectDead.y1 = y2 + h2 - 1; - info->HaveNonRect = TRUE; - } - default: - break; - } - - switch(info->CRT2Position) { - case radeonLeftOf: - case radeonRightOf: - if(info->CRT1YOffs) { - info->OffDead1.x0 = x1; - info->OffDead1.x1 = x1 + w1 - 1; - info->OffDead1.y0 = 0; - info->OffDead1.y1 = y1 - 1; - info->OffDead2.x0 = x2; - info->OffDead2.x1 = x2 + w2 - 1; - info->OffDead2.y0 = y2 + h2; - info->OffDead2.y1 = pScrn1->virtualY - 1; - info->HaveOffsRegions = TRUE; - } else if(info->CRT2YOffs) { - info->OffDead1.x0 = x2; - info->OffDead1.x1 = x2 + w2 - 1; - info->OffDead1.y0 = 0; - info->OffDead1.y1 = y2 - 1; - info->OffDead2.x0 = x1; - info->OffDead2.x1 = x1 + w1 - 1; - info->OffDead2.y0 = y1 + h1; - info->OffDead2.y1 = pScrn1->virtualY - 1; - info->HaveOffsRegions = TRUE; - } - break; - case radeonAbove: - case radeonBelow: - if(info->CRT1XOffs) { - info->OffDead1.x0 = x2 + w2; - info->OffDead1.x1 = pScrn1->virtualX - 1; - info->OffDead1.y0 = y2; - info->OffDead1.y1 = y2 + h2 - 1; - info->OffDead2.x0 = 0; - info->OffDead2.x1 = x1 - 1; - info->OffDead2.y0 = y1; - info->OffDead2.y1 = y1 + h1 - 1; - info->HaveOffsRegions = TRUE; - } else if(info->CRT2XOffs) { - info->OffDead1.x0 = x1 + w1; - info->OffDead1.x1 = pScrn1->virtualX - 1; - info->OffDead1.y0 = y1; - info->OffDead1.y1 = y1 + h1 - 1; - info->OffDead2.x0 = 0; - info->OffDead2.x1 = x2 - 1; - info->OffDead2.y0 = y2; - info->OffDead2.y1 = y2 + h2 - 1; - info->HaveOffsRegions = TRUE; - } - default: - break; - } - - } else { /* Only clone-modes left */ - - x1 = x2 = 0; - y1 = y2 = 0; - w1 = w2 = max(info->maxClone_X1, info->maxClone_X2); - h1 = h2 = max(info->maxClone_Y1, info->maxClone_Y2); - - } - - RADEONXineramadataPtr[crt1scrnnum].x = x1; - RADEONXineramadataPtr[crt1scrnnum].y = y1; - RADEONXineramadataPtr[crt1scrnnum].width = w1; - RADEONXineramadataPtr[crt1scrnnum].height = h1; - RADEONXineramadataPtr[crt2scrnnum].x = x2; - RADEONXineramadataPtr[crt2scrnnum].y = y2; - RADEONXineramadataPtr[crt2scrnnum].width = w2; - RADEONXineramadataPtr[crt2scrnnum].height = h2; - - if(infochanged) { - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n", - crt1scrnnum, x1, y1, w1+x1-1, h1+y1-1); - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n", - crt2scrnnum, x2, y2, w2+x2-1, h2+y2-1); - if(info->HaveNonRect) { - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", - info->NonRectDead.x0, info->NonRectDead.y0, - info->NonRectDead.x1, info->NonRectDead.y1); - } - if(info->HaveOffsRegions) { - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", - info->OffDead1.x0, info->OffDead1.y0, - info->OffDead1.x1, info->OffDead1.y1); - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", - info->OffDead2.x0, info->OffDead2.y0, - info->OffDead2.x1, info->OffDead2.y1); - } - if(info->HaveNonRect || info->HaveOffsRegions) { - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Mouse restriction for inaccessible areas is %s\n", - info->MouseRestrictions ? "enabled" : "disabled"); - } - } -} -/* Proc */ - -int -RADEONProcXineramaQueryVersion(ClientPtr client) -{ - xPanoramiXQueryVersionReply rep; - register int n; - - REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = RADEON_XINERAMA_MAJOR_VERSION; - rep.minorVersion = RADEON_XINERAMA_MINOR_VERSION; - if(client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - -int -RADEONProcXineramaGetState(ClientPtr client) -{ - REQUEST(xPanoramiXGetStateReq); - WindowPtr pWin; - xPanoramiXGetStateReply rep; - register int n; - - REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); - pWin = LookupWindow(stuff->window, client); - if(!pWin) return BadWindow; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.state = !RADEONnoPanoramiXExtension; - if(client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swaps (&rep.state, n); - } - WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep); - return client->noClientException; -} - -int -RADEONProcXineramaGetScreenCount(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenCountReq); - WindowPtr pWin; - xPanoramiXGetScreenCountReply rep; - register int n; - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); - pWin = LookupWindow(stuff->window, client); - if(!pWin) return BadWindow; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.ScreenCount = RADEONXineramaNumScreens; - if(client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.ScreenCount, n); - } - WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); - return client->noClientException; -} - -int -RADEONProcXineramaGetScreenSize(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenSizeReq); - WindowPtr pWin; - xPanoramiXGetScreenSizeReply rep; - register int n; - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); - pWin = LookupWindow (stuff->window, client); - if(!pWin) return BadWindow; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.width = RADEONXineramadataPtr[stuff->screen].width; - rep.height = RADEONXineramadataPtr[stuff->screen].height; - if(client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.width, n); - swaps(&rep.height, n); - } - WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); - return client->noClientException; -} - -int -RADEONProcXineramaIsActive(ClientPtr client) -{ - xXineramaIsActiveReply rep; - - REQUEST_SIZE_MATCH(xXineramaIsActiveReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.state = !RADEONnoPanoramiXExtension; - if(client->swapped) { - register int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.state, n); - } - WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep); - return client->noClientException; -} - -int -RADEONProcXineramaQueryScreens(ClientPtr client) -{ - xXineramaQueryScreensReply rep; - - REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.number = (RADEONnoPanoramiXExtension) ? 0 : RADEONXineramaNumScreens; - rep.length = rep.number * sz_XineramaScreenInfo >> 2; - if(client->swapped) { - register int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.number, n); - } - WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep); - - if(!RADEONnoPanoramiXExtension) { - xXineramaScreenInfo scratch; - int i; - - for(i = 0; i < RADEONXineramaNumScreens; i++) { - scratch.x_org = RADEONXineramadataPtr[i].x; - scratch.y_org = RADEONXineramadataPtr[i].y; - scratch.width = RADEONXineramadataPtr[i].width; - scratch.height = RADEONXineramadataPtr[i].height; - if(client->swapped) { - register int n; - swaps(&scratch.x_org, n); - swaps(&scratch.y_org, n); - swaps(&scratch.width, n); - swaps(&scratch.height, n); - } - WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch); - } - } - - return client->noClientException; -} - -static int -RADEONProcXineramaDispatch(ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_PanoramiXQueryVersion: - return RADEONProcXineramaQueryVersion(client); - case X_PanoramiXGetState: - return RADEONProcXineramaGetState(client); - case X_PanoramiXGetScreenCount: - return RADEONProcXineramaGetScreenCount(client); - case X_PanoramiXGetScreenSize: - return RADEONProcXineramaGetScreenSize(client); - case X_XineramaIsActive: - return RADEONProcXineramaIsActive(client); - case X_XineramaQueryScreens: - return RADEONProcXineramaQueryScreens(client); - } - return BadRequest; -} - -/* SProc */ - -static int -RADEONSProcXineramaQueryVersion (ClientPtr client) -{ - REQUEST(xPanoramiXQueryVersionReq); - register int n; - swaps(&stuff->length,n); - REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); - return RADEONProcXineramaQueryVersion(client); -} - -static int -RADEONSProcXineramaGetState(ClientPtr client) -{ - REQUEST(xPanoramiXGetStateReq); - register int n; - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); - return RADEONProcXineramaGetState(client); -} - -static int -RADEONSProcXineramaGetScreenCount(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenCountReq); - register int n; - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); - return RADEONProcXineramaGetScreenCount(client); -} - -static int -RADEONSProcXineramaGetScreenSize(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenSizeReq); - register int n; - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); - return RADEONProcXineramaGetScreenSize(client); -} - -static int -RADEONSProcXineramaIsActive(ClientPtr client) -{ - REQUEST(xXineramaIsActiveReq); - register int n; - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xXineramaIsActiveReq); - return RADEONProcXineramaIsActive(client); -} - -static int -RADEONSProcXineramaQueryScreens(ClientPtr client) -{ - REQUEST(xXineramaQueryScreensReq); - register int n; - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); - return RADEONProcXineramaQueryScreens(client); -} - -int -RADEONSProcXineramaDispatch(ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) { - case X_PanoramiXQueryVersion: - return RADEONSProcXineramaQueryVersion(client); - case X_PanoramiXGetState: - return RADEONSProcXineramaGetState(client); - case X_PanoramiXGetScreenCount: - return RADEONSProcXineramaGetScreenCount(client); - case X_PanoramiXGetScreenSize: - return RADEONSProcXineramaGetScreenSize(client); - case X_XineramaIsActive: - return RADEONSProcXineramaIsActive(client); - case X_XineramaQueryScreens: - return RADEONSProcXineramaQueryScreens(client); - } - return BadRequest; -} - -static void -RADEONXineramaResetProc(ExtensionEntry* extEntry) -{ - if(RADEONXineramadataPtr) { - Xfree(RADEONXineramadataPtr); - RADEONXineramadataPtr = NULL; - } -} - -void -RADEONXineramaExtensionInit(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - Bool success = FALSE; - - if(!(RADEONXineramadataPtr)) { - - if(!info->MergedFB) { - RADEONnoPanoramiXExtension = TRUE; - info->MouseRestrictions = FALSE; - return; - } - -#ifdef PANORAMIX - if(!noPanoramiXExtension) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Xinerama active, not initializing Radeon Pseudo-Xinerama\n"); - RADEONnoPanoramiXExtension = TRUE; - info->MouseRestrictions = FALSE; - return; - } -#endif - - if(RADEONnoPanoramiXExtension) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Radeon Pseudo-Xinerama disabled\n"); - info->MouseRestrictions = FALSE; - return; - } - - if(info->CRT2Position == radeonClone) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Running MergedFB in Clone mode, Radeon Pseudo-Xinerama disabled\n"); - RADEONnoPanoramiXExtension = TRUE; - info->MouseRestrictions = FALSE; - return; - } - - if(!(info->AtLeastOneNonClone)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Only Clone modes defined, Radeon Pseudo-Xinerama disabled\n"); - RADEONnoPanoramiXExtension = TRUE; - info->MouseRestrictions = FALSE; - return; - } - - RADEONXineramaNumScreens = 2; - - while(RADEONXineramaGeneration != serverGeneration) { - - info->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, - RADEONProcXineramaDispatch, - RADEONSProcXineramaDispatch, - RADEONXineramaResetProc, - StandardMinorOpcode); - - if(!info->XineramaExtEntry) break; - - RADEONXineramaReqCode = (unsigned char)info->XineramaExtEntry->base; - - if(!(RADEONXineramadataPtr = (RADEONXineramaData *) - xcalloc(RADEONXineramaNumScreens, sizeof(RADEONXineramaData)))) break; - - RADEONXineramaGeneration = serverGeneration; - success = TRUE; - } - - if(!success) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to initialize Radeon Pseudo-Xinerama extension\n"); - RADEONnoPanoramiXExtension = TRUE; - info->MouseRestrictions = FALSE; - return; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Initialized Radeon Pseudo-Xinerama extension\n"); - - info->RADEONXineramaVX = 0; - info->RADEONXineramaVY = 0; - - } - - RADEONUpdateXineramaScreenInfo(pScrn); - -} -/* End of PseudoXinerama */ - -static Bool -InRegion(int x, int y, region r) -{ - return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1); -} - -void -RADEONMergePointerMoved(int scrnIndex, int x, int y) -{ - ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; - RADEONInfoPtr info = RADEONPTR(pScrn1); - ScrnInfoPtr pScrn2 = info->CRT2pScrn; - region out, in1, in2, f2, f1; - int deltax, deltay; - int temp1, temp2; - int old1x0, old1y0, old2x0, old2y0; - int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; - int HVirt = pScrn1->virtualX; - int VVirt = pScrn1->virtualY; - int sigstate; - Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; - RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position; - - if(info->DGAactive) { - return; - /* DGA: There is no cursor and no panning while DGA is active. */ - /* If it were, we would need to do: */ - /* HVirt = info->CurrentLayout.displayWidth; - VVirt = info->CurrentLayout.displayHeight; - BOUND(x, info->CurrentLayout.DGAViewportX, HVirt); - BOUND(y, info->CurrentLayout.DGAViewportY, VVirt); */ - } else { - CRT1XOffs = info->CRT1XOffs; - CRT1YOffs = info->CRT1YOffs; - CRT2XOffs = info->CRT2XOffs; - CRT2YOffs = info->CRT2YOffs; - HaveNonRect = info->HaveNonRect; - HaveOffsRegions = info->HaveOffsRegions; - } - - /* Check if the pointer is inside our dead areas */ - if((info->MouseRestrictions) && (srel != radeonClone) && !RADEONnoPanoramiXExtension) { - if(HaveNonRect) { - if(InRegion(x, y, info->NonRectDead)) { - switch(srel) { - case radeonLeftOf: - case radeonRightOf: y = info->NonRectDead.y0 - 1; - doit = TRUE; - break; - case radeonAbove: - case radeonBelow: x = info->NonRectDead.x0 - 1; - doit = TRUE; - default: break; - } - } - } - if(HaveOffsRegions) { - if(InRegion(x, y, info->OffDead1)) { - switch(srel) { - case radeonLeftOf: - case radeonRightOf: y = info->OffDead1.y1; - doit = TRUE; - break; - case radeonAbove: - case radeonBelow: x = info->OffDead1.x1; - doit = TRUE; - default: break; - } - } else if(InRegion(x, y, info->OffDead2)) { - switch(srel) { - case radeonLeftOf: - case radeonRightOf: y = info->OffDead2.y0 - 1; - doit = TRUE; - break; - case radeonAbove: - case radeonBelow: x = info->OffDead2.x0 - 1; - doit = TRUE; - default: break; - } - } - } - if(doit) { - UpdateCurrentTime(); - sigstate = xf86BlockSIGIO(); - miPointerAbsoluteCursor(x, y, currentTime.milliseconds); - xf86UnblockSIGIO(sigstate); - return; - } - } - - f1.x0 = old1x0 = info->CRT1frameX0; - f1.x1 = info->CRT1frameX1; - f1.y0 = old1y0 = info->CRT1frameY0; - f1.y1 = info->CRT1frameY1; - f2.x0 = old2x0 = pScrn2->frameX0; - f2.x1 = pScrn2->frameX1; - f2.y0 = old2y0 = pScrn2->frameY0; - f2.y1 = pScrn2->frameY1; - - /* Define the outer region. Crossing this causes all frames to move */ - out.x0 = pScrn1->frameX0; - out.x1 = pScrn1->frameX1; - out.y0 = pScrn1->frameY0; - out.y1 = pScrn1->frameY1; - - /* - * Define the inner sliding window. Being outsize both frames but - * inside the outer clipping window will slide corresponding frame - */ - in1 = out; - in2 = out; - switch(srel) { - case radeonLeftOf: - in1.x0 = f1.x0; - in2.x1 = f2.x1; - break; - case radeonRightOf: - in1.x1 = f1.x1; - in2.x0 = f2.x0; - break; - case radeonBelow: - in1.y1 = f1.y1; - in2.y0 = f2.y0; - break; - case radeonAbove: - in1.y0 = f1.y0; - in2.y1 = f2.y1; - break; - case radeonClone: - break; - } - - deltay = 0; - deltax = 0; - - if(InRegion(x, y, out)) { /* inside outer region */ - - /* xf86DrvMsg(0, X_INFO, "1: %d %d | %d %d %d %d | %d %d %d %d\n", - x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1); */ - - if(InRegion(x, y, in1) && !InRegion(x, y, f1)) { - REBOUND(f1.x0, f1.x1, x); - REBOUND(f1.y0, f1.y1, y); - deltax = 1; - /* xf86DrvMsg(0, X_INFO, "2: %d %d | %d %d %d %d | %d %d %d %d\n", - x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1); */ - } - if(InRegion(x, y, in2) && !InRegion(x, y, f2)) { - REBOUND(f2.x0, f2.x1, x); - REBOUND(f2.y0, f2.y1, y); - deltax = 1; - } - - } else { /* outside outer region */ - - /* xf86DrvMsg(0, X_INFO, "3: %d %d | %d %d %d %d | %d %d %d %d\n", - x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1); - xf86DrvMsg(0, X_INFO, "3-out: %d %d %d %d\n", - out.x0, out.x1, out.y0, out.y1); */ - - if(out.x0 > x) { - deltax = x - out.x0; - } - if(out.x1 < x) { - deltax = x - out.x1; - } - if(deltax) { - pScrn1->frameX0 += deltax; - pScrn1->frameX1 += deltax; - f1.x0 += deltax; - f1.x1 += deltax; - f2.x0 += deltax; - f2.x1 += deltax; - } - - if(out.y0 > y) { - deltay = y - out.y0; - } - if(out.y1 < y) { - deltay = y - out.y1; - } - if(deltay) { - pScrn1->frameY0 += deltay; - pScrn1->frameY1 += deltay; - f1.y0 += deltay; - f1.y1 += deltay; - f2.y0 += deltay; - f2.y1 += deltay; - } - - switch(srel) { - case radeonLeftOf: - if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } - if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } - break; - case radeonRightOf: - if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); } - if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); } - break; - case radeonBelow: - if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); } - if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); } - break; - case radeonAbove: - if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); } - if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); } - break; - case radeonClone: - break; - } - - } - - if(deltax || deltay) { - info->CRT1frameX0 = f1.x0; - info->CRT1frameY0 = f1.y0; - pScrn2->frameX0 = f2.x0; - pScrn2->frameY0 = f2.y0; - - switch(((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position) { - case radeonLeftOf: - case radeonRightOf: - if(info->CRT1YOffs || info->CRT2YOffs || HaveNonRect) { - if(info->CRT1frameY0 != old1y0) { - if(info->CRT1frameY0 < info->CRT1YOffs) - info->CRT1frameY0 = info->CRT1YOffs; - temp1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay; - /*temp2 = pScrn1->virtualY - info->CRT2YOffs;*/ - temp2 = min((VVirt - CRT2YOffs), (CRT1YOffs + info->MBXNR1YMAX)); - if(temp1 > temp2) - info->CRT1frameY0 -= (temp1 - temp2); - } - if(pScrn2->frameY0 != old2y0) { - if(pScrn2->frameY0 < info->CRT2YOffs) - pScrn2->frameY0 = info->CRT2YOffs; - temp1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay; - /*temp2 = pScrn1->virtualY - info->CRT1YOffs;*/ - temp2 = min((VVirt - CRT1YOffs), (CRT2YOffs + info->MBXNR2YMAX)); - if(temp1 > temp2) - pScrn2->frameY0 -= (temp1 - temp2); - } - } - break; - case radeonBelow: - case radeonAbove: - if(info->CRT1XOffs || info->CRT2XOffs || HaveNonRect) { - if(info->CRT1frameX0 != old1x0) { - if(info->CRT1frameX0 < info->CRT1XOffs) - info->CRT1frameX0 = info->CRT1XOffs; - temp1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay; - /*temp2 = pScrn1->virtualX - info->CRT2XOffs;*/ - temp2 = min((HVirt - CRT2XOffs), (CRT1XOffs + info->MBXNR1XMAX)); - if(temp1 > temp2) - info->CRT1frameX0 -= (temp1 - temp2); - } - if(pScrn2->frameX0 != old2x0) { - if(pScrn2->frameX0 < info->CRT2XOffs) - pScrn2->frameX0 = info->CRT2XOffs; - temp1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay; - /*temp2 = pScrn1->virtualX - info->CRT1XOffs;*/ - temp2 = min((HVirt - CRT1XOffs), (CRT2XOffs + info->MBXNR2XMAX)); - if(temp1 > temp2) - pScrn2->frameX0 -= (temp1 - temp2); - } - } - break; - case radeonClone: - break; - } - - info->CRT1frameX1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; - info->CRT1frameY1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; - pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; - pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; -#if 0 - pScrn1->frameX1 = pScrn1->frameX0 + info->CurrentLayout.mode->HDisplay - 1; - pScrn1->frameY1 = pScrn1->frameY0 + info->CurrentLayout.mode->VDisplay - 1; -#endif - - RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE); - RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE); - } -} - -static void -RADEONAdjustFrameMergedHelper(int scrnIndex, int x, int y, int flags) -{ - ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; - RADEONInfoPtr info = RADEONPTR(pScrn1); - ScrnInfoPtr pScrn2 = info->CRT2pScrn; - int VTotal = info->CurrentLayout.mode->VDisplay; - int HTotal = info->CurrentLayout.mode->HDisplay; - int VMax = VTotal; - int HMax = HTotal; - int HVirt = pScrn1->virtualX; - int VVirt = pScrn1->virtualY; - int x1 = x, x2 = x; - int y1 = y, y2 = y; - int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; - int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; - - if(info->DGAactive) { - HVirt = info->CurrentLayout.displayWidth; - VVirt = info->CurrentLayout.displayHeight; - } else { - CRT1XOffs = info->CRT1XOffs; - CRT1YOffs = info->CRT1YOffs; - CRT2XOffs = info->CRT2XOffs; - CRT2YOffs = info->CRT2YOffs; - MBXNR1XMAX = info->MBXNR1XMAX; - MBXNR1YMAX = info->MBXNR1YMAX; - MBXNR2XMAX = info->MBXNR2XMAX; - MBXNR2YMAX = info->MBXNR2YMAX; - } - - - BOUND(x, 0, pScrn1->virtualX - HTotal); - BOUND(y, 0, pScrn1->virtualY - VTotal); - if(SDMPTR(pScrn1)->CRT2Position != radeonClone) { -#if 0 - BOUND(x1, info->CRT1XOffs, pScrn1->virtualX - HTotal - info->CRT2XOffs); - BOUND(y1, info->CRT1YOffs, pScrn1->virtualY - VTotal - info->CRT2YOffs); - BOUND(x2, info->CRT2XOffs, pScrn1->virtualX - HTotal - info->CRT1XOffs); - BOUND(y2, info->CRT2YOffs, pScrn1->virtualY - VTotal - info->CRT1YOffs); -#endif - BOUND(x1, CRT1XOffs, min(HVirt, MBXNR1XMAX + CRT1XOffs) - min(HTotal, MBXNR1XMAX) - CRT2XOffs); - BOUND(y1, CRT1YOffs, min(VVirt, MBXNR1YMAX + CRT1YOffs) - min(VTotal, MBXNR1YMAX) - CRT2YOffs); - BOUND(x2, CRT2XOffs, min(HVirt, MBXNR2XMAX + CRT2XOffs) - min(HTotal, MBXNR2XMAX) - CRT1XOffs); - BOUND(y2, CRT2YOffs, min(VVirt, MBXNR2YMAX + CRT2YOffs) - min(VTotal, MBXNR2YMAX) - CRT1YOffs); - } - - switch(SDMPTR(pScrn1)->CRT2Position) { - case radeonLeftOf: - pScrn2->frameX0 = x2; - /*BOUND(pScrn2->frameY0, y2, y2 + VMax - CDMPTR->CRT2->VDisplay);*/ - BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); - info->CRT1frameX0 = x1 + CDMPTR->CRT2->HDisplay; - /*BOUND(info->CRT1frameY0, y1, y1 + VMax - CDMPTR->CRT1->VDisplay);*/ - BOUND(info->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); - break; - case radeonRightOf: - info->CRT1frameX0 = x1; - /*BOUND(info->CRT1frameY0, y1, y1 + VMax - CDMPTR->CRT1->VDisplay);*/ - BOUND(info->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); - pScrn2->frameX0 = x2 + CDMPTR->CRT1->HDisplay; - /*BOUND(pScrn2->frameY0, y2, y2 + VMax - CDMPTR->CRT2->VDisplay);*/ - BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); - break; - case radeonAbove: - /*BOUND(pScrn2->frameX0, x2, x2 + HMax - CDMPTR->CRT2->HDisplay);*/ - BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); - pScrn2->frameY0 = y2; - /*BOUND(info->CRT1frameX0, x1, x1 + HMax - CDMPTR->CRT1->HDisplay);*/ - BOUND(info->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); - info->CRT1frameY0 = y1 + CDMPTR->CRT2->VDisplay; - break; - case radeonBelow: - /*BOUND(info->CRT1frameX0, x1, x1 + HMax - CDMPTR->CRT1->HDisplay);*/ - BOUND(info->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); - info->CRT1frameY0 = y1; - /*BOUND(pScrn2->frameX0, x2, x2 + HMax - CDMPTR->CRT2->HDisplay);*/ - BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); - pScrn2->frameY0 = y2 + CDMPTR->CRT1->VDisplay; - break; - case radeonClone: - BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); - BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); - BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); - BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); - break; - } - - BOUND(info->CRT1frameX0, 0, pScrn1->virtualX - CDMPTR->CRT1->HDisplay); - BOUND(info->CRT1frameY0, 0, pScrn1->virtualY - CDMPTR->CRT1->VDisplay); - BOUND(pScrn2->frameX0, 0, pScrn1->virtualX - CDMPTR->CRT2->HDisplay); - BOUND(pScrn2->frameY0, 0, pScrn1->virtualY - CDMPTR->CRT2->VDisplay); - - pScrn1->frameX0 = x; - pScrn1->frameY0 = y; - - info->CRT1frameX1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; - info->CRT1frameY1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; - pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; - pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; - pScrn1->frameX1 = pScrn1->frameX0 + info->CurrentLayout.mode->HDisplay - 1; - pScrn1->frameY1 = pScrn1->frameY0 + info->CurrentLayout.mode->VDisplay - 1; - - if(SDMPTR(pScrn1)->CRT2Position != radeonClone) { - pScrn1->frameX1 += CRT1XOffs + CRT2XOffs; - pScrn1->frameY1 += CRT1YOffs + CRT2YOffs; - } - -/* - RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE); - RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE); -*/ -} - -void -RADEONAdjustFrameMerged(int scrnIndex, int x, int y, int flags) -{ - ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex]; - RADEONInfoPtr info = RADEONPTR(pScrn1); - ScrnInfoPtr pScrn2 = info->CRT2pScrn; - - RADEONAdjustFrameMergedHelper(scrnIndex, x, y, flags); - RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE); - RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE); -} - -static void -RADEONMergedFBCalcDPI(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel, Bool quiet) -{ - RADEONInfoPtr info = RADEONPTR(pScrn1); - MessageType from = X_DEFAULT; - xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC); - xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC); - int ddcWidthmm = 0, ddcHeightmm = 0; - const char *dsstr = "MergedFB: Display dimensions: %dx%d mm\n"; - - /* This sets the DPI for MergedFB mode. The problem is that - * this can never be exact, because the output devices may - * have different dimensions. This function tries to compromise - * through a few assumptions, and it just calculates an average - * DPI value for both monitors. - */ - - /* Copy user-given DisplaySize (which should regard BOTH monitors!) */ - pScrn1->widthmm = pScrn1->monitor->widthmm; - pScrn1->heightmm = pScrn1->monitor->heightmm; - - if(monitorResolution > 0) { - - /* Set command line given values (overrules given options) */ - pScrn1->xDpi = monitorResolution; - pScrn1->yDpi = monitorResolution; - from = X_CMDLINE; - - } else if(info->MergedFBXDPI) { - - /* Set option-wise given values (overrules DisplaySize config option) */ - pScrn1->xDpi = info->MergedFBXDPI; - pScrn1->yDpi = info->MergedFBYDPI; - from = X_CONFIG; - - } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) { - - /* Set values calculated from given DisplaySize */ - from = X_CONFIG; - if(pScrn1->widthmm > 0) { - pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); - } - if(pScrn1->heightmm > 0) { - pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); - } - if(!quiet) { - xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm); - } - - } else if(ddcWidthmm && ddcHeightmm) { - - /* Set values from DDC-provided display size */ - - /* Get DDC display size; if only either CRT1 or CRT2 provided these, - * assume equal dimensions for both, otherwise add dimensions - */ - if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) && - (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) { - ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10; - ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10; - switch(srel) { - case radeonLeftOf: - case radeonRightOf: - ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10; - break; - case radeonAbove: - case radeonBelow: - ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10; - default: - break; - } - } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) { - ddcWidthmm = DDC1->features.hsize * 10; - ddcHeightmm = DDC1->features.vsize * 10; - switch(srel) { - case radeonLeftOf: - case radeonRightOf: - ddcWidthmm *= 2; - break; - case radeonAbove: - case radeonBelow: - ddcHeightmm *= 2; - default: - break; - } - } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) { - ddcWidthmm = DDC2->features.hsize * 10; - ddcHeightmm = DDC2->features.vsize * 10; - switch(srel) { - case radeonLeftOf: - case radeonRightOf: - ddcWidthmm *= 2; - break; - case radeonAbove: - case radeonBelow: - ddcHeightmm *= 2; - default: - break; - } - } - - from = X_PROBED; - - if(!quiet) { - xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm); - } - - pScrn1->widthmm = ddcWidthmm; - pScrn1->heightmm = ddcHeightmm; - if(pScrn1->widthmm > 0) { - pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm); - } - if(pScrn1->heightmm > 0) { - pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm); - } - - } else { - - pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI; - - } - - /* Sanity check */ - if(pScrn1->xDpi > 0 && pScrn1->yDpi <= 0) - pScrn1->yDpi = pScrn1->xDpi; - if(pScrn1->yDpi > 0 && pScrn1->xDpi <= 0) - pScrn1->xDpi = pScrn1->yDpi; - - pScrn2->xDpi = pScrn1->xDpi; - pScrn2->yDpi = pScrn1->yDpi; - - if(!quiet) { - xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n", - pScrn1->xDpi, pScrn1->yDpi); - } -} - - -void -RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel) -{ - RADEONInfoPtr info = RADEONPTR(pScrn1); - - RADEONMergedFBCalcDPI(pScrn1, pScrn2, srel, FALSE); - - info->MergedDPISRel = srel; - info->RADEONMergedDPIVX = pScrn1->virtualX; - info->RADEONMergedDPIVY = pScrn1->virtualY; - -} - -void -RADEONMergedFBResetDpi(ScrnInfoPtr pScrn, Bool force) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; - RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position; - - /* This does the same calculation for the DPI as - * the initial run. This means that an eventually - * given -dpi command line switch will lead to - * constant dpi values, regardless of the virtual - * screen size. - * I consider this consequent. If this is undesired, - * one should use the DisplaySize parameter in the - * config file instead of the command line switch. - * The DPI will be calculated then. - */ - - if(force || - (info->MergedDPISRel != srel) || - (info->RADEONMergedDPIVX != pScrn->virtualX) || - (info->RADEONMergedDPIVY != pScrn->virtualY) - ) { - - RADEONMergedFBCalcDPI(pScrn, info->CRT2pScrn, srel, TRUE); - - pScreen->mmWidth = (pScrn->virtualX * 254 + pScrn->xDpi * 5) / (pScrn->xDpi * 10); - pScreen->mmHeight = (pScrn->virtualY * 254 + pScrn->yDpi * 5) / (pScrn->yDpi * 10); - - info->MergedDPISRel = srel; - info->RADEONMergedDPIVX = pScrn->virtualX; - info->RADEONMergedDPIVY = pScrn->virtualY; - - } -} - -/* radeon cursor helpers */ -static void -RADEONChooseCursorCRTC(ScrnInfoPtr pScrn1, int x, int y) -{ - RADEONInfoPtr info = RADEONPTR(pScrn1); - unsigned char *RADEONMMIO = info->MMIO; - RADEONScrn2Rel srel = - ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position; - ScrnInfoPtr pScrn2 = info->CRT2pScrn; - - if (srel == radeonClone) { - /* show cursor 2 */ - OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN, - ~RADEON_CRTC2_CUR_EN); - /* show cursor 1 */ - OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN, - ~RADEON_CRTC_CUR_EN); - } - else { - if (((x >= pScrn1->frameX0) && (x <= pScrn1->frameX1)) && - ((y >= pScrn1->frameY0) && (y <= pScrn1->frameY1))) { - /* hide cursor 2 */ - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN); - /* show cursor 1 */ - OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN, - ~RADEON_CRTC_CUR_EN); - } - if (((x >= pScrn2->frameX0) && (x <= pScrn2->frameX1)) && - ((y >= pScrn2->frameY0) && (y <= pScrn2->frameY1))) { - /* hide cursor 1 */ - OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_CUR_EN); - /* show cursor 2 */ - OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN, - ~RADEON_CRTC2_CUR_EN); - } - } -} - -void -RADEONSetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - xf86CursorInfoPtr cursor = info->cursor; - int xorigin = 0; - int yorigin = 0; - int stride = 256; - ScrnInfoPtr pScrn2 = info->CRT2pScrn; - DisplayModePtr mode1 = CDMPTR->CRT1; - DisplayModePtr mode2 = CDMPTR->CRT2; - int x1, y1, x2, y2; - int total_y1 = pScrn->frameY1 - pScrn->frameY0; - int total_y2 = pScrn2->frameY1 - pScrn2->frameY0; - - if (x < 0) xorigin = -x+1; - if (y < 0) yorigin = -y+1; - /* if (y > total_y) y = total_y; */ - if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; - if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; - - x += pScrn->frameX0; - y += pScrn->frameY0; - - x1 = x - info->CRT1frameX0; - y1 = y - info->CRT1frameY0; - - x2 = x - pScrn2->frameX0; - y2 = y - pScrn2->frameY0; - - if (y1 > total_y1) - y1 = total_y1; - if (y2 > total_y2) - y2 = total_y2; - - if(mode1->Flags & V_INTERLACE) - y1 /= 2; - else if(mode1->Flags & V_DBLSCAN) - y1 *= 2; - - if(mode2->Flags & V_INTERLACE) - y2 /= 2; - else if(mode2->Flags & V_DBLSCAN) - y2 *= 2; - - if (x < 0) - x = 0; - if (y < 0) - y = 0; - - RADEONChooseCursorCRTC(pScrn, x, y); - - /* cursor1 */ - OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK - | (xorigin << 16) - | yorigin)); - OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK - | ((xorigin ? 0 : x1) << 16) - | (yorigin ? 0 : y1))); - OUTREG(RADEON_CUR_OFFSET, info->cursor_offset + yorigin * stride); - /* cursor2 */ - OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK - | (xorigin << 16) - | yorigin)); - OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK - | ((xorigin ? 0 : x2) << 16) - | (yorigin ? 0 : y2))); - OUTREG(RADEON_CUR2_OFFSET, info->cursor_offset + yorigin * stride); -} - -/* radeon Xv helpers */ - -/* choose the crtc for the overlay for mergedfb based on the location - of the output window and the orientation of the crtcs */ - -void -RADEONChooseOverlayCRTC( - ScrnInfoPtr pScrn, - BoxPtr dstBox -) { - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONScrn2Rel srel = - ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position; - - if (srel == radeonLeftOf) { - if (dstBox->x1 >= info->CRT2pScrn->frameX1) - info->OverlayOnCRTC2 = FALSE; - else - info->OverlayOnCRTC2 = TRUE; - } - if (srel == radeonRightOf) { - if (dstBox->x2 <= info->CRT2pScrn->frameX0) - info->OverlayOnCRTC2 = FALSE; - else - info->OverlayOnCRTC2 = TRUE; - } - if (srel == radeonAbove) { - if (dstBox->y1 >= info->CRT2pScrn->frameY1) - info->OverlayOnCRTC2 = FALSE; - else - info->OverlayOnCRTC2 = TRUE; - } - if (srel == radeonBelow) { - if (dstBox->y2 <= info->CRT2pScrn->frameY0) - info->OverlayOnCRTC2 = FALSE; - else - info->OverlayOnCRTC2 = TRUE; - } -} diff --git a/src/radeon_mergedfb.h b/src/radeon_mergedfb.h deleted file mode 100644 index d9bcc03c..00000000 --- a/src/radeon_mergedfb.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2003 Alex Deucher. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation on the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL ALEX DEUCHER, OR ANY OTHER - * CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/* - * Authors: - * Alex Deucher <agd5f@yahoo.com> - * - */ - -#ifndef _RADEON_MERGEDFB_H_ -#define _RADEON_MERGEDFB_H_ - -#include "xf86.h" - -#include "radeon.h" - -#if 0 - /* Psuedo Xinerama support */ -#define NEED_REPLIES /* ? */ -#define EXTENSION_PROC_ARGS void * -#include "extnsionst.h" /* required */ -#include <X11/extensions/panoramiXproto.h> /* required */ -#define RADEON_XINERAMA_MAJOR_VERSION 1 -#define RADEON_XINERAMA_MINOR_VERSION 1 - -/* needed for pseudo-xinerama by radeon_driver.c */ -Bool RADEONnoPanoramiXExtension = TRUE; - -/* Relative merge position */ -typedef enum { - radeonLeftOf, - radeonRightOf, - radeonAbove, - radeonBelow, - radeonClone -} RADEONScrn2Rel; -#endif - -#define SDMPTR(x) ((RADEONMergedDisplayModePtr)(x->currentMode->Private)) -#define CDMPTR ((RADEONMergedDisplayModePtr)(info->CurrentLayout.mode->Private)) - -#define BOUND(test,low,hi) { \ - if(test < low) test = low; \ - if(test > hi) test = hi; } - -#define REBOUND(low,hi,test) { \ - if(test < low) { \ - hi += test-low; \ - low = test; } \ - if(test > hi) { \ - low += test-hi; \ - hi = test; } } - -typedef struct _MergedDisplayModeRec { - DisplayModePtr CRT1; - DisplayModePtr CRT2; - RADEONScrn2Rel CRT2Position; -} RADEONMergedDisplayModeRec, *RADEONMergedDisplayModePtr; - -typedef struct _RADEONXineramaData { - int x; - int y; - int width; - int height; -} RADEONXineramaData; - -/* needed by radeon_driver.c */ -extern void -RADEONAdjustFrameMerged(int scrnIndex, int x, int y, int flags); -extern void -RADEONMergePointerMoved(int scrnIndex, int x, int y); -extern DisplayModePtr -RADEONGenerateModeList(ScrnInfoPtr pScrn, char* str, - DisplayModePtr i, DisplayModePtr j, - RADEONScrn2Rel srel); -extern int -RADEONStrToRanges(range *r, char *s, int max); -extern void -RADEONXineramaExtensionInit(ScrnInfoPtr pScrn); -extern void -RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1); -extern void -RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel); -extern void -RADEONMergedFBResetDpi(ScrnInfoPtr pScrn, Bool force); -extern void -RADEONRecalcDefaultVirtualSize(ScrnInfoPtr pScrn); - -/* needed by radeon_cursor.c */ -extern void -RADEONSetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y); - -/* needed by radeon_video.c */ -extern void -RADEONChooseOverlayCRTC(ScrnInfoPtr, BoxPtr); - -#endif /* _RADEON_MERGEDFB_H_ */ diff --git a/src/radeon_modes.c b/src/radeon_modes.c index 70bf1846..687e3888 100644 --- a/src/radeon_modes.c +++ b/src/radeon_modes.c @@ -42,80 +42,18 @@ #include "xf86.h" /* Driver data structures */ +#include "randrstr.h" +#include "radeon_probe.h" #include "radeon.h" #include "radeon_reg.h" #include "radeon_macros.h" -#include "radeon_probe.h" + #include "radeon_version.h" +#include "xf86Modes.h" /* DDC support */ #include "xf86DDC.h" - -/* Established timings from EDID standard */ -static struct -{ - int hsize; - int vsize; - int refresh; -} est_timings[] = { - {1280, 1024, 75}, - {1024, 768, 75}, - {1024, 768, 70}, - {1024, 768, 60}, - {1024, 768, 87}, - {832, 624, 75}, - {800, 600, 75}, - {800, 600, 72}, - {800, 600, 60}, - {800, 600, 56}, - {640, 480, 75}, - {640, 480, 72}, - {640, 480, 67}, - {640, 480, 60}, - {720, 400, 88}, - {720, 400, 70}, -}; - -/* This function will sort all modes according to their resolution. - * Highest resolution first. - */ -static void RADEONSortModes(DisplayModePtr *new, DisplayModePtr *first, - DisplayModePtr *last) -{ - DisplayModePtr p; - - p = *last; - while (p) { - if ((((*new)->HDisplay < p->HDisplay) && - ((*new)->VDisplay < p->VDisplay)) || - (((*new)->HDisplay == p->HDisplay) && - ((*new)->VDisplay == p->VDisplay) && - ((*new)->Clock < p->Clock))) { - - if (p->next) p->next->prev = *new; - (*new)->prev = p; - (*new)->next = p->next; - p->next = *new; - if (!((*new)->next)) *last = *new; - break; - } - if (!p->prev) { - (*new)->prev = NULL; - (*new)->next = p; - p->prev = *new; - *first = *new; - break; - } - p = p->prev; - } - - if (!*first) { - *first = *new; - (*new)->prev = NULL; - (*new)->next = NULL; - *last = *new; - } -} +#include <randrstr.h> void RADEONSetPitch (ScrnInfoPtr pScrn) { @@ -136,346 +74,61 @@ void RADEONSetPitch (ScrnInfoPtr pScrn) break; } pScrn->displayWidth = dummy; -} - -/* When no mode provided in config file, this will add all modes supported in - * DDC date the pScrn->modes list - */ -static DisplayModePtr RADEONDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) -{ - DisplayModePtr p; - DisplayModePtr last = NULL; - DisplayModePtr new = NULL; - DisplayModePtr first = NULL; - int count = 0; - int j, tmp; - char stmp[32]; - - /* Go thru detailed timing table first */ - for (j = 0; j < 4; j++) { - if (ddc->det_mon[j].type == 0) { - struct detailed_timings *d_timings = - &ddc->det_mon[j].section.d_timings; - - if (d_timings->h_active == 0 || d_timings->v_active == 0) break; - - new = xnfcalloc(1, sizeof (DisplayModeRec)); - memset(new, 0, sizeof (DisplayModeRec)); - - new->HDisplay = d_timings->h_active; - new->VDisplay = d_timings->v_active; - - sprintf(stmp, "%dx%d", new->HDisplay, new->VDisplay); - new->name = xnfalloc(strlen(stmp) + 1); - strcpy(new->name, stmp); - - new->HTotal = new->HDisplay + d_timings->h_blanking; - new->HSyncStart = new->HDisplay + d_timings->h_sync_off; - new->HSyncEnd = new->HSyncStart + d_timings->h_sync_width; - new->VTotal = new->VDisplay + d_timings->v_blanking; - new->VSyncStart = new->VDisplay + d_timings->v_sync_off; - new->VSyncEnd = new->VSyncStart + d_timings->v_sync_width; - new->Clock = d_timings->clock / 1000; - new->Flags = (d_timings->interlaced ? V_INTERLACE : 0); - new->status = MODE_OK; -#ifdef M_T_PREFERRED - if (PREFERRED_TIMING_MODE(ddc->features.msc)) - new->type = M_T_PREFERRED; - else -#endif - new->type = M_T_DEFAULT; - - if (d_timings->sync == 3) { - switch (d_timings->misc) { - case 0: new->Flags |= V_NHSYNC | V_NVSYNC; break; - case 1: new->Flags |= V_PHSYNC | V_NVSYNC; break; - case 2: new->Flags |= V_NHSYNC | V_PVSYNC; break; - case 3: new->Flags |= V_PHSYNC | V_PVSYNC; break; - } - } - count++; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid Mode from Detailed timing table: %s\n", - new->name); + info->CurrentLayout.displayWidth = pScrn->displayWidth; - RADEONSortModes(&new, &first, &last); - } - } - - /* Search thru standard VESA modes from EDID */ - for (j = 0; j < 8; j++) { - if (ddc->timings2[j].hsize == 0 || ddc->timings2[j].vsize == 0) - continue; - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - /* Ignore all double scan modes */ - if ((ddc->timings2[j].hsize == p->HDisplay) && - (ddc->timings2[j].vsize == p->VDisplay)) { - float refresh = - (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; - - if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) { - /* Is this good enough? */ - new = xnfcalloc(1, sizeof (DisplayModeRec)); - memcpy(new, p, sizeof(DisplayModeRec)); - new->name = xnfalloc(strlen(p->name) + 1); - strcpy(new->name, p->name); - new->status = MODE_OK; - new->type = M_T_DEFAULT; - - count++; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid Mode from standard timing table: %s\n", - new->name); - - RADEONSortModes(&new, &first, &last); - break; - } - } - } - } - - /* Search thru established modes from EDID */ - tmp = (ddc->timings1.t1 << 8) | ddc->timings1.t2; - for (j = 0; j < 16; j++) { - if (tmp & (1 << j)) { - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - if ((est_timings[j].hsize == p->HDisplay) && - (est_timings[j].vsize == p->VDisplay)) { - float refresh = - (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; - - if (abs((float)est_timings[j].refresh - refresh) < 1.0) { - /* Is this good enough? */ - new = xnfcalloc(1, sizeof (DisplayModeRec)); - memcpy(new, p, sizeof(DisplayModeRec)); - new->name = xnfalloc(strlen(p->name) + 1); - strcpy(new->name, p->name); - new->status = MODE_OK; - new->type = M_T_DEFAULT; - - count++; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid Mode from established timing " - "table: %s\n", new->name); - - RADEONSortModes(&new, &first, &last); - break; - } - } - } - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total of %d mode(s) found.\n", count); - - return first; } -/* XFree86's xf86ValidateModes routine doesn't work well with DDC modes, - * so here is our own validation routine. - */ -int RADEONValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName, - RADEONMonitorType DisplayType, int crtc2) +static DisplayModePtr RADEONTVModes(xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn1); - DisplayModePtr p; - DisplayModePtr last = NULL; - DisplayModePtr first = NULL; - DisplayModePtr ddcModes = NULL; - int count = 0; - int i, width, height; - ScrnInfoPtr pScrn = pScrn1; - - if (crtc2) - pScrn = info->CRT2pScrn; - - pScrn->virtualX = pScrn1->display->virtualX; - pScrn->virtualY = pScrn1->display->virtualY; - - if (pScrn->monitor->DDC) { - int maxVirtX = pScrn->virtualX; - int maxVirtY = pScrn->virtualY; - - /* Collect all of the DDC modes */ - first = last = ddcModes = RADEONDDCModes(pScrn, pScrn->monitor->DDC); + DisplayModePtr new = NULL; - for (p = ddcModes; p; p = p->next) { + /* just a place holder */ + new = xf86CVTMode(800, 600, 60.00, FALSE, FALSE); + new->type = M_T_DRIVER | M_T_PREFERRED; - /* If primary head is a flat panel, use RMX by default */ - if ((!info->IsSecondary && DisplayType != MT_CRT) && - (!info->ddc_mode) && (!crtc2)) { - /* These values are effective values after expansion. - * They are not really used to set CRTC registers. - */ - p->HTotal = info->PanelXRes + info->HBlank; - p->HSyncStart = info->PanelXRes + info->HOverPlus; - p->HSyncEnd = p->HSyncStart + info->HSyncWidth; - p->VTotal = info->PanelYRes + info->VBlank; - p->VSyncStart = info->PanelYRes + info->VOverPlus; - p->VSyncEnd = p->VSyncStart + info->VSyncWidth; - p->Clock = info->DotClock; - - p->Flags |= RADEON_USE_RMX; - } - - maxVirtX = MAX(maxVirtX, p->HDisplay); - maxVirtY = MAX(maxVirtY, p->VDisplay); - count++; - - last = p; - } - - /* Match up modes that are specified in the XF86Config file */ - if (ppModeName[0]) { - DisplayModePtr next; - - /* Reset the max virtual dimensions */ - maxVirtX = pScrn->virtualX; - maxVirtY = pScrn->virtualY; - - /* Reset list */ - first = last = NULL; - - for (i = 0; ppModeName[i]; i++) { - /* FIXME: Use HDisplay and VDisplay instead of mode string */ - if (sscanf(ppModeName[i], "%dx%d", &width, &height) == 2) { - for (p = ddcModes; p; p = next) { - next = p->next; - - if (p->HDisplay == width && p->VDisplay == height) { - /* We found a DDC mode that matches the one - requested in the XF86Config file */ - p->type |= M_T_USERDEF; - - /* Update the max virtual setttings */ - maxVirtX = MAX(maxVirtX, width); - maxVirtY = MAX(maxVirtY, height); - - /* Unhook from DDC modes */ - if (p->prev) p->prev->next = p->next; - if (p->next) p->next->prev = p->prev; - if (p == ddcModes) ddcModes = p->next; - - /* Add to used modes */ - if (last) { - last->next = p; - p->prev = last; - } else { - first = p; - p->prev = NULL; - } - p->next = NULL; - last = p; - - break; - } - } - } - } - - /* - * Add remaining DDC modes if they're smaller than the user - * specified modes - */ - for (p = ddcModes; p; p = next) { - next = p->next; - if (p->HDisplay <= maxVirtX && p->VDisplay <= maxVirtY) { - /* Unhook from DDC modes */ - if (p->prev) p->prev->next = p->next; - if (p->next) p->next->prev = p->prev; - if (p == ddcModes) ddcModes = p->next; - - /* Add to used modes */ - if (last) { - last->next = p; - p->prev = last; - } else { - first = p; - p->prev = NULL; - } - p->next = NULL; - last = p; - } - } - - /* Delete unused modes */ - while (ddcModes) - xf86DeleteMode(&ddcModes, ddcModes); - } else { - /* - * No modes were configured, so we make the DDC modes - * available for the user to cycle through. - */ - for (p = ddcModes; p; p = p->next) - p->type |= M_T_USERDEF; - } - - if (crtc2) { - pScrn->virtualX = maxVirtX; - pScrn->virtualY = maxVirtY; - } else { - pScrn->virtualX = pScrn->display->virtualX = maxVirtX; - pScrn->virtualY = pScrn->display->virtualY = maxVirtY; - } - } - - /* Close the doubly-linked mode list, if we found any usable modes */ - if (last) { - last->next = first; - first->prev = last; - pScrn->modes = first; - RADEONSetPitch(pScrn); - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total number of valid DDC mode(s) found: %d\n", count); - - return count; + return new; } /* This is used only when no mode is specified for FP and no ddc is * available. We force it to native mode, if possible. */ -static DisplayModePtr RADEONFPNativeMode(ScrnInfoPtr pScrn) +static DisplayModePtr RADEONFPNativeMode(xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONOutputPrivatePtr radeon_output = output->driver_private; DisplayModePtr new = NULL; char stmp[32]; - if (info->PanelXRes != 0 && - info->PanelYRes != 0 && - info->DotClock != 0) { + if (radeon_output->PanelXRes != 0 && + radeon_output->PanelYRes != 0 && + radeon_output->DotClock != 0) { /* Add native panel size */ new = xnfcalloc(1, sizeof (DisplayModeRec)); - sprintf(stmp, "%dx%d", info->PanelXRes, info->PanelYRes); + sprintf(stmp, "%dx%d", radeon_output->PanelXRes, radeon_output->PanelYRes); new->name = xnfalloc(strlen(stmp) + 1); strcpy(new->name, stmp); - new->HDisplay = info->PanelXRes; - new->VDisplay = info->PanelYRes; + new->HDisplay = radeon_output->PanelXRes; + new->VDisplay = radeon_output->PanelYRes; - new->HTotal = new->HDisplay + info->HBlank; - new->HSyncStart = new->HDisplay + info->HOverPlus; - new->HSyncEnd = new->HSyncStart + info->HSyncWidth; - new->VTotal = new->VDisplay + info->VBlank; - new->VSyncStart = new->VDisplay + info->VOverPlus; - new->VSyncEnd = new->VSyncStart + info->VSyncWidth; + new->HTotal = new->HDisplay + radeon_output->HBlank; + new->HSyncStart = new->HDisplay + radeon_output->HOverPlus; + new->HSyncEnd = new->HSyncStart + radeon_output->HSyncWidth; + new->VTotal = new->VDisplay + radeon_output->VBlank; + new->VSyncStart = new->VDisplay + radeon_output->VOverPlus; + new->VSyncEnd = new->VSyncStart + radeon_output->VSyncWidth; - new->Clock = info->DotClock; + new->Clock = radeon_output->DotClock; new->Flags = 0; - new->type = M_T_USERDEF; + new->type = M_T_USERDEF | M_T_PREFERRED; new->next = NULL; new->prev = NULL; pScrn->display->virtualX = - pScrn->virtualX = MAX(pScrn->virtualX, info->PanelXRes); + pScrn->virtualX = MAX(pScrn->virtualX, radeon_output->PanelXRes); pScrn->display->virtualY = - pScrn->virtualY = MAX(pScrn->virtualY, info->PanelYRes); + pScrn->virtualY = MAX(pScrn->virtualY, radeon_output->PanelYRes); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No valid mode specified, force to native mode\n"); @@ -486,9 +139,10 @@ static DisplayModePtr RADEONFPNativeMode(ScrnInfoPtr pScrn) /* FP mode initialization routine for using on-chip RMX to scale */ -int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) +int RADEONValidateFPModes(xf86OutputPtr output, char **ppModeName, DisplayModePtr *modeList) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONOutputPrivatePtr radeon_output = output->driver_private; DisplayModePtr last = NULL; DisplayModePtr new = NULL; DisplayModePtr first = NULL; @@ -511,13 +165,13 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) * need the internal RMX unit in the video chips (and there is * only one per card), this will only apply to the primary head. */ - if (width < 320 || width > info->PanelXRes || - height < 200 || height > info->PanelYRes) { + if (width < 320 || width > radeon_output->PanelXRes || + height < 200 || height > radeon_output->PanelYRes) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode %s is out of range.\n", ppModeName[i]); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Valid modes must be between 320x200-%dx%d\n", - info->PanelXRes, info->PanelYRes); + radeon_output->PanelXRes, radeon_output->PanelYRes); continue; } @@ -530,17 +184,17 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) /* These values are effective values after expansion They are * not really used to set CRTC registers. */ - new->HTotal = info->PanelXRes + info->HBlank; - new->HSyncStart = info->PanelXRes + info->HOverPlus; - new->HSyncEnd = new->HSyncStart + info->HSyncWidth; - new->VTotal = info->PanelYRes + info->VBlank; - new->VSyncStart = info->PanelYRes + info->VOverPlus; - new->VSyncEnd = new->VSyncStart + info->VSyncWidth; - new->Clock = info->DotClock; + new->HTotal = radeon_output->PanelXRes + radeon_output->HBlank; + new->HSyncStart = radeon_output->PanelXRes + radeon_output->HOverPlus; + new->HSyncEnd = new->HSyncStart + radeon_output->HSyncWidth; + new->VTotal = radeon_output->PanelYRes + radeon_output->VBlank; + new->VSyncStart = radeon_output->PanelYRes + radeon_output->VOverPlus; + new->VSyncEnd = new->VSyncStart + radeon_output->VSyncWidth; + new->Clock = radeon_output->DotClock; new->Flags |= RADEON_USE_RMX; #ifdef M_T_PREFERRED - if (width == info->PanelXRes && height == info->PanelYRes) + if (width == radeon_output->PanelXRes && height == radeon_output->PanelYRes) new->type |= M_T_PREFERRED; #endif @@ -551,7 +205,7 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) if (last) last->next = new; last = new; - if (!first) first = new; + if (!first) first = new; pScrn->display->virtualX = pScrn->virtualX = MAX(pScrn->virtualX, width); @@ -564,13 +218,13 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) /* If all else fails, add the native mode */ if (!count) { - first = last = RADEONFPNativeMode(pScrn); + first = last = RADEONFPNativeMode(output); if (first) count = 1; } /* add in all default vesa modes smaller than panel size, used for randr*/ - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - if ((p->HDisplay <= info->PanelXRes) && (p->VDisplay <= info->PanelYRes)) { + for (p = *modeList; p && p->next; p = p->next->next) { + if ((p->HDisplay <= radeon_output->PanelXRes) && (p->VDisplay <= radeon_output->PanelYRes)) { tmp = first; while (tmp) { if ((p->HDisplay == tmp->HDisplay) && (p->VDisplay == tmp->VDisplay)) break; @@ -586,22 +240,19 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) /* These values are effective values after expansion They are * not really used to set CRTC registers. */ - new->HTotal = info->PanelXRes + info->HBlank; - new->HSyncStart = info->PanelXRes + info->HOverPlus; - new->HSyncEnd = new->HSyncStart + info->HSyncWidth; - new->VTotal = info->PanelYRes + info->VBlank; - new->VSyncStart = info->PanelYRes + info->VOverPlus; - new->VSyncEnd = new->VSyncStart + info->VSyncWidth; - new->Clock = info->DotClock; + new->HTotal = radeon_output->PanelXRes + radeon_output->HBlank; + new->HSyncStart = radeon_output->PanelXRes + radeon_output->HOverPlus; + new->HSyncEnd = new->HSyncStart + radeon_output->HSyncWidth; + new->VTotal = radeon_output->PanelYRes + radeon_output->VBlank; + new->VSyncStart = radeon_output->PanelYRes + radeon_output->VOverPlus; + new->VSyncEnd = new->VSyncStart + radeon_output->VSyncWidth; + new->Clock = radeon_output->DotClock; new->Flags |= RADEON_USE_RMX; new->type |= M_T_DEFAULT; - new->next = NULL; - new->prev = last; - if (last) last->next = new; - last = new; + last = new; if (!first) first = new; } } @@ -609,10 +260,10 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) /* Close the doubly-linked mode list, if we found any usable modes */ if (last) { - last->next = first; - first->prev = last; - pScrn->modes = first; - RADEONSetPitch(pScrn); + last->next = NULL; //first; + first->prev = NULL; //last; + *modeList = first; + //RADEONSetPitch(pScrn); } xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -621,164 +272,66 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) return count; } - -int RADEONValidateMergeModes(ScrnInfoPtr pScrn1) +DisplayModePtr +RADEONProbeOutputModes(xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn1); - ClockRangePtr clockRanges; - int modesFound; - ScrnInfoPtr pScrn = info->CRT2pScrn; - - /* fill in pScrn2 */ - pScrn->videoRam = pScrn1->videoRam; - pScrn->depth = pScrn1->depth; - pScrn->numClocks = pScrn1->numClocks; - pScrn->progClock = pScrn1->progClock; - pScrn->fbFormat = pScrn1->fbFormat; - pScrn->videoRam = pScrn1->videoRam; - pScrn->maxHValue = pScrn1->maxHValue; - pScrn->maxVValue = pScrn1->maxVValue; - pScrn->xInc = pScrn1->xInc; - - if (info->NoVirtual) { - pScrn1->display->virtualX = 0; - pScrn1->display->virtualY = 0; - } - - if (pScrn->monitor->DDC) { - /* If we still don't know sync range yet, let's try EDID. - * - * Note that, since we can have dual heads, Xconfigurator - * may not be able to probe both monitors correctly through - * vbe probe function (RADEONProbeDDC). Here we provide an - * additional way to auto-detect sync ranges if they haven't - * been added to XF86Config manually. - */ - if (pScrn->monitor->nHsync <= 0) - RADEONSetSyncRangeFromEdid(pScrn, 1); - if (pScrn->monitor->nVrefresh <= 0) - RADEONSetSyncRangeFromEdid(pScrn, 0); - } - - /* Get mode information */ - pScrn->progClock = TRUE; - clockRanges = xnfcalloc(sizeof(*clockRanges), 1); - clockRanges->next = NULL; - clockRanges->minClock = info->pll.min_pll_freq; - clockRanges->maxClock = info->pll.max_pll_freq * 10; - clockRanges->clockIndex = -1; - clockRanges->interlaceAllowed = (info->MergeType == MT_CRT); - clockRanges->doubleScanAllowed = (info->MergeType == MT_CRT); - - /* We'll use our own mode validation routine for DFP/LCD, since - * xf86ValidateModes does not work correctly with the DFP/LCD modes - * 'stretched' from their native mode. - */ - if (info->MergeType == MT_CRT && !info->ddc_mode) { - - modesFound = - xf86ValidateModes(pScrn, - pScrn->monitor->Modes, - pScrn1->display->modes, - clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ - info->allowColorTiling ? 2048 : - 64 * pScrn1->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - info->MaxLines, /* maxHeight */ - pScrn1->display->virtualX ? pScrn1->virtualX : 0, - pScrn1->display->virtualY ? pScrn1->virtualY : 0, - info->FbMapSize, - LOOKUP_BEST_REFRESH); - - if (modesFound == -1) return 0; - - xf86PruneDriverModes(pScrn); - if (!modesFound || !pScrn->modes) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); - return 0; + ScrnInfoPtr pScrn = output->scrn; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + DisplayModePtr mode; + xf86MonPtr edid_mon; + DisplayModePtr modes = NULL; + +#if 0 + /* force reprobe */ + radeon_output->MonType = MT_UNKNOWN; + + RADEONConnectorFindMonitor(pScrn, output); +#endif + ErrorF("in RADEONProbeOutputModes\n"); + + if (output->status == XF86OutputStatusConnected) { + if (radeon_output->type == OUTPUT_DVI || radeon_output->type == OUTPUT_VGA) { + edid_mon = xf86OutputGetEDID (output, radeon_output->pI2CBus); + xf86OutputSetEDID (output, edid_mon); + + modes = xf86OutputGetEDIDModes (output); + return modes; } - - } else { - /* First, free any allocated modes during configuration, since - * we don't need them - */ - while (pScrn->modes) - xf86DeleteMode(&pScrn->modes, pScrn->modes); - while (pScrn->modePool) - xf86DeleteMode(&pScrn->modePool, pScrn->modePool); - - /* Next try to add DDC modes */ - modesFound = RADEONValidateDDCModes(pScrn, pScrn1->display->modes, - info->MergeType, 1); - - /* If that fails and we're connect to a flat panel, then try to - * add the flat panel modes - */ - if (info->MergeType != MT_CRT) { - - /* some panels have DDC, but don't have internal scaler. - * in this case, we need to validate additional modes - * by using on-chip RMX. - */ - int user_modes_asked = 0, user_modes_found = 0, i; - DisplayModePtr tmp_mode = pScrn->modes; - while (pScrn1->display->modes[user_modes_asked]) user_modes_asked++; - if (tmp_mode) { - for (i = 0; i < modesFound; i++) { - if (tmp_mode->type & M_T_USERDEF) user_modes_found++; - tmp_mode = tmp_mode->next; + if (radeon_output->type == OUTPUT_STV || radeon_output->type == OUTPUT_CTV) { + modes = RADEONTVModes(output); + return modes; + } + if (radeon_output->type == OUTPUT_LVDS) { + /* okay we got DDC info */ + if (output->MonInfo) { + /* Debug info for now, at least */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %d\n", radeon_output->num); + xf86PrintEDID(output->MonInfo); + + modes = xf86DDCGetModes(pScrn->scrnIndex, output->MonInfo); + + for (mode = modes; mode != NULL; mode = mode->next) { + if (mode->Flags & V_DBLSCAN) { + if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768)) + mode->status = MODE_CLOCK_RANGE; + } } + xf86PruneInvalidModes(pScrn, &modes, TRUE); + + /* do some physcial size stuff */ } - - if ((modesFound <= 1) || (user_modes_found < user_modes_asked)) { - /* when panel size is not valid, try to validate - * mode using xf86ValidateModes routine - * This can happen when DDC is disabled. - */ - /* if (info->PanelXRes < 320 || info->PanelYRes < 200) */ - modesFound = - xf86ValidateModes(pScrn, - pScrn->monitor->Modes, - pScrn1->display->modes, - clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ - info->allowColorTiling ? 2048 : - 64 * pScrn1->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - info->MaxLines, /* maxHeight */ - pScrn1->display->virtualX, - pScrn1->display->virtualY, - info->FbMapSize, - LOOKUP_BEST_REFRESH); - - } - } - - /* Setup the screen's clockRanges for the VidMode extension */ - if (!pScrn->clockRanges) { - pScrn->clockRanges = xnfcalloc(sizeof(*(pScrn->clockRanges)), 1); - memcpy(pScrn->clockRanges, clockRanges, sizeof(*clockRanges)); - pScrn->clockRanges->strategy = LOOKUP_BEST_REFRESH; - } - - /* Fail if we still don't have any valid modes */ - if (modesFound < 1) { - if (info->MergeType == MT_CRT) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid DDC modes found for this CRT\n"); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Try turning off the \"DDCMode\" option\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid mode found for this DFP/LCD\n"); + + if (modes == NULL) { + RADEONValidateFPModes(output, pScrn->display->modes, &modes); } - return 0; } } - return modesFound; + + if (modes) { + xf86ValidateModesUserConfig(pScrn, modes); + xf86PruneInvalidModes(pScrn, &modes, FALSE); + } + + return modes; } + diff --git a/src/radeon_output.c b/src/radeon_output.c new file mode 100644 index 00000000..4df25972 --- /dev/null +++ b/src/radeon_output.c @@ -0,0 +1,2756 @@ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR + * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdio.h> + +/* X and server generic header files */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "vgaHW.h" +#include "xf86Modes.h" + +/* Driver data structures */ +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_version.h" +#include "radeon_tv.h" + + +const char *MonTypeName[7] = { + "AUTO", + "NONE", + "CRT", + "LVDS", + "TMDS", + "CTV", + "STV" +}; + +const RADEONMonitorType MonTypeID[7] = { + MT_UNKNOWN, /* this is just a dummy value for AUTO DETECTION */ + MT_NONE, /* NONE -> NONE */ + MT_CRT, /* CRT -> CRT */ + MT_LCD, /* Laptop LCDs are driven via LVDS port */ + MT_DFP, /* DFPs are driven via TMDS */ + MT_CTV, /* CTV -> CTV */ + MT_STV, /* STV -> STV */ +}; + +const char *TMDSTypeName[4] = { + "Unknown", + "Internal", + "External", + "None" +}; + +const char *DDCTypeName[6] = { + "None", + "MONID", + "DVI_DDC", + "VGA_DDC", + "CRT2_DDC", + "LCD_DDC" +}; + +const char *DACTypeName[4] = { + "Unknown", + "Primary", + "TVDAC/ExtDAC", + "None" +}; + +const char *ConnectorTypeName[8] = { + "None", + "Proprietary/LVDS", + "VGA", + "DVI-I", + "DVI-D", + "CTV", + "STV", + "Unsupported" +}; + +const char *ConnectorTypeNameATOM[10] = { + "None", + "VGA", + "DVI-I", + "DVI-D", + "DVI-A", + "STV", + "CTV", + "LVDS", + "Digital", + "Unsupported" +}; + +const char *OutputType[10] = { + "None", + "VGA", + "DVI", + "LVDS", + "S-video", + "Composite", +}; + +static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = +{ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ + {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ + {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /*CHIP_FAMILY_RV280*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */ +}; + +static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output); +static void RADEONUpdatePanelSize(xf86OutputPtr output); +static RADEONMonitorType radeon_detect_tv(ScrnInfoPtr pScrn); +static RADEONMonitorType radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color); +static RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color); +static RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn); +static void RADEONGetTMDSInfoFromTable(xf86OutputPtr output); + +void RADEONPrintPortMap(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONOutputPrivatePtr radeon_output; + xf86OutputPtr output; + int o; + + for (o = 0; o < xf86_config->num_output; o++) { + output = xf86_config->output[o]; + radeon_output = output->driver_private; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Port%d:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + o, + MonTypeName[radeon_output->MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[radeon_output->ConnectorType]: + ConnectorTypeName[radeon_output->ConnectorType], + DACTypeName[radeon_output->DACType+1], + TMDSTypeName[radeon_output->TMDSType+1], + DDCTypeName[radeon_output->DDCType]); + } + +} + +static RADEONMonitorType +RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned long DDCReg; + RADEONMonitorType MonType = MT_NONE; + xf86MonPtr* MonInfo = &output->MonInfo; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONDDCType DDCType = radeon_output->DDCType; + int i, j; + + DDCReg = radeon_output->DDCReg; + + /* Read and output monitor info using DDC2 over I2C bus */ + if (radeon_output->pI2CBus && info->ddc2 && (DDCReg != RADEON_LCD_GPIO_MASK)) { + OUTREG(DDCReg, INREG(DDCReg) & + (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); + + /* For some old monitors (like Compaq Presario FP500), we need + * following process to initialize/stop DDC + */ + OUTREG(DDCReg, INREG(DDCReg) & ~(RADEON_GPIO_EN_1)); + for (j = 0; j < 3; j++) { + OUTREG(DDCReg, + INREG(DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(13000); + + OUTREG(DDCReg, + INREG(DDCReg) & ~(RADEON_GPIO_EN_1)); + for (i = 0; i < 10; i++) { + usleep(15000); + if (INREG(DDCReg) & RADEON_GPIO_Y_1) + break; + } + if (i == 10) continue; + + usleep(15000); + + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_1); + usleep(15000); + OUTREG(DDCReg, + INREG(DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(15000); + *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, radeon_output->pI2CBus); + + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_1); + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + OUTREG(DDCReg, + INREG(DDCReg) & ~(RADEON_GPIO_EN_1)); + for (i = 0; i < 5; i++) { + usleep(15000); + if (INREG(DDCReg) & RADEON_GPIO_Y_1) + break; + } + usleep(15000); + OUTREG(DDCReg, + INREG(DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(15000); + + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_1); + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + if(*MonInfo) break; + } + } else if (radeon_output->pI2CBus && info->ddc2 && DDCReg == RADEON_LCD_GPIO_MASK) { + *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, radeon_output->pI2CBus); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); + MonType = MT_NONE; + } + + OUTREG(DDCReg, INREG(DDCReg) & + ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1)); + + if (*MonInfo) { + if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_LVDS_ATOM) || + (!info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_PROPRIETARY)) { + MonType = MT_LCD; + } else if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D_ATOM) || + (!info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D)) { + MonType = MT_DFP; + } else if ((*MonInfo)->rawData[0x14] & 0x80) { /* if it's digital */ + MonType = MT_DFP; + } else { + MonType = MT_CRT; + } + } else MonType = MT_NONE; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DDC Type: %d, Detected Monitor Type: %d\n", DDCType, MonType); + + return MonType; +} + +#if 0 +static RADEONMonitorType +RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int bConnected = 0; + + /* the monitor either wasn't connected or it is a non-DDC CRT. + * try to probe it + */ + if(IsCrtDac) { + unsigned long ulOrigVCLK_ECP_CNTL; + unsigned long ulOrigDAC_CNTL; + unsigned long ulOrigDAC_MACRO_CNTL; + unsigned long ulOrigDAC_EXT_CNTL; + unsigned long ulOrigCRTC_EXT_CNTL; + unsigned long ulData; + unsigned long ulMask; + + ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + + ulData = ulOrigVCLK_ECP_CNTL; + ulData &= ~(RADEON_PIXCLK_ALWAYS_ONb + | RADEON_PIXCLK_DAC_ALWAYS_ONb); + ulMask = ~(RADEON_PIXCLK_ALWAYS_ONb + |RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); + + ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL); + ulData = ulOrigCRTC_EXT_CNTL; + ulData |= RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, ulData); + + ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); + ulData = ulOrigDAC_EXT_CNTL; + ulData &= ~RADEON_DAC_FORCE_DATA_MASK; + ulData |= (RADEON_DAC_FORCE_BLANK_OFF_EN + |RADEON_DAC_FORCE_DATA_EN + |RADEON_DAC_FORCE_DATA_SEL_MASK); + if ((info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280)) + ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); + + OUTREG(RADEON_DAC_EXT_CNTL, ulData); + + /* turn on power so testing can go through */ + ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); + ulOrigDAC_CNTL &= ~RADEON_DAC_PDWN; + OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL); + + ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); + ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); + + /* Enable comparators and set DAC range to PS2 (VGA) output level */ + ulData = ulOrigDAC_CNTL; + ulData |= RADEON_DAC_CMP_EN; + ulData &= ~RADEON_DAC_RANGE_CNTL_MASK; + ulData |= 0x2; + OUTREG(RADEON_DAC_CNTL, ulData); + + /* Settle down */ + usleep(10000); + + /* Read comparators */ + ulData = INREG(RADEON_DAC_CNTL); + bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; + + /* Restore things */ + ulData = ulOrigVCLK_ECP_CNTL; + ulMask = 0xFFFFFFFFL; + OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); + + OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); + OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); + OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); + + if (!bConnected) { + /* Power DAC down if CRT is not connected */ + ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); + ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); + + ulData = INREG(RADEON_DAC_CNTL); + ulData |= RADEON_DAC_PDWN; + OUTREG(RADEON_DAC_CNTL, ulData); + } + } else { /* TV DAC */ + + /* This doesn't seem to work reliably (maybe worse on some OEM cards), + for now we always return false. If one wants to connected a + non-DDC monitor on the DVI port when CRT port is also connected, + he will need to explicitly tell the driver in the config file + with Option MonitorLayout. + */ + bConnected = FALSE; + +#if 0 + if (info->ChipFamily == CHIP_FAMILY_R200) { + unsigned long ulOrigGPIO_MONID; + unsigned long ulOrigFP2_GEN_CNTL; + unsigned long ulOrigDISP_OUTPUT_CNTL; + unsigned long ulOrigCRTC2_GEN_CNTL; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_A; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_B; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_C; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_D; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_E; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_F; + unsigned long ulOrigCRTC2_H_TOTAL_DISP; + unsigned long ulOrigCRTC2_V_TOTAL_DISP; + unsigned long ulOrigCRTC2_H_SYNC_STRT_WID; + unsigned long ulOrigCRTC2_V_SYNC_STRT_WID; + unsigned long ulData, i; + + ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID); + ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL); + ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); + ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); + ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); + ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); + ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); + ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); + ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); + ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); + + ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP); + ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP); + ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); + ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); + + ulData = INREG(RADEON_GPIO_MONID); + ulData &= ~RADEON_GPIO_A_0; + OUTREG(RADEON_GPIO_MONID, ulData); + + OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c); + + OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012); + + OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) { + ulData = INREG(RADEON_GPIO_MONID); + bConnected = (ulData & RADEON_GPIO_Y_0)?1:0; + if (!bConnected) break; + + usleep(1000); + } + + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID); + OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL); + OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); + OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); + OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); + } else { + unsigned long ulOrigPIXCLKSDATA; + unsigned long ulOrigTV_MASTER_CNTL; + unsigned long ulOrigTV_DAC_CNTL; + unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; + unsigned long ulOrigDAC_CNTL2; + unsigned long ulData; + unsigned long ulMask; + + ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + + ulData = ulOrigPIXCLKSDATA; + ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); + + ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); + ulData = ulOrigTV_MASTER_CNTL; + ulData &= ~RADEON_TVCLK_ALWAYS_ONb; + OUTREG(RADEON_TV_MASTER_CNTL, ulData); + + ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); + ulData = ulOrigDAC_CNTL2; + ulData &= ~RADEON_DAC2_DAC2_CLK_SEL; + OUTREG(RADEON_DAC_CNTL2, ulData); + + ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); + + ulData = 0x00880213; + OUTREG(RADEON_TV_DAC_CNTL, ulData); + + ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); + + ulData = (RADEON_Y_RED_EN + | RADEON_C_GRN_EN + | RADEON_CMP_BLU_EN + | RADEON_RED_MX_FORCE_DAC_DATA + | RADEON_GRN_MX_FORCE_DAC_DATA + | RADEON_BLU_MX_FORCE_DAC_DATA); + if (IS_R300_VARIANT) + ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT; + else + ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT; + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData); + + usleep(10000); + + ulData = INREG(RADEON_TV_DAC_CNTL); + bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; + + ulData = ulOrigPIXCLKSDATA; + ulMask = 0xFFFFFFFFL; + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); + + OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); + OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); + OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); + } +#endif + return MT_UNKNOWN; + } + + return(bConnected ? MT_CRT : MT_NONE); +} +#endif + +/* Primary Head (DVI or Laptop Int. panel)*/ +/* A ddc capable display connected on DVI port */ +/* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ +void RADEONConnectorFindMonitor(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (radeon_output->MonType == MT_UNKNOWN) { + if (radeon_output->type == OUTPUT_STV || radeon_output->type == OUTPUT_CTV) { + if (info->InternalTVOut) { + if (radeon_output->load_detection) + radeon_output->MonType = radeon_detect_tv(pScrn); + else + radeon_output->MonType = MT_NONE; + } + } else { + radeon_output->MonType = RADEONDisplayDDCConnected(pScrn, output); + if (!radeon_output->MonType) { + if (radeon_output->type == OUTPUT_LVDS || radeon_output->type == OUTPUT_DVI) + radeon_output->MonType = RADEONPortCheckNonDDC(pScrn, output); + if (!radeon_output->MonType) { + if (radeon_output->DACType == DAC_PRIMARY) { + if (radeon_output->load_detection) + radeon_output->MonType = radeon_detect_primary_dac(pScrn, TRUE); + } else if (radeon_output->DACType == DAC_TVDAC) { + if (radeon_output->load_detection) { + if (info->ChipFamily == CHIP_FAMILY_R200) + radeon_output->MonType = radeon_detect_ext_dac(pScrn); + else + radeon_output->MonType = radeon_detect_tv_dac(pScrn, TRUE); + } else + radeon_output->MonType = MT_NONE; + } + } + } + } + } + + /* update panel info for RMX */ + if (radeon_output->MonType == MT_LCD || radeon_output->MonType == MT_DFP) + RADEONUpdatePanelSize(output); + + if (output->MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on connector: %s ----------------------\n", + info->IsAtomBios ? + ConnectorTypeNameATOM[radeon_output->ConnectorType]: + ConnectorTypeName[radeon_output->ConnectorType] + ); + xf86PrintEDID( output->MonInfo ); + } +} + +static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONMonitorType MonType = MT_NONE; + + + if (radeon_output->type == OUTPUT_LVDS) { + MonType = MT_LCD; + } else if (radeon_output->type == OUTPUT_DVI) { + if (radeon_output->TMDSType == TMDS_INT) { + if (INREG(RADEON_FP_GEN_CNTL) & RADEON_FP_DETECT_SENSE) + MonType = MT_DFP; + } else if (radeon_output->TMDSType == TMDS_EXT) { + if (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_DETECT_SENSE) + MonType = MT_DFP; + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected Monitor Type: %d\n", MonType); + + return MonType; + +} + +static void +radeon_dpms(xf86OutputPtr output, int mode) +{ + switch(mode) { + case DPMSModeOn: + RADEONEnableDisplay(output, TRUE); + break; + case DPMSModeOff: + case DPMSModeSuspend: + case DPMSModeStandby: + RADEONEnableDisplay(output, FALSE); + break; + } +} + +static void +radeon_save(xf86OutputPtr output) +{ + +} + +static void +radeon_restore(xf86OutputPtr restore) +{ + +} + +static int +radeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + /* FIXME: Update when more modes are added */ + if (pMode->HDisplay == 800 && pMode->VDisplay == 600) + return MODE_OK; + else + return MODE_CLOCK_RANGE; + } + + if (radeon_output->type != OUTPUT_LVDS) + return MODE_OK; + + if (pMode->HDisplay > radeon_output->PanelXRes || + pMode->VDisplay > radeon_output->PanelYRes) + return MODE_PANEL; + + return MODE_OK; +} + +static Bool +radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (radeon_output->MonType == MT_LCD || radeon_output->MonType == MT_DFP) { + xf86CrtcPtr crtc = output->crtc; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + if ((mode->HDisplay < radeon_output->PanelXRes || + mode->VDisplay < radeon_output->PanelYRes) && + radeon_crtc->crtc_id == 0) + adjusted_mode->Flags |= RADEON_USE_RMX; + + if (adjusted_mode->Flags & RADEON_USE_RMX) { + adjusted_mode->CrtcHTotal = mode->CrtcHDisplay + radeon_output->HBlank; + adjusted_mode->CrtcHSyncStart = mode->CrtcHDisplay + radeon_output->HOverPlus; + adjusted_mode->CrtcHSyncEnd = mode->CrtcHSyncStart + radeon_output->HSyncWidth; + adjusted_mode->CrtcVTotal = mode->CrtcVDisplay + radeon_output->VBlank; + adjusted_mode->CrtcVSyncStart = mode->CrtcVDisplay + radeon_output->VOverPlus; + adjusted_mode->CrtcVSyncEnd = mode->CrtcVSyncStart + radeon_output->VSyncWidth; + adjusted_mode->Clock = radeon_output->DotClock; + radeon_output->Flags |= RADEON_USE_RMX; + adjusted_mode->Flags = radeon_output->Flags; + } else + radeon_output->Flags &= ~RADEON_USE_RMX; + + } + + return TRUE; +} + +static void +radeon_mode_prepare(xf86OutputPtr output) +{ +} + +static void RADEONInitFPRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int i; + CARD32 tmp = info->SavedReg.tmds_pll_cntl & 0xfffff; + + for (i=0; i<4; i++) { + if (radeon_output->tmds_pll[i].freq == 0) break; + if ((CARD32)(mode->Clock/10) < radeon_output->tmds_pll[i].freq) { + tmp = radeon_output->tmds_pll[i].value ; + break; + } + } + + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) { + if (tmp & 0xfff00000) + save->tmds_pll_cntl = tmp; + else { + save->tmds_pll_cntl = info->SavedReg.tmds_pll_cntl & 0xfff00000; + save->tmds_pll_cntl |= tmp; + } + } else save->tmds_pll_cntl = tmp; + + save->tmds_transmitter_cntl = info->SavedReg.tmds_transmitter_cntl & + ~(RADEON_TMDS_TRANSMITTER_PLLRST); + + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !pRADEONEnt->HasCRTC2) + save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); + else /* weird, RV chips got this bit reversed? */ + save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); + + save->fp_gen_cntl = info->SavedReg.fp_gen_cntl | + (RADEON_FP_CRTC_DONT_SHADOW_VPAR | + RADEON_FP_CRTC_DONT_SHADOW_HEND ); + + save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + + if (pScrn->rgbBits == 8) + save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ + else + save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ + + + if (IsPrimary) { + if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { + save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + if (mode->Flags & RADEON_USE_RMX) + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; + else + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; + } else + save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1; + } else { + if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { + save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; + } else + save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2; + } + +} + +static void RADEONInitFP2Registers(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + + if (pScrn->rgbBits == 8) + save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl | + RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ + else + save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl & + ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ + + save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + + if (IsPrimary) { + if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_EN | + RADEON_FP2_DVO_RATE_SEL_SDR); + if (mode->Flags & RADEON_USE_RMX) + save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; + } else { + save->fp2_gen_cntl &= ~(RADEON_FP2_SRC_SEL_CRTC2 | + RADEON_FP2_DVO_RATE_SEL_SDR); + } + } else { + if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; + } else { + save->fp2_gen_cntl &= ~(RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; + } + } + +} + +static void RADEONInitLVDSRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + save->lvds_pll_cntl = info->SavedReg.lvds_pll_cntl; + + save->lvds_gen_cntl = info->SavedReg.lvds_gen_cntl; + save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; + save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON); + + if (IsPrimary) + save->lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; + else + save->lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2; + +} + +static void RADEONInitRMXRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int xres = mode->HDisplay; + int yres = mode->VDisplay; + float Hratio, Vratio; + + save->fp_vert_stretch = info->SavedReg.fp_vert_stretch & + RADEON_VERT_STRETCH_RESERVED; + save->fp_horz_stretch = info->SavedReg.fp_horz_stretch & + (RADEON_HORZ_FP_LOOP_STRETCH | + RADEON_HORZ_AUTO_RATIO_INC); + + if (radeon_output->MonType != MT_LCD && radeon_output->MonType != MT_DFP) + return; + + if (radeon_output->PanelXRes == 0 || radeon_output->PanelYRes == 0) { + Hratio = 1.0; + Vratio = 1.0; + } else { + if (xres > radeon_output->PanelXRes) xres = radeon_output->PanelXRes; + if (yres > radeon_output->PanelYRes) yres = radeon_output->PanelYRes; + + Hratio = (float)xres/(float)radeon_output->PanelXRes; + Vratio = (float)yres/(float)radeon_output->PanelYRes; + } + + if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { + save->fp_horz_stretch |= ((xres/8-1)<<16); + } else { + save->fp_horz_stretch |= ((((unsigned long) + (Hratio * RADEON_HORZ_STRETCH_RATIO_MAX)) & + RADEON_HORZ_STRETCH_RATIO_MASK) | + RADEON_HORZ_STRETCH_BLEND | + RADEON_HORZ_STRETCH_ENABLE | + ((radeon_output->PanelXRes/8-1)<<16)); + } + + if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { + save->fp_vert_stretch |= ((yres-1)<<12); + } else { + save->fp_vert_stretch |= ((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX)) & + RADEON_VERT_STRETCH_RATIO_MASK) | + RADEON_VERT_STRETCH_ENABLE | + RADEON_VERT_STRETCH_BLEND | + ((radeon_output->PanelYRes-1)<<12)); + } + +} + +static void RADEONInitDACRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (IsPrimary) { + if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg.disp_output_cntl & + ~RADEON_DISP_DAC_SOURCE_MASK; + } else { + save->dac2_cntl = info->SavedReg.dac2_cntl & ~(RADEON_DAC2_DAC_CLK_SEL); + } + } else { + if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg.disp_output_cntl & + ~RADEON_DISP_DAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; + } else { + save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC_CLK_SEL; + } + } + save->dac_cntl = (RADEON_DAC_MASK_ALL + | RADEON_DAC_VGA_ADR_EN + | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN)); + + save->dac_macro_cntl = info->SavedReg.dac_macro_cntl; +} + +/* XXX: fix me */ +static void +RADEONInitTvDacCntl(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (info->ChipFamily == CHIP_FAMILY_R420 || + info->ChipFamily == CHIP_FAMILY_RV410) { + save->tv_dac_cntl = info->SavedReg.tv_dac_cntl & + ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + R420_TV_DAC_DACADJ_MASK | + R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_TVENABLE); + } else { + save->tv_dac_cntl = info->SavedReg.tv_dac_cntl & + ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + RADEON_TV_DAC_DACADJ_MASK | + RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_GDACPD); + } + /* FIXME: doesn't make sense, this just replaces the previous value... */ + save->tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_DAC_STD_PS2); + +} + +static void RADEONInitDAC2Registers(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + /*0x0028023;*/ + RADEONInitTvDacCntl(pScrn, save); + + if (IS_R300_VARIANT) + save->gpiopad_a = info->SavedReg.gpiopad_a | 1; + + save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; + + if (IsPrimary) { + if (IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg.disp_output_cntl & + ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; + } else if (info->ChipFamily == CHIP_FAMILY_R200) { + save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl & + ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + } else { + save->disp_hw_debug = info->SavedReg.disp_hw_debug | RADEON_CRT2_DISP1_SEL; + } + } else { + if (IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg.disp_output_cntl & + ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + } else if (info->ChipFamily == CHIP_FAMILY_R200) { + save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl & + ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; + } else { + save->disp_hw_debug = info->SavedReg.disp_hw_debug & + ~RADEON_CRT2_DISP1_SEL; + } + } +} + +static void +RADEONInitOutputRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output, + int crtc_num) +{ + Bool IsPrimary = crtc_num == 0 ? TRUE : FALSE; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (crtc_num == 0) + RADEONInitRMXRegisters(output, save, mode); + + if (radeon_output->MonType == MT_CRT) { + if (radeon_output->DACType == DAC_PRIMARY) { + RADEONInitDACRegisters(output, save, mode, IsPrimary); + } else { + RADEONInitDAC2Registers(output, save, mode, IsPrimary); + } + } else if (radeon_output->MonType == MT_LCD) { + RADEONInitLVDSRegisters(output, save, mode, IsPrimary); + } else if (radeon_output->MonType == MT_DFP) { + if (radeon_output->TMDSType == TMDS_INT) { + RADEONInitFPRegisters(output, save, mode, IsPrimary); + } else { + RADEONInitFP2Registers(output, save, mode, IsPrimary); + } + } else if (radeon_output->MonType == MT_STV || + radeon_output->MonType == MT_CTV) { + RADEONInitTVRegisters(output, save, mode, IsPrimary); + } +} + +static void +radeon_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + xf86CrtcPtr crtc = output->crtc; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + if (radeon_output->type == OUTPUT_DVI && + radeon_output->TMDSType == TMDS_INT) { + if (radeon_output->tmds_pll_table == TMDS_PLL_BIOS) { + if (!RADEONGetTMDSInfoFromBIOS(output)) + RADEONGetTMDSInfoFromTable(output); + } else + RADEONGetTMDSInfoFromTable(output); + } + + RADEONInitOutputRegisters(pScrn, &info->ModeReg, adjusted_mode, output, radeon_crtc->crtc_id); + + if (radeon_crtc->crtc_id == 0) + RADEONRestoreRMXRegisters(pScrn, &info->ModeReg); + + switch(radeon_output->MonType) { + case MT_LCD: + ErrorF("restore LVDS\n"); + RADEONRestoreLVDSRegisters(pScrn, &info->ModeReg); + break; + case MT_DFP: + if (radeon_output->TMDSType == TMDS_INT) { + ErrorF("restore FP\n"); + RADEONRestoreFPRegisters(pScrn, &info->ModeReg); + } else { + ErrorF("restore FP2\n"); + RADEONRestoreFP2Registers(pScrn, &info->ModeReg); + } + break; + case MT_STV: + case MT_CTV: + ErrorF("restore tv\n"); + RADEONRestoreDACRegisters(pScrn, &info->ModeReg); + RADEONRestoreTVRegisters(pScrn, &info->ModeReg); + break; + default: + ErrorF("restore dac\n"); + RADEONRestoreDACRegisters(pScrn, &info->ModeReg); + } + +} + +static void +radeon_mode_commit(xf86OutputPtr output) +{ + RADEONEnableDisplay(output, TRUE); +} + +/* the following functions are based on the load detection code + * in the beos radeon driver by Thomas Kurschel and the existing + * load detection code in this driver. + */ +static RADEONMonitorType +radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 vclk_ecp_cntl, crtc_ext_cntl; + CARD32 dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp; + RADEONMonitorType found = MT_NONE; + + /* save the regs we need */ + vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); + dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); + dac_cntl = INREG(RADEON_DAC_CNTL); + dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); + + tmp = vclk_ecp_cntl & + ~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); + + tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, tmp); + + tmp = RADEON_DAC_FORCE_BLANK_OFF_EN | + RADEON_DAC_FORCE_DATA_EN; + + if (color) + tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; + else + tmp |= RADEON_DAC_FORCE_DATA_SEL_G; + + if (IS_R300_VARIANT) + tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); + + OUTREG(RADEON_DAC_EXT_CNTL, tmp); + + tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN); + tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; + OUTREG(RADEON_DAC_CNTL, tmp); + + tmp &= ~(RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + + OUTREG(RADEON_DAC_MACRO_CNTL, tmp); + + usleep(2000); + + if (INREG(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) { + found = MT_CRT; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Found %s CRT connected to primary DAC\n", + color ? "color" : "bw"); + } + + /* restore the regs we used */ + OUTREG(RADEON_DAC_CNTL, dac_cntl); + OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); + OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl); + + return found; +} + +static RADEONMonitorType +radeon_detect_ext_dac(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; + CARD32 disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; + CARD32 disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; + CARD32 tmp, crtc2_h_total_disp, crtc2_v_total_disp; + CARD32 crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; + RADEONMonitorType found = MT_NONE; + int connected = 0; + int i = 0; + + /* save the regs we need */ + gpio_monid = INREG(RADEON_GPIO_MONID); + fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); + disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + disp_lin_trans_grph_a = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); + disp_lin_trans_grph_b = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); + disp_lin_trans_grph_c = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); + disp_lin_trans_grph_d = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); + disp_lin_trans_grph_e = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); + disp_lin_trans_grph_f = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); + crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP); + crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP); + crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); + crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); + + tmp = INREG(RADEON_GPIO_MONID); + tmp &= ~RADEON_GPIO_A_0; + OUTREG(RADEON_GPIO_MONID, tmp); + + OUTREG(RADEON_FP2_GEN_CNTL, + RADEON_FP2_ON | + RADEON_FP2_PANEL_FORMAT | + R200_FP2_SOURCE_SEL_TRANS_UNIT | + RADEON_FP2_DVO_EN | + R200_FP2_DVO_RATE_SEL_SDR); + + OUTREG(RADEON_DISP_OUTPUT_CNTL, + RADEON_DISP_DAC_SOURCE_RMX | + RADEON_DISP_TRANS_MATRIX_GRAPHICS); + + OUTREG(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_EN | + RADEON_CRTC2_DISP_REQ_EN_B); + + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) { + tmp = INREG(RADEON_GPIO_MONID); + if (tmp & RADEON_GPIO_Y_0) + connected = 1; + else + connected = 0; + + if (!connected) + break; + + usleep(1000); + } + + if (connected) + found = MT_CRT; + + /* restore the regs we used */ + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); + OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + OUTREG(RADEON_GPIO_MONID, gpio_monid); + + return found; +} + +static RADEONMonitorType +radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; + CARD32 disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; + RADEONMonitorType found = MT_NONE; + + /* save the regs we need */ + pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + gpiopad_a = IS_R300_VARIANT ? INREG(RADEON_GPIOPAD_A) : 0; + disp_output_cntl = IS_R300_VARIANT ? INREG(RADEON_DISP_OUTPUT_CNTL) : 0; + disp_hw_debug = !IS_R300_VARIANT ? INREG(RADEON_DISP_HW_DEBUG) : 0; + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); + dac_cntl2 = INREG(RADEON_DAC_CNTL2); + + tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + + if (IS_R300_VARIANT) { + OUTREGP(RADEON_GPIOPAD_A, 1, ~1 ); + } + + tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; + tmp |= RADEON_CRTC2_CRT2_ON | + (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); + + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); + + if (IS_R300_VARIANT) { + tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; + tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp); + } else { + tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; + OUTREG(RADEON_DISP_HW_DEBUG, tmp); + } + + tmp = RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | + RADEON_TV_DAC_STD_PS2; + + OUTREG(RADEON_TV_DAC_CNTL, tmp); + + tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN | + RADEON_DAC2_FORCE_DATA_EN; + + if (color) + tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; + else + tmp |= RADEON_DAC_FORCE_DATA_SEL_G; + + if (IS_R300_VARIANT) + tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); + + OUTREG(RADEON_DAC_EXT_CNTL, tmp); + + tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN; + OUTREG(RADEON_DAC_CNTL2, tmp); + + usleep(10000); + + if (IS_R300_VARIANT) { + if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) { + found = MT_CRT; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Found %s CRT connected to TV DAC\n", + color ? "color" : "bw"); + } + } else { + if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) { + found = MT_CRT; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Found %s CRT connected to TV DAC\n", + color ? "color" : "bw"); + } + } + + /* restore regs we used */ + OUTREG(RADEON_DAC_CNTL2, dac_cntl2); + OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + + if (IS_R300_VARIANT) { + OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1 ); + } else { + OUTREG(RADEON_DISP_HW_DEBUG, disp_hw_debug); + } + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, pixclks_cntl); + + return found; +} + +static RADEONMonitorType +r300_detect_tv(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp, dac_cntl2, crtc2_gen_cntl, dac_ext_cntl, tv_dac_cntl; + CARD32 gpiopad_a, disp_output_cntl; + RADEONMonitorType found = MT_NONE; + + /* save the regs we need */ + gpiopad_a = INREG(RADEON_GPIOPAD_A); + dac_cntl2 = INREG(RADEON_DAC_CNTL2); + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); + + OUTREGP(RADEON_GPIOPAD_A, 0, ~1 ); + + OUTREG(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL ); + + OUTREG(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT ); + + tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; + tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp); + + OUTREG(RADEON_DAC_EXT_CNTL, + RADEON_DAC2_FORCE_BLANK_OFF_EN | + RADEON_DAC2_FORCE_DATA_EN | + RADEON_DAC_FORCE_DATA_SEL_RGB | + (0xec << RADEON_DAC_FORCE_DATA_SHIFT )); + + OUTREG(RADEON_TV_DAC_CNTL, + RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT) | + (6 << RADEON_TV_DAC_DACADJ_SHIFT )); + + INREG(RADEON_TV_DAC_CNTL); + + usleep(4000); + + OUTREG(RADEON_TV_DAC_CNTL, + RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | + RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT) | + (6 << RADEON_TV_DAC_DACADJ_SHIFT )); + + INREG(RADEON_TV_DAC_CNTL); + + usleep(6000); + + tmp = INREG(RADEON_TV_DAC_CNTL); + if ( (tmp & RADEON_TV_DAC_GDACDET) != 0 ) { + found = MT_STV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "S-Video TV connection detected\n"); + } else if ( (tmp & RADEON_TV_DAC_BDACDET) != 0 ) { + found = MT_CTV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Composite TV connection detected\n" ); + } + + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl ); + OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + OUTREG(RADEON_DAC_CNTL2, dac_cntl2); + OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1); + + return found; +} + +static RADEONMonitorType +radeon_detect_tv(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp, dac_cntl2, tv_master_cntl; + CARD32 tv_dac_cntl, tv_pre_dac_mux_cntl, config_cntl; + RADEONMonitorType found = MT_NONE; + + if (IS_R300_VARIANT) + return r300_detect_tv(pScrn); + + /* save the regs we need */ + dac_cntl2 = INREG(RADEON_DAC_CNTL2); + tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL); + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + config_cntl = INREG(RADEON_CONFIG_CNTL); + tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); + + tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL; + OUTREG(RADEON_DAC_CNTL2, tmp); + + tmp = tv_master_cntl | RADEON_TV_ON; + tmp &= ~(RADEON_TV_ASYNC_RST | + RADEON_RESTART_PHASE_FIX | + RADEON_CRT_FIFO_CE_EN | + RADEON_TV_FIFO_CE_EN | + RADEON_RE_SYNC_NOW_SEL_MASK); + tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST; + + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + + tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT); + + if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK) + tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT); + else + tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT); + + OUTREG(RADEON_TV_DAC_CNTL, tmp); + + tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN | + RADEON_RED_MX_FORCE_DAC_DATA | + RADEON_GRN_MX_FORCE_DAC_DATA | + RADEON_BLU_MX_FORCE_DAC_DATA | + (0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT); + + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tmp); + + usleep(3000); + + tmp = INREG(RADEON_TV_DAC_CNTL); + if (tmp & RADEON_TV_DAC_GDACDET) { + found = MT_STV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "S-Video TV connection detected\n"); + } else if (tmp & RADEON_TV_DAC_BDACDET) { + found = MT_CTV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Composite TV connection detected\n" ); + } + + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl); + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + OUTREG(RADEON_TV_MASTER_CNTL, tv_master_cntl); + OUTREG(RADEON_DAC_CNTL2, dac_cntl2); + + return found; +} + +static xf86OutputStatus +radeon_detect(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + Bool connected = TRUE; + + radeon_output->MonType = MT_UNKNOWN; + RADEONConnectorFindMonitor(pScrn, output); + + /* force montype based on output property */ + if (radeon_output->type == OUTPUT_DVI) { + if (radeon_output->MonType == MT_NONE) + connected = FALSE; + if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_I_ATOM) || + (!info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_I)) { + if (radeon_output->DVIType == DVI_ANALOG) + radeon_output->MonType = MT_CRT; + else if (radeon_output->DVIType == DVI_DIGITAL) + radeon_output->MonType = MT_DFP; + } + } + + /* set montype so users can force outputs on even if detection fails */ + if (radeon_output->MonType == MT_NONE) { + connected = FALSE; + if (radeon_output->type == OUTPUT_LVDS) + radeon_output->MonType = MT_LCD; + else if (radeon_output->type == OUTPUT_VGA) + radeon_output->MonType = MT_CRT; + else if (radeon_output->type == OUTPUT_STV) + radeon_output->MonType = MT_STV; + else if (radeon_output->type == OUTPUT_CTV) + radeon_output->MonType = MT_CTV; + else if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D_ATOM) || + (!info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D)) + radeon_output->MonType = MT_DFP; + } + + if (radeon_output->MonType == MT_UNKNOWN) { + output->subpixel_order = SubPixelUnknown; + return XF86OutputStatusUnknown; + } else { + + switch(radeon_output->MonType) { + case MT_LCD: + case MT_DFP: + output->subpixel_order = SubPixelHorizontalRGB; + break; + default: + output->subpixel_order = SubPixelNone; + break; + } + + if (connected) + return XF86OutputStatusConnected; + else + return XF86OutputStatusDisconnected; + } + +} + +static DisplayModePtr +radeon_get_modes(xf86OutputPtr output) +{ + DisplayModePtr modes; + modes = RADEONProbeOutputModes(output); + return modes; +} + +static void +radeon_destroy (xf86OutputPtr output) +{ + if(output->driver_private) + xfree(output->driver_private); +} + +static void +radeon_set_backlight_level(xf86OutputPtr output, int level) +{ +#if 0 + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char * RADEONMMIO = info->MMIO; + CARD32 lvds_gen_cntl; + + lvds_gen_cntl = INREG(RADEON_LVDS_GEN_CNTL); + lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN; + lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_LEVEL_MASK; + lvds_gen_cntl |= (level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & RADEON_LVDS_BL_MOD_LEVEL_MASK; + //usleep (radeon_output->PanelPwrDly * 1000); + OUTREG(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN; + //usleep (radeon_output->PanelPwrDly * 1000); + OUTREG(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); +#endif +} + +static Atom backlight_atom; +static Atom tmds_pll_atom; +static Atom rmx_atom; +static Atom monitor_type_atom; +static Atom load_detection_atom; +static Atom tv_hsize_atom; +static Atom tv_hpos_atom; +static Atom tv_vpos_atom; +static Atom tv_std_atom; +#define RADEON_MAX_BACKLIGHT_LEVEL 255 + +static void +radeon_create_resources(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + INT32 range[2]; + int data, err; + const char *s; + + /* backlight control */ + if (radeon_output->type == OUTPUT_LVDS) { + backlight_atom = MAKE_ATOM("backlight"); + + range[0] = 0; + range[1] = RADEON_MAX_BACKLIGHT_LEVEL; + err = RRConfigureOutputProperty(output->randr_output, backlight_atom, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + /* Set the current value of the backlight property */ + //data = (info->SavedReg.lvds_gen_cntl & RADEON_LVDS_BL_MOD_LEVEL_MASK) >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT; + data = RADEON_MAX_BACKLIGHT_LEVEL; + err = RRChangeOutputProperty(output->randr_output, backlight_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + if (radeon_output->DACType == DAC_PRIMARY || + radeon_output->DACType == DAC_TVDAC) { + load_detection_atom = MAKE_ATOM("load_detection"); + + range[0] = 0; /* off */ + range[1] = 1; /* on */ + err = RRConfigureOutputProperty(output->randr_output, load_detection_atom, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + + if (radeon_output->DACType == DAC_PRIMARY) + data = 1; /* primary dac, only drives vga */ + else if (radeon_output->DACType == DAC_TVDAC && + info->tvdac_use_count < 2) + data = 1; /* only one output with tvdac */ + else + data = 0; /* shared tvdac between vga/dvi/tv */ + + err = RRChangeOutputProperty(output->randr_output, load_detection_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + if (radeon_output->type == OUTPUT_DVI && + radeon_output->TMDSType == TMDS_INT) { + tmds_pll_atom = MAKE_ATOM("tmds_pll"); + + err = RRConfigureOutputProperty(output->randr_output, tmds_pll_atom, + FALSE, FALSE, FALSE, 0, NULL); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + /* Set the current value of the property */ +#if defined(__powerpc__) + s = "driver"; +#else + s = "bios"; +#endif + err = RRChangeOutputProperty(output->randr_output, tmds_pll_atom, + XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s, + FALSE, FALSE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + + } + + /* RMX control - fullscreen, centered, keep ratio */ + /* actually more of a crtc property as only crtc1 has rmx */ + if (radeon_output->type == OUTPUT_LVDS || + radeon_output->type == OUTPUT_DVI) { + rmx_atom = MAKE_ATOM("scaler"); + + err = RRConfigureOutputProperty(output->randr_output, rmx_atom, + FALSE, FALSE, FALSE, 0, NULL); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + /* Set the current value of the property */ + s = "full"; + err = RRChangeOutputProperty(output->randr_output, rmx_atom, + XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s, + FALSE, FALSE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + /* force auto/analog/digital for DVI-I ports */ + if (radeon_output->type == OUTPUT_DVI) { + if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_I_ATOM) || + (!info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_I)) { + monitor_type_atom = MAKE_ATOM("dvi_monitor_type"); + + err = RRConfigureOutputProperty(output->randr_output, monitor_type_atom, + FALSE, FALSE, FALSE, 0, NULL); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + /* Set the current value of the backlight property */ + s = "auto"; + err = RRChangeOutputProperty(output->randr_output, monitor_type_atom, + XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s, + FALSE, FALSE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + } + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + tv_hsize_atom = MAKE_ATOM("tv_horizontal_size"); + + range[0] = -MAX_H_SIZE; + range[1] = MAX_H_SIZE; + err = RRConfigureOutputProperty(output->randr_output, tv_hsize_atom, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + data = 0; + err = RRChangeOutputProperty(output->randr_output, tv_hsize_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + tv_hpos_atom = MAKE_ATOM("tv_horizontal_position"); + + range[0] = -MAX_H_POSITION; + range[1] = MAX_H_POSITION; + err = RRConfigureOutputProperty(output->randr_output, tv_hpos_atom, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + data = 0; + err = RRChangeOutputProperty(output->randr_output, tv_hpos_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + tv_vpos_atom = MAKE_ATOM("tv_vertical_position"); + + range[0] = -MAX_V_POSITION; + range[1] = MAX_V_POSITION; + err = RRConfigureOutputProperty(output->randr_output, tv_vpos_atom, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + data = 0; + err = RRChangeOutputProperty(output->randr_output, tv_vpos_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + tv_std_atom = MAKE_ATOM("tv_standard"); + + err = RRConfigureOutputProperty(output->randr_output, tv_std_atom, + FALSE, FALSE, FALSE, 0, NULL); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + /* Set the current value of the backlight property */ + switch (radeon_output->default_tvStd) { + case TV_STD_PAL: + s = "pal"; + break; + case TV_STD_PAL_M: + s = "pal-m"; + break; + case TV_STD_PAL_60: + s = "pal-60"; + break; + case TV_STD_NTSC_J: + s = "ntsc-j"; + break; + case TV_STD_SCART_PAL: + s = "scart-pal"; + break; + case TV_STD_NTSC: + default: + s = "ntsc"; + break; + } + err = RRChangeOutputProperty(output->randr_output, tv_std_atom, + XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s, + FALSE, FALSE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } +} + +static Bool +radeon_set_property(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + INT32 val; + + + if (property == backlight_atom) { + if (value->type != XA_INTEGER || + value->format != 32 || + value->size != 1) { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < 0 || val > RADEON_MAX_BACKLIGHT_LEVEL) + return FALSE; + +#if defined(__powerpc__) + val = RADEON_MAX_BACKLIGHT_LEVEL - val; +#endif + + radeon_set_backlight_level(output, val); + + } else if (property == load_detection_atom) { + if (value->type != XA_INTEGER || + value->format != 32 || + value->size != 1) { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < 0 || val > 1) + return FALSE; + + radeon_output->load_detection = val; + + } else if (property == rmx_atom) { + xf86CrtcPtr crtc = output->crtc; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + if (radeon_crtc->crtc_id == 0) { + const char *s; + if (value->type != XA_STRING || value->format != 8) + return FALSE; + s = (char*)value->data; + if (value->size == strlen("full") && !strncmp("full", s, strlen("full"))) { + return TRUE; + } else if (value->size == strlen("aspect") && !strncmp("aspect", s, strlen("aspect"))) { + return TRUE; + } else if (value->size == strlen("center") && !strncmp("center", s, strlen("center"))) { + return TRUE; + } + return FALSE; + } else { + return FALSE; + } + } else if (property == tmds_pll_atom) { + const char *s; + if (value->type != XA_STRING || value->format != 8) + return FALSE; + s = (char*)value->data; + if (value->size == strlen("bios") && !strncmp("bios", s, strlen("bios"))) { + radeon_output->tmds_pll_table = TMDS_PLL_BIOS; + return TRUE; + } else if (value->size == strlen("driver") && !strncmp("driver", s, strlen("driver"))) { + radeon_output->tmds_pll_table = TMDS_PLL_DRIVER; + return TRUE; + } + return FALSE; + } else if (property == monitor_type_atom) { + const char *s; + if (value->type != XA_STRING || value->format != 8) + return FALSE; + s = (char*)value->data; + if (value->size == strlen("auto") && !strncmp("auto", s, strlen("auto"))) { + radeon_output->DVIType = DVI_AUTO; + return TRUE; + } else if (value->size == strlen("analog") && !strncmp("analog", s, strlen("analog"))) { + radeon_output->DVIType = DVI_ANALOG; + return TRUE; + } else if (value->size == strlen("digital") && !strncmp("digital", s, strlen("digital"))) { + radeon_output->DVIType = DVI_DIGITAL; + return TRUE; + } + return FALSE; + } else if (property == tv_hsize_atom) { + if (value->type != XA_INTEGER || + value->format != 32 || + value->size != 1) { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < -MAX_H_SIZE || val > MAX_H_SIZE) + return FALSE; + + radeon_output->hSize = val; + if (radeon_output->tv_on) + RADEONUpdateHVPosition(output, &output->crtc->mode); + return TRUE; + } else if (property == tv_hpos_atom) { + if (value->type != XA_INTEGER || + value->format != 32 || + value->size != 1) { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < -MAX_H_POSITION || val > MAX_H_POSITION) + return FALSE; + + radeon_output->hPos = val; + if (radeon_output->tv_on) + RADEONUpdateHVPosition(output, &output->crtc->mode); + return TRUE; + } else if (property == tv_vpos_atom) { + if (value->type != XA_INTEGER || + value->format != 32 || + value->size != 1) { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < -MAX_H_POSITION || val > MAX_H_POSITION) + return FALSE; + + radeon_output->vPos = val; + if (radeon_output->tv_on) + RADEONUpdateHVPosition(output, &output->crtc->mode); + return TRUE; + } else if (property == tv_std_atom) { + const char *s; + if (value->type != XA_STRING || value->format != 8) + return FALSE; + s = (char*)value->data; + if (value->size == strlen("default") && !strncmp("default", s, strlen("default"))) { + radeon_output->tvStd = radeon_output->default_tvStd; + return TRUE; + } else if (value->size == strlen("ntsc") && !strncmp("ntsc", s, strlen("ntsc"))) { + if (radeon_output->SupportedTVStds & TV_STD_NTSC) { + radeon_output->tvStd = TV_STD_NTSC; + return TRUE; + } else { + return FALSE; + } + } else if (value->size == strlen("pal") && !strncmp("pal", s, strlen("pal"))) { + if (radeon_output->SupportedTVStds & TV_STD_PAL) { + radeon_output->tvStd = TV_STD_PAL; + return TRUE; + } else { + return FALSE; + } + } else if (value->size == strlen("pal-m") && !strncmp("pal-m", s, strlen("pal-m"))) { + if (radeon_output->SupportedTVStds & TV_STD_PAL_M) { + radeon_output->tvStd = TV_STD_PAL_M; + return TRUE; + } else { + return FALSE; + } + } else if (value->size == strlen("pal-60") && !strncmp("pal-60", s, strlen("pal-60"))) { + if (radeon_output->SupportedTVStds & TV_STD_PAL_60) { + radeon_output->tvStd = TV_STD_PAL_60; + return TRUE; + } else { + return FALSE; + } + } else if (value->size == strlen("ntsc-j") && !strncmp("ntsc-j", s, strlen("ntsc-j"))) { + if (radeon_output->SupportedTVStds & TV_STD_NTSC_J) { + radeon_output->tvStd = TV_STD_NTSC_J; + return TRUE; + } else { + return FALSE; + } + } else if (value->size == strlen("scart-pal") && !strncmp("scart-pal", s, strlen("scart-pal"))) { + if (radeon_output->SupportedTVStds & TV_STD_SCART_PAL) { + radeon_output->tvStd = TV_STD_SCART_PAL; + return TRUE; + } else { + return FALSE; + } + } + return FALSE; + } + + return TRUE; +} + +static const xf86OutputFuncsRec radeon_output_funcs = { + .create_resources = radeon_create_resources, + .dpms = radeon_dpms, + .save = radeon_save, + .restore = radeon_restore, + .mode_valid = radeon_mode_valid, + .mode_fixup = radeon_mode_fixup, + .prepare = radeon_mode_prepare, + .mode_set = radeon_mode_set, + .commit = radeon_mode_commit, + .detect = radeon_detect, + .get_modes = radeon_get_modes, + .set_property = radeon_set_property, + .destroy = radeon_destroy +}; + +void RADEONSetOutputType(ScrnInfoPtr pScrn, RADEONOutputPrivatePtr radeon_output) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + RADEONOutputType output; + + if (info->IsAtomBios) { + switch(radeon_output->ConnectorType) { + case CONNECTOR_VGA_ATOM: + output = OUTPUT_VGA; break; + case CONNECTOR_DVI_I_ATOM: + case CONNECTOR_DVI_D_ATOM: + case CONNECTOR_DVI_A_ATOM: + output = OUTPUT_DVI; break; + case CONNECTOR_STV_ATOM: + output = OUTPUT_STV; break; + case CONNECTOR_CTV_ATOM: + output = OUTPUT_CTV; break; + case CONNECTOR_LVDS_ATOM: + case CONNECTOR_DIGITAL_ATOM: + output = OUTPUT_LVDS; break; + case CONNECTOR_NONE_ATOM: + case CONNECTOR_UNSUPPORTED_ATOM: + default: + output = OUTPUT_NONE; break; + } + } + else { + switch(radeon_output->ConnectorType) { + case CONNECTOR_PROPRIETARY: + output = OUTPUT_LVDS; break; + case CONNECTOR_CRT: + output = OUTPUT_VGA; break; + case CONNECTOR_DVI_I: + case CONNECTOR_DVI_D: + output = OUTPUT_DVI; break; + case CONNECTOR_CTV: + output = OUTPUT_CTV; break; + case CONNECTOR_STV: + output = OUTPUT_STV; break; + case CONNECTOR_NONE: + case CONNECTOR_UNSUPPORTED: + default: + output = OUTPUT_NONE; break; + } + } + radeon_output->type = output; +} + +static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long val; + unsigned char *RADEONMMIO = info->MMIO; + + /* Get the result */ + + if (b->DriverPrivate.uval == RADEON_LCD_GPIO_MASK) { + val = INREG(b->DriverPrivate.uval+4); + *Clock = (val & (1<<13)) != 0; + *data = (val & (1<<12)) != 0; + } else { + val = INREG(b->DriverPrivate.uval); + *Clock = (val & RADEON_GPIO_Y_1) != 0; + *data = (val & RADEON_GPIO_Y_0) != 0; + } +} + +static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long val; + unsigned char *RADEONMMIO = info->MMIO; + + if (b->DriverPrivate.uval == RADEON_LCD_GPIO_MASK) { + val = INREG(b->DriverPrivate.uval) & (CARD32)~((1<<12) | (1<<13)); + val |= (Clock ? 0:(1<<13)); + val |= (data ? 0:(1<<12)); + OUTREG(b->DriverPrivate.uval, val); + } else { + val = INREG(b->DriverPrivate.uval) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1); + val |= (Clock ? 0:RADEON_GPIO_EN_1); + val |= (data ? 0:RADEON_GPIO_EN_0); + OUTREG(b->DriverPrivate.uval, val); + } + /* read back to improve reliability on some cards. */ + val = INREG(b->DriverPrivate.uval); +} + +static Bool +RADEONI2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name) +{ + I2CBusPtr pI2CBus; + + pI2CBus = xf86CreateI2CBusRec(); + if (!pI2CBus) return FALSE; + + pI2CBus->BusName = name; + pI2CBus->scrnIndex = pScrn->scrnIndex; + pI2CBus->I2CPutBits = RADEONI2CPutBits; + pI2CBus->I2CGetBits = RADEONI2CGetBits; + pI2CBus->AcknTimeout = 5; + pI2CBus->DriverPrivate.uval = i2c_reg; + + if (!xf86I2CBusInit(pI2CBus)) return FALSE; + + *bus_ptr = pI2CBus; + return TRUE; +} + +static void +RADEONGetPanelInfoFromReg (xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + unsigned char *RADEONMMIO = info->MMIO; + CARD32 fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); + CARD32 fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); + + radeon_output->PanelPwrDly = 200; + if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) { + radeon_output->PanelYRes = ((fp_vert_stretch & RADEON_VERT_PANEL_SIZE) >> + RADEON_VERT_PANEL_SHIFT) + 1; + } else { + radeon_output->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; + } + if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { + radeon_output->PanelXRes = (((fp_horz_stretch & RADEON_HORZ_PANEL_SIZE) >> + RADEON_HORZ_PANEL_SHIFT) + 1) * 8; + } else { + radeon_output->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; + } + + if ((radeon_output->PanelXRes < 640) || (radeon_output->PanelYRes < 480)) { + radeon_output->PanelXRes = 640; + radeon_output->PanelYRes = 480; + } + + // move this to crtc function + if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { + CARD32 ppll_div_sel, ppll_val; + + ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; + RADEONPllErrataAfterIndex(info); + ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); + if ((ppll_val & 0x000707ff) == 0x1bb) + goto noprobe; + info->FeedbackDivider = ppll_val & 0x7ff; + info->PostDivider = (ppll_val >> 16) & 0x7; + info->RefDivider = info->pll.reference_div; + info->UseBiosDividers = TRUE; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Existing panel PLL dividers will be used.\n"); + } + noprobe: + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Panel size %dx%d is derived, this may not be correct.\n" + "If not, use PanelSize option to overwrite this setting\n", + radeon_output->PanelXRes, radeon_output->PanelYRes); +} + +/* BIOS may not have right panel size, we search through all supported + * DDC modes looking for the maximum panel size. + */ +static void +RADEONUpdatePanelSize(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int j; + /* XXX: fixme */ + //xf86MonPtr ddc = pScrn->monitor->DDC; + xf86MonPtr ddc = output->MonInfo; + DisplayModePtr p; + + // crtc should handle? + if ((info->UseBiosDividers && radeon_output->DotClock != 0) || (ddc == NULL)) + return; + + /* Go thru detailed timing table first */ + for (j = 0; j < 4; j++) { + if (ddc->det_mon[j].type == 0) { + struct detailed_timings *d_timings = + &ddc->det_mon[j].section.d_timings; + int match = 0; + + /* If we didn't get a panel clock or guessed one, try to match the + * mode with the panel size. We do that because we _need_ a panel + * clock, or ValidateFPModes will fail, even when UseBiosDividers + * is set. + */ + if (radeon_output->DotClock == 0 && + radeon_output->PanelXRes == d_timings->h_active && + radeon_output->PanelYRes == d_timings->v_active) + match = 1; + + /* If we don't have a BIOS provided panel data with fixed dividers, + * check for a larger panel size + */ + if (radeon_output->PanelXRes < d_timings->h_active && + radeon_output->PanelYRes < d_timings->v_active && + !info->UseBiosDividers) + match = 1; + + if (match) { + radeon_output->PanelXRes = d_timings->h_active; + radeon_output->PanelYRes = d_timings->v_active; + radeon_output->DotClock = d_timings->clock / 1000; + radeon_output->HOverPlus = d_timings->h_sync_off; + radeon_output->HSyncWidth = d_timings->h_sync_width; + radeon_output->HBlank = d_timings->h_blanking; + radeon_output->VOverPlus = d_timings->v_sync_off; + radeon_output->VSyncWidth = d_timings->v_sync_width; + radeon_output->VBlank = d_timings->v_blanking; + radeon_output->Flags = (d_timings->interlaced ? V_INTERLACE : 0); + switch (d_timings->misc) { + case 0: radeon_output->Flags |= V_NHSYNC | V_NVSYNC; break; + case 1: radeon_output->Flags |= V_PHSYNC | V_NVSYNC; break; + case 2: radeon_output->Flags |= V_NHSYNC | V_PVSYNC; break; + case 3: radeon_output->Flags |= V_PHSYNC | V_PVSYNC; break; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC detailed: %dx%d\n", + radeon_output->PanelXRes, radeon_output->PanelYRes); + } + } + } + + if (info->UseBiosDividers && radeon_output->DotClock != 0) + return; + + /* Search thru standard VESA modes from EDID */ + for (j = 0; j < 8; j++) { + if ((radeon_output->PanelXRes < ddc->timings2[j].hsize) && + (radeon_output->PanelYRes < ddc->timings2[j].vsize)) { + for (p = pScrn->monitor->Modes; p; p = p->next) { + if ((ddc->timings2[j].hsize == p->HDisplay) && + (ddc->timings2[j].vsize == p->VDisplay)) { + float refresh = + (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; + + if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) { + /* Is this good enough? */ + radeon_output->PanelXRes = ddc->timings2[j].hsize; + radeon_output->PanelYRes = ddc->timings2[j].vsize; + radeon_output->HBlank = p->HTotal - p->HDisplay; + radeon_output->HOverPlus = p->HSyncStart - p->HDisplay; + radeon_output->HSyncWidth = p->HSyncEnd - p->HSyncStart; + radeon_output->VBlank = p->VTotal - p->VDisplay; + radeon_output->VOverPlus = p->VSyncStart - p->VDisplay; + radeon_output->VSyncWidth = p->VSyncEnd - p->VSyncStart; + radeon_output->DotClock = p->Clock; + radeon_output->Flags = p->Flags; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC VESA/EDID: %dx%d\n", + radeon_output->PanelXRes, radeon_output->PanelYRes); + } + } + } + } + } +} + +static Bool +RADEONGetLVDSInfo (xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + char* s; + + if (!RADEONGetLVDSInfoFromBIOS(output)) + RADEONGetPanelInfoFromReg(output); + + if ((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { + radeon_output->PanelPwrDly = 200; + if (sscanf (s, "%dx%d", &radeon_output->PanelXRes, &radeon_output->PanelYRes) != 2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s); + RADEONGetPanelInfoFromReg(output); + } + } + + /* The panel size we collected from BIOS may not be the + * maximum size supported by the panel. If not, we update + * it now. These will be used if no matching mode can be + * found from EDID data. + */ + RADEONUpdatePanelSize(output); + + if (radeon_output->DotClock == 0) { + DisplayModePtr tmp_mode = NULL; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No valid timing info from BIOS.\n"); + /* No timing information for the native mode, + use whatever specified in the Modeline. + If no Modeline specified, we'll just pick + the VESA mode at 60Hz refresh rate which + is likely to be the best for a flat panel. + */ + tmp_mode = pScrn->monitor->Modes; + while(tmp_mode) { + if ((tmp_mode->HDisplay == radeon_output->PanelXRes) && + (tmp_mode->VDisplay == radeon_output->PanelYRes)) { + + float refresh = + (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; + if ((abs(60.0 - refresh) < 1.0) || + (tmp_mode->type == 0)) { + radeon_output->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; + radeon_output->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; + radeon_output->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; + radeon_output->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; + radeon_output->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; + radeon_output->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; + radeon_output->DotClock = tmp_mode->Clock; + radeon_output->Flags = 0; + break; + } + } + + tmp_mode = tmp_mode->next; + + if (tmp_mode == pScrn->monitor->Modes) + break; + } + if ((radeon_output->DotClock == 0) && !output->MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Panel size is not correctly detected.\n" + "Please try to use PanelSize option for correct settings.\n"); + return FALSE; + } + } + + return TRUE; +} + +static void +RADEONGetTMDSInfoFromTable(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int i; + + for (i=0; i<4; i++) { + radeon_output->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; + radeon_output->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; + } +} + +static void +RADEONGetTMDSInfo(xf86OutputPtr output) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int i; + + for (i=0; i<4; i++) { + radeon_output->tmds_pll[i].value = 0; + radeon_output->tmds_pll[i].freq = 0; + } + + if (RADEONGetTMDSInfoFromBIOS(output)) return; + + RADEONGetTMDSInfoFromTable(output); + +} + +static void +RADEONGetTVInfo(xf86OutputPtr output) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + radeon_output->hPos = 0; + radeon_output->vPos = 0; + radeon_output->hSize = 0; + + if (RADEONGetTVInfoFromBIOS(output)) return; + + /* set some reasonable defaults */ + radeon_output->default_tvStd = TV_STD_NTSC; + radeon_output->tvStd = TV_STD_NTSC; + radeon_output->TVRefClk = 27.000000000; + radeon_output->SupportedTVStds = TV_STD_NTSC | TV_STD_PAL; + +} + +void RADEONInitConnector(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int DDCReg = 0; + char* name = (char*) DDCTypeName[radeon_output->DDCType]; + + switch(radeon_output->DDCType) { + case DDC_MONID: DDCReg = RADEON_GPIO_MONID; break; + case DDC_DVI : DDCReg = RADEON_GPIO_DVI_DDC; break; + case DDC_VGA : DDCReg = RADEON_GPIO_VGA_DDC; break; + case DDC_CRT2 : DDCReg = RADEON_GPIO_CRT2_DDC; break; + case DDC_LCD : DDCReg = RADEON_LCD_GPIO_MASK; break; + default: break; + } + + if (radeon_output->DACType == DAC_PRIMARY) + radeon_output->load_detection = 1; /* primary dac, only drives vga */ + else if (radeon_output->DACType == DAC_TVDAC && + info->tvdac_use_count < 2) + radeon_output->load_detection = 1; /* only one output with tvdac */ + else + radeon_output->load_detection = 0; /* shared tvdac between vga/dvi/tv */ + + if (DDCReg) { + radeon_output->DDCReg = DDCReg; + RADEONI2CInit(pScrn, &radeon_output->pI2CBus, DDCReg, name); + } + + if (radeon_output->type == OUTPUT_LVDS) { + RADEONGetLVDSInfo(output); + } + + if (radeon_output->type == OUTPUT_DVI) { + RADEONGetTMDSInfo(output); + } + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + RADEONGetTVInfo(output); + } + + if (radeon_output->DACType == DAC_TVDAC) { + radeon_output->tv_on = FALSE; + RADEONGetTVDacAdjInfo(output); + } + +} + +static void RADEONSetupGenericConnectors(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (info->IsMobility) { + /* Below is the most common setting, but may not be true */ + if (info->IsIGP) { + info->BiosConnector[0].DDCType = DDC_LCD; + info->BiosConnector[0].DACType = DAC_UNKNOWN; + info->BiosConnector[0].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[0].ConnectorType = CONNECTOR_PROPRIETARY; + info->BiosConnector[0].valid = TRUE; + + /* IGP only has TVDAC */ + if (info->ChipFamily == CHIP_FAMILY_RS400) + info->BiosConnector[1].DDCType = DDC_CRT2; + else + info->BiosConnector[1].DDCType = DDC_VGA; + info->BiosConnector[1].DACType = DAC_TVDAC; + info->BiosConnector[1].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; + info->BiosConnector[1].valid = TRUE; + } else { +#if defined(__powerpc__) + info->BiosConnector[0].DDCType = DDC_DVI; +#else + info->BiosConnector[0].DDCType = DDC_LCD; +#endif + info->BiosConnector[0].DACType = DAC_UNKNOWN; + info->BiosConnector[0].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[0].ConnectorType = CONNECTOR_PROPRIETARY; + info->BiosConnector[0].valid = TRUE; + + info->BiosConnector[1].DDCType = DDC_VGA; + info->BiosConnector[1].DACType = DAC_PRIMARY; + info->BiosConnector[1].TMDSType = TMDS_EXT; + info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; + info->BiosConnector[1].valid = TRUE; + } + } else { + /* Below is the most common setting, but may not be true */ + if (info->IsIGP) { + if (info->ChipFamily == CHIP_FAMILY_RS400) + info->BiosConnector[0].DDCType = DDC_CRT2; + else + info->BiosConnector[0].DDCType = DDC_VGA; + info->BiosConnector[0].DACType = DAC_TVDAC; + info->BiosConnector[0].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[0].ConnectorType = CONNECTOR_CRT; + info->BiosConnector[0].valid = TRUE; + + /* not sure what a good default DDCType for DVI on + * IGP desktop chips is + */ + info->BiosConnector[1].DDCType = DDC_MONID; /* DDC_DVI? */ + info->BiosConnector[1].DACType = DAC_UNKNOWN; + info->BiosConnector[1].TMDSType = TMDS_EXT; + info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_D; + info->BiosConnector[1].valid = TRUE; + } else { + info->BiosConnector[0].DDCType = DDC_DVI; + info->BiosConnector[0].DACType = DAC_TVDAC; + info->BiosConnector[0].TMDSType = TMDS_INT; + info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I; + info->BiosConnector[0].valid = TRUE; + + info->BiosConnector[1].DDCType = DDC_VGA; + info->BiosConnector[1].DACType = DAC_PRIMARY; + info->BiosConnector[1].TMDSType = TMDS_EXT; + info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; + info->BiosConnector[1].valid = TRUE; + } + } + + if (info->InternalTVOut) { + info->BiosConnector[2].ConnectorType = CONNECTOR_STV; + info->BiosConnector[2].DACType = DAC_TVDAC; + info->BiosConnector[2].TMDSType = TMDS_NONE; + info->BiosConnector[2].DDCType = DDC_NONE_DETECTED; + info->BiosConnector[2].valid = TRUE; + } + + /* Some cards have the DDC lines swapped and we have no way to + * detect it yet (Mac cards) + */ + if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) { + info->BiosConnector[0].DDCType = DDC_VGA; + info->BiosConnector[1].DDCType = DDC_DVI; + } + +} + +/* + * initialise the static data sos we don't have to re-do at randr change */ +Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + xf86OutputPtr output; + char *optstr; + int i = 0; + int num_vga = 0; + int num_dvi = 0; + + /* We first get the information about all connectors from BIOS. + * This is how the card is phyiscally wired up. + * The information should be correct even on a OEM card. + */ + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + info->BiosConnector[i].valid = FALSE; + info->BiosConnector[i].DDCType = DDC_NONE_DETECTED; + info->BiosConnector[i].DACType = DAC_UNKNOWN; + info->BiosConnector[i].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[i].ConnectorType = CONNECTOR_NONE; + } + + if (xf86ReturnOptValBool(info->Options, OPTION_DEFAULT_CONNECTOR_TABLE, FALSE)) { + RADEONSetupGenericConnectors(pScrn); + } else { + if (!RADEONGetConnectorInfoFromBIOS(pScrn)) + RADEONSetupGenericConnectors(pScrn); + } + + if (info->HasSingleDAC) { + /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/ + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].ConnectorType == CONNECTOR_CRT) + info->BiosConnector[i].DACType = DAC_TVDAC; + } + } else if (!pRADEONEnt->HasCRTC2) { + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].ConnectorType == CONNECTOR_CRT) + info->BiosConnector[i].DACType = DAC_PRIMARY; + } + } + + /* parse connector table option */ + optstr = (char *)xf86GetOptValString(info->Options, OPTION_CONNECTORTABLE); + + if (optstr) { + for (i = 2; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + info->BiosConnector[i].valid = FALSE; + } + info->BiosConnector[0].valid = TRUE; + info->BiosConnector[1].valid = TRUE; + if (sscanf(optstr, "%u,%d,%d,%u,%u,%d,%d,%u", + &info->BiosConnector[0].DDCType, + &info->BiosConnector[0].DACType, + &info->BiosConnector[0].TMDSType, + &info->BiosConnector[0].ConnectorType, + &info->BiosConnector[1].DDCType, + &info->BiosConnector[1].DACType, + &info->BiosConnector[1].TMDSType, + &info->BiosConnector[1].ConnectorType) != 8) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid ConnectorTable option: %s\n", optstr); + return FALSE; + } + } + + info->tvdac_use_count = 0; + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].valid) { + if (info->BiosConnector[i].DACType == DAC_TVDAC) + info->tvdac_use_count++; + + if (info->IsAtomBios) { + if ((info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D_ATOM) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I_ATOM) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_A_ATOM)) { + num_dvi++; + } else if (info->BiosConnector[i].ConnectorType == CONNECTOR_VGA_ATOM) { + num_vga++; + } + } else { + if ((info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I)) { + num_dvi++; + } else if (info->BiosConnector[i].ConnectorType == CONNECTOR_CRT) { + num_vga++; + } + } + } + } + + for (i = 0 ; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].valid) { + RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); + if (!radeon_output) { + return FALSE; + } + radeon_output->MonType = MT_UNKNOWN; + radeon_output->ConnectorType = info->BiosConnector[i].ConnectorType; + radeon_output->DDCType = info->BiosConnector[i].DDCType; + if (info->IsAtomBios) { + if (radeon_output->ConnectorType == CONNECTOR_DVI_D_ATOM) + radeon_output->DACType = DAC_NONE; + else + radeon_output->DACType = info->BiosConnector[i].DACType; + + if (radeon_output->ConnectorType == CONNECTOR_VGA_ATOM) + radeon_output->TMDSType = TMDS_NONE; + else + radeon_output->TMDSType = info->BiosConnector[i].TMDSType; + } else { + if (radeon_output->ConnectorType == CONNECTOR_DVI_D) + radeon_output->DACType = DAC_NONE; + else + radeon_output->DACType = info->BiosConnector[i].DACType; + + if (radeon_output->ConnectorType == CONNECTOR_CRT) + radeon_output->TMDSType = TMDS_NONE; + else + radeon_output->TMDSType = info->BiosConnector[i].TMDSType; + } + RADEONSetOutputType(pScrn, radeon_output); + if (info->IsAtomBios) { + if ((info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D_ATOM) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I_ATOM) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_A_ATOM)) { + if (num_dvi > 1) { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "DVI-1"); + num_dvi--; + } else { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "DVI-0"); + } + } else if (info->BiosConnector[i].ConnectorType == CONNECTOR_VGA_ATOM) { + if (num_vga > 1) { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "VGA-1"); + num_vga--; + } else { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "VGA-0"); + } + } else + output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); + } else { + if ((info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I)) { + if (num_dvi > 1) { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "DVI-1"); + num_dvi--; + } else { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "DVI-0"); + } + } else if (info->BiosConnector[i].ConnectorType == CONNECTOR_CRT) { + if (num_vga > 1) { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "VGA-1"); + num_vga--; + } else { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "VGA-0"); + } + } else + output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); + } + + if (!output) { + return FALSE; + } + output->driver_private = radeon_output; + output->possible_crtcs = 1; + /* crtc2 can drive LVDS, it just doesn't have RMX */ + if (radeon_output->type != OUTPUT_LVDS) + output->possible_crtcs |= 2; + + /* we can clone the DACs, and probably TV-out, + but I'm not sure it's worth the trouble */ + output->possible_clones = 0; + + RADEONInitConnector(output); + } + } + + return TRUE; +} + diff --git a/src/radeon_probe.c b/src/radeon_probe.c index 98b35aa6..c697f65c 100644 --- a/src/radeon_probe.c +++ b/src/radeon_probe.c @@ -40,7 +40,6 @@ * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge. */ -#include "atimodule.h" #include "ativersion.h" #include "radeon_probe.h" @@ -200,7 +199,7 @@ PciChipsets RADEONPciChipsets[] = { int gRADEONEntityIndex = -1; /* Return the options for supported chipset 'n'; NULL otherwise */ -const OptionInfoRec * +_X_EXPORT const OptionInfoRec * RADEONAvailableOptions(int chipid, int busid) { int i; @@ -219,7 +218,7 @@ RADEONAvailableOptions(int chipid, int busid) } /* Return the string name for supported chipset 'n'; NULL otherwise. */ -void +_X_EXPORT void RADEONIdentify(int flags) { xf86PrintChipsets(RADEON_NAME, @@ -228,7 +227,7 @@ RADEONIdentify(int flags) } /* Return TRUE if chipset is present; FALSE otherwise. */ -Bool +_X_EXPORT Bool RADEONProbe(DriverPtr drv, int flags) { int numUsed; @@ -285,22 +284,26 @@ RADEONProbe(DriverPtr drv, int flags) if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], RADEONPciChipsets, 0, 0, 0, 0, 0))) { -#ifdef XFree86LOADER - if (!xf86LoadSubModule(pScrn, "radeon")) { - xf86Msg(X_ERROR, RADEON_NAME - ": Failed to load \"radeon\" module.\n"); - xf86DeleteScreen(pScrn->scrnIndex, 0); - continue; - } - - xf86LoaderReqSymLists(RADEONSymbols, NULL); + pScrn->driverVersion = RADEON_VERSION_CURRENT; + pScrn->driverName = RADEON_DRIVER_NAME; + pScrn->name = RADEON_NAME; + pScrn->Probe = RADEONProbe; + pScrn->PreInit = RADEONPreInit; + pScrn->ScreenInit = RADEONScreenInit; + pScrn->SwitchMode = RADEONSwitchMode; +#ifdef X_XF86MiscPassMessage + pScrn->HandleMessage = RADEONHandleMessage; #endif + pScrn->AdjustFrame = RADEONAdjustFrame; + pScrn->EnterVT = RADEONEnterVT; + pScrn->LeaveVT = RADEONLeaveVT; + pScrn->FreeScreen = RADEONFreeScreen; + pScrn->ValidMode = RADEONValidMode; - pScrn->Probe = RADEONProbe; - RADEONFillInScreenInfo(pScrn); foundScreen = TRUE; } + xfree(pEnt); pEnt = xf86GetEntityInfo(usedChips[i]); /* create a RADEONEntity for all chips, even with diff --git a/src/radeon_probe.h b/src/radeon_probe.h index b651e7d0..b6ef59dd 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -38,17 +38,28 @@ #include "xf86str.h" #include "xf86DDC.h" +#include "randrstr.h" #define _XF86MISC_SERVER_ #include <X11/extensions/xf86misc.h> +#include "xf86Crtc.h" + +#ifdef USE_EXA +#include "exa.h" +#endif +#ifdef USE_XAA +#include "xaa.h" +#endif + typedef enum { DDC_NONE_DETECTED, DDC_MONID, DDC_DVI, DDC_VGA, - DDC_CRT2 + DDC_CRT2, + DDC_LCD, } RADEONDDCType; typedef enum @@ -92,41 +103,120 @@ typedef enum { DAC_UNKNOWN = -1, DAC_PRIMARY = 0, - DAC_TVDAC = 1 + DAC_TVDAC = 1, + DAC_NONE = 2 } RADEONDacType; typedef enum { TMDS_UNKNOWN = -1, TMDS_INT = 0, - TMDS_EXT = 1 + TMDS_EXT = 1, + TMDS_NONE = 2 } RADEONTmdsType; -typedef struct +typedef enum { - Bool IsUsed; - Bool IsActive; - int binding; // which instance of the driver "owns" this controller - DisplayModePtr pCurMode; -} RADEONController; + DVI_AUTO, + DVI_DIGITAL, + DVI_ANALOG +} RADEONDviType; -typedef struct +typedef enum +{ + TMDS_PLL_BIOS, + TMDS_PLL_DRIVER +} RADEONTMDSPllType; + +typedef struct { + CARD32 freq; + CARD32 value; +}RADEONTMDSPll; + +typedef enum +{ + OUTPUT_NONE, + OUTPUT_VGA, + OUTPUT_DVI, + OUTPUT_LVDS, + OUTPUT_STV, + OUTPUT_CTV, +} RADEONOutputType; + +/* standards */ +typedef enum { + TV_STD_NTSC = 1, + TV_STD_PAL = 2, + TV_STD_PAL_M = 4, + TV_STD_PAL_60 = 8, + TV_STD_NTSC_J = 16, + TV_STD_SCART_PAL = 32, +} TVStd; + +typedef struct _RADEONCrtcPrivateRec { +#ifdef USE_XAA + FBLinearPtr rotate_mem_xaa; +#endif +#ifdef USE_EXA + ExaOffscreenArea *rotate_mem_exa; +#endif + int crtc_id; + int binding; + /* Lookup table values to be set when the CRTC is enabled */ + CARD8 lut_r[256], lut_g[256], lut_b[256]; +} RADEONCrtcPrivateRec, *RADEONCrtcPrivatePtr; + +typedef struct { RADEONDDCType DDCType; RADEONDacType DACType; RADEONTmdsType TMDSType; RADEONConnectorType ConnectorType; - RADEONMonitorType MonType; - xf86MonPtr MonInfo; + Bool valid; +} RADEONBIOSConnector; - /* one connector can be bound to one CRTC */ +typedef struct _RADEONOutputPrivateRec { + int num; + RADEONOutputType type; + void *dev_priv; + RADEONDDCType DDCType; + RADEONDacType DACType; + RADEONDviType DVIType; + RADEONTmdsType TMDSType; + RADEONConnectorType ConnectorType; + RADEONMonitorType MonType; int crtc_num; -} RADEONConnector; - - + int DDCReg; + I2CBusPtr pI2CBus; + CARD32 tv_dac_adj; + /* panel stuff */ + int PanelXRes; + int PanelYRes; + int HOverPlus; + int HSyncWidth; + int HBlank; + int VOverPlus; + int VSyncWidth; + int VBlank; + int Flags; /* Saved copy of mode flags */ + int PanelPwrDly; + int DotClock; + RADEONTMDSPll tmds_pll[4]; + RADEONTMDSPllType tmds_pll_table; + /* TV out */ + TVStd default_tvStd; + TVStd tvStd; + int hPos; + int vPos; + int hSize; + float TVRefClk; + int SupportedTVStds; + Bool tv_on; + int load_detection; +} RADEONOutputPrivateRec, *RADEONOutputPrivatePtr; -#define RADEON_MAX_CONNECTOR 2 #define RADEON_MAX_CRTC 2 +#define RADEON_MAX_BIOS_CONNECTOR 8 typedef struct { @@ -139,13 +229,11 @@ typedef struct Bool IsSecondaryRestored; Bool RestorePrimary; - ScrnInfoPtr pSecondaryScrn; - ScrnInfoPtr pPrimaryScrn; - Bool ReversedDAC; /* TVDAC used as primary dac */ Bool ReversedTMDS; /* DDC_DVI is used for external TMDS */ - RADEONConnector *PortInfo[RADEON_MAX_CONNECTOR]; - RADEONController *Controller[RADEON_MAX_CRTC]; /* pointer to a controller */ + xf86CrtcPtr pCrtc[RADEON_MAX_CRTC]; + RADEONCrtcPrivatePtr Controller[RADEON_MAX_CRTC]; + } RADEONEntRec, *RADEONEntPtr; /* radeon_probe.c */ @@ -172,6 +260,4 @@ extern ModeStatus RADEONValidMode(int, DisplayModePtr, Bool, int); extern const OptionInfoRec *RADEONOptionsWeak(void); -extern void RADEONFillInScreenInfo(ScrnInfoPtr); - #endif /* _RADEON_PROBE_H_ */ diff --git a/src/radeon_reg.h b/src/radeon_reg.h index b50fcf0a..af62a692 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -231,7 +231,13 @@ # define RADEON_ACTIVE_HILO_LAT_MASK (3 << 13) # define RADEON_ACTIVE_HILO_LAT_SHIFT 13 # define RADEON_DISP_DYN_STOP_LAT_MASK (1 << 12) +# define RADEON_MC_BUSY (1 << 16) +# define RADEON_DLL_READY (1 << 19) +# define RADEON_CG_NO1_DEBUG_0 (1 << 24) +# define RADEON_CG_NO1_DEBUG_MASK (0x1f << 24) # define RADEON_DYN_STOP_MODE_MASK (7 << 21) +# define RADEON_TVPLL_PWRMGT_OFF (1 << 30) +# define RADEON_TVCLK_TURNOFF (1 << 31) #define RADEON_PLL_PWRMGT_CNTL 0x0015 # define RADEON_TCL_BYPASS_DISABLE (1 << 20) #define RADEON_CLR_CMP_CLR_3D 0x1a24 @@ -308,7 +314,7 @@ # define RADEON_CRTC_CSYNC_EN (1 << 4) # define RADEON_CRTC_ICON_EN (1 << 15) # define RADEON_CRTC_CUR_EN (1 << 16) -# define RADEON_CRTC_CUR_MODE_MASK (7 << 17) +# define RADEON_CRTC_CUR_MODE_MASK (7 << 20) # define RADEON_CRTC_EXT_DISP_EN (1 << 24) # define RADEON_CRTC_EN (1 << 25) # define RADEON_CRTC_DISP_REQ_EN_B (1 << 26) @@ -319,6 +325,8 @@ # define RADEON_CRTC2_HSYNC_TRISTAT (1 << 5) # define RADEON_CRTC2_VSYNC_TRISTAT (1 << 6) # define RADEON_CRTC2_CRT2_ON (1 << 7) +# define RADEON_CRTC2_PIX_WIDTH_SHIFT 8 +# define RADEON_CRTC2_PIX_WIDTH_MASK (0xf << 8) # define RADEON_CRTC2_ICON_EN (1 << 15) # define RADEON_CRTC2_CUR_EN (1 << 16) # define RADEON_CRTC2_CUR_MODE_MASK (7 << 20) @@ -329,8 +337,8 @@ # define RADEON_CRTC2_HSYNC_DIS (1 << 28) # define RADEON_CRTC2_VSYNC_DIS (1 << 29) #define RADEON_CRTC_MORE_CNTL 0x27c -# define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4) -# define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5) +# define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4) +# define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5) #define RADEON_CRTC_GUI_TRIG_VLINE 0x0218 #define RADEON_CRTC_H_SYNC_STRT_WID 0x0204 # define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0) @@ -451,6 +459,7 @@ #define RADEON_DAC_CNTL 0x0058 # define RADEON_DAC_RANGE_CNTL (3 << 0) +# define RADEON_DAC_RANGE_CNTL_PS2 (2 << 0) # define RADEON_DAC_RANGE_CNTL_MASK 0x03 # define RADEON_DAC_BLANKING (1 << 2) # define RADEON_DAC_CMP_EN (1 << 3) @@ -461,13 +470,25 @@ # define RADEON_DAC_PDWN (1 << 15) # define RADEON_DAC_MASK_ALL (0xff << 24) #define RADEON_DAC_CNTL2 0x007c +# define RADEON_DAC2_TV_CLK_SEL (0 << 1) # define RADEON_DAC2_DAC_CLK_SEL (1 << 0) # define RADEON_DAC2_DAC2_CLK_SEL (1 << 1) # define RADEON_DAC2_PALETTE_ACC_CTL (1 << 5) +# define RADEON_DAC2_CMP_EN (1 << 7) +# define RADEON_DAC2_CMP_OUT_R (1 << 8) +# define RADEON_DAC2_CMP_OUT_G (1 << 9) +# define RADEON_DAC2_CMP_OUT_B (1 << 10) +# define RADEON_DAC2_CMP_OUTPUT (1 << 11) #define RADEON_DAC_EXT_CNTL 0x0280 -# define RADEON_DAC_FORCE_BLANK_OFF_EN (1 << 4) -# define RADEON_DAC_FORCE_DATA_EN (1 << 5) +# define RADEON_DAC2_FORCE_BLANK_OFF_EN (1 << 0) +# define RADEON_DAC2_FORCE_DATA_EN (1 << 1) +# define RADEON_DAC_FORCE_BLANK_OFF_EN (1 << 4) +# define RADEON_DAC_FORCE_DATA_EN (1 << 5) # define RADEON_DAC_FORCE_DATA_SEL_MASK (3 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_R (0 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_G (1 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_B (2 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_RGB (3 << 6) # define RADEON_DAC_FORCE_DATA_MASK 0x0003ff00 # define RADEON_DAC_FORCE_DATA_SHIFT 8 #define RADEON_DAC_MACRO_CNTL 0x0d04 @@ -480,15 +501,22 @@ # define RADEON_TV_DAC_PEDESTAL (1 << 2) # define RADEON_TV_MONITOR_DETECT_EN (1 << 4) # define RADEON_TV_DAC_CMPOUT (1 << 5) +# define RADEON_TV_DAC_STD_MASK (3 << 8) +# define RADEON_TV_DAC_STD_PAL (0 << 8) # define RADEON_TV_DAC_STD_NTSC (1 << 8) -# define RADEON_TV_DAC_STD_MASK 0x0300 -# define RADEON_TV_DAC_STD_PS2 0x0200 +# define RADEON_TV_DAC_STD_PS2 (2 << 8) +# define RADEON_TV_DAC_STD_RS343 (3 << 8) # define RADEON_TV_DAC_BGSLEEP (1 << 6) # define RADEON_TV_DAC_BGADJ_MASK (0xf << 16) +# define RADEON_TV_DAC_BGADJ_SHIFT 16 # define RADEON_TV_DAC_DACADJ_MASK (0xf << 20) +# define RADEON_TV_DAC_DACADJ_SHIFT 20 # define RADEON_TV_DAC_RDACPD (1 << 24) # define RADEON_TV_DAC_GDACPD (1 << 25) # define RADEON_TV_DAC_BDACPD (1 << 26) +# define RADEON_TV_DAC_RDACDET (1 << 29) +# define RADEON_TV_DAC_GDACDET (1 << 30) +# define RADEON_TV_DAC_BDACDET (1 << 31) # define R420_TV_DAC_DACADJ_MASK (0x1f << 20) # define R420_TV_DAC_RDACPD (1 << 25) # define R420_TV_DAC_GDACPD (1 << 26) @@ -500,10 +528,18 @@ # define RADEON_DISP_DAC_SOURCE_MASK 0x03 # define RADEON_DISP_DAC2_SOURCE_MASK 0x0c # define RADEON_DISP_DAC_SOURCE_CRTC2 0x01 +# define RADEON_DISP_DAC_SOURCE_RMX 0x02 +# define RADEON_DISP_DAC_SOURCE_LTU 0x03 # define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04 -# define RADEON_DISP_TVDAC_SOURCE_MASK (0x03<<2) +# define RADEON_DISP_TVDAC_SOURCE_MASK (0x03 << 2) # define RADEON_DISP_TVDAC_SOURCE_CRTC 0x0 -# define RADEON_DISP_TVDAC_SOURCE_CRTC2 (0x01<<2) +# define RADEON_DISP_TVDAC_SOURCE_CRTC2 (0x01 << 2) +# define RADEON_DISP_TVDAC_SOURCE_RMX (0x02 << 2) +# define RADEON_DISP_TVDAC_SOURCE_LTU (0x03 << 2) +# define RADEON_DISP_TRANS_MATRIX_MASK (0x03 << 4) +# define RADEON_DISP_TRANS_MATRIX_ALPHA_MSB (0x00 << 4) +# define RADEON_DISP_TRANS_MATRIX_GRAPHICS (0x01 << 4) +# define RADEON_DISP_TRANS_MATRIX_VIDEO (0x02 << 4) # define RADEON_DISP_TV_SOURCE_CRTC (1 << 16) /* crtc1 or crtc2 */ # define RADEON_DISP_TV_SOURCE_LTU (0 << 16) /* linear transform unit */ #define RADEON_DISP_TV_OUT_CNTL 0x0d6c @@ -531,12 +567,12 @@ # define RADEON_DISP_ALPHA_MODE_KEY 0 # define RADEON_DISP_ALPHA_MODE_PER_PIXEL 1 # define RADEON_DISP_ALPHA_MODE_GLOBAL 2 -# define RADEON_DISP_RGB_OFFSET_EN (1<<8) +# define RADEON_DISP_RGB_OFFSET_EN (1 << 8) # define RADEON_DISP_GRPH_ALPHA_MASK (0xff << 16) # define RADEON_DISP_OV0_ALPHA_MASK (0xff << 24) # define RADEON_DISP_LIN_TRANS_BYPASS (0x01 << 9) #define RADEON_DISP2_MERGE_CNTL 0x0d68 -# define RADEON_DISP2_RGB_OFFSET_EN (1<<8) +# define RADEON_DISP2_RGB_OFFSET_EN (1 << 8) #define RADEON_DISP_LIN_TRANS_GRPH_A 0x0d80 #define RADEON_DISP_LIN_TRANS_GRPH_B 0x0d84 #define RADEON_DISP_LIN_TRANS_GRPH_C 0x0d88 @@ -742,10 +778,12 @@ # define RADEON_FP2_BLANK_EN (1 << 1) # define RADEON_FP2_ON (1 << 2) # define RADEON_FP2_PANEL_FORMAT (1 << 3) +# define RADEON_FP2_DETECT_SENSE (1 << 8) # define R200_FP2_SOURCE_SEL_MASK (3 << 10) # define R200_FP2_SOURCE_SEL_CRTC1 (0 << 10) # define R200_FP2_SOURCE_SEL_CRTC2 (1 << 10) # define R200_FP2_SOURCE_SEL_RMX (2 << 10) +# define R200_FP2_SOURCE_SEL_TRANS_UNIT (3 << 10) # define RADEON_FP2_SRC_SEL_MASK (3 << 13) # define RADEON_FP2_SRC_SEL_CRTC2 (1 << 13) # define RADEON_FP2_FP_POL (1 << 16) @@ -757,6 +795,7 @@ # define RADEON_FP2_CRC_READ_EN (1 << 24) # define RADEON_FP2_DVO_EN (1 << 25) # define RADEON_FP2_DVO_RATE_SEL_SDR (1 << 26) +# define R200_FP2_DVO_RATE_SEL_SDR (1 << 27) #define RADEON_FP_H_SYNC_STRT_WID 0x02c4 #define RADEON_FP_H2_SYNC_STRT_WID 0x03c4 #define RADEON_FP_HORZ_STRETCH 0x028c @@ -837,6 +876,7 @@ # define RADEON_HDP_SOFT_RESET (1 << 26) # define RADEON_HDP_APER_CNTL (1 << 23) #define RADEON_HTOTAL_CNTL 0x0009 /* PLL */ +# define RADEON_HTOT_CNTL_VGA_EN (1 << 28) #define RADEON_HTOTAL2_CNTL 0x002e /* PLL */ /* Multimedia I2C bus */ @@ -875,6 +915,9 @@ # define RADEON_LVDS_PANEL_TYPE (1 << 2) # define RADEON_LVDS_PANEL_FORMAT (1 << 3) # define RADEON_LVDS_EN (1 << 7) +# define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8 +# define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8) +# define RADEON_LVDS_BL_MOD_EN (1 << 16) # define RADEON_LVDS_DIGON (1 << 18) # define RADEON_LVDS_BLON (1 << 19) # define RADEON_LVDS_SEL_CRTC2 (1 << 23) @@ -885,9 +928,6 @@ #define RADEON_MAX_LATENCY 0x0f3f /* PCI */ #define RADEON_MC_AGP_LOCATION 0x014c #define RADEON_MC_FB_LOCATION 0x0148 -#define RADEON_MC_STATUS 0x0150 -# define RADEON_MC_IDLE (1 << 2) -# define R300_MC_IDLE (1 << 4) #define RADEON_DISPLAY_BASE_ADDR 0x23c #define RADEON_DISPLAY2_BASE_ADDR 0x33c #define RADEON_OV0_BASE_ADDR 0x43c @@ -903,27 +943,41 @@ # define R300_DISABLE_MC_MCLKA (1 << 21) # define R300_DISABLE_MC_MCLKB (1 << 21) #define RADEON_MCLK_MISC 0x001f /* PLL */ -# define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1<<12) -# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1<<13) +# define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1 << 12) +# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13) # define RADEON_MC_MCLK_DYN_ENABLE (1 << 14) # define RADEON_IO_MCLK_DYN_ENABLE (1 << 15) +#define RADEON_LCD_GPIO_MASK 0x01a0 +#define RADEON_LCD_GPIO_Y_REG 0x01a4 #define RADEON_MDGPIO_A_REG 0x01ac #define RADEON_MDGPIO_EN_REG 0x01b0 #define RADEON_MDGPIO_MASK 0x0198 +#define RADEON_GPIOPAD_A 0x019c #define RADEON_MDGPIO_Y_REG 0x01b4 #define RADEON_MEM_ADDR_CONFIG 0x0148 #define RADEON_MEM_BASE 0x0f10 /* PCI */ #define RADEON_MEM_CNTL 0x0140 # define RADEON_MEM_NUM_CHANNELS_MASK 0x01 -# define RADEON_MEM_USE_B_CH_ONLY (1<<1) -# define RV100_HALF_MODE (1<<3) +# define RADEON_MEM_USE_B_CH_ONLY (1 << 1) +# define RV100_HALF_MODE (1 << 3) # define R300_MEM_NUM_CHANNELS_MASK 0x03 -# define R300_MEM_USE_CD_CH_ONLY (1<<2) +# define R300_MEM_USE_CD_CH_ONLY (1 << 2) #define RADEON_MEM_TIMING_CNTL 0x0144 /* EXT_MEM_CNTL */ #define RADEON_MEM_INIT_LAT_TIMER 0x0154 #define RADEON_MEM_INTF_CNTL 0x014c #define RADEON_MEM_SDRAM_MODE_REG 0x0158 +# define RADEON_SDRAM_MODE_MASK 0xffff0000 +# define RADEON_B3MEM_RESET_MASK 0x6fffffff #define RADEON_MEM_STR_CNTL 0x0150 +# define RADEON_MEM_PWRUP_COMPL_A (1 << 0) +# define RADEON_MEM_PWRUP_COMPL_B (1 << 1) +# define R300_MEM_PWRUP_COMPL_C (1 << 2) +# define R300_MEM_PWRUP_COMPL_D (1 << 3) +# define RADEON_MEM_PWRUP_COMPLETE 0x03 +# define R300_MEM_PWRUP_COMPLETE 0x0f +#define RADEON_MC_STATUS 0x0150 +# define RADEON_MC_IDLE (1 << 2) +# define R300_MC_IDLE (1 << 4) #define RADEON_MEM_VGA_RP_SEL 0x003c #define RADEON_MEM_VGA_WP_SEL 0x0038 #define RADEON_MIN_GRANT 0x0f3e /* PCI */ @@ -1040,6 +1094,7 @@ # define RADEON_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L # define RADEON_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L # define RADEON_REG_LD_CTL_LOCK_READBACK 0x00000008L +# define RADEON_REG_LD_CTL_FLIP_READBACK 0x00000010L #define RADEON_OV0_SCALE_CNTL 0x0420 # define RADEON_SCALER_HORZ_PICK_NEAREST 0x00000004L # define RADEON_SCALER_VERT_PICK_NEAREST 0x00000008L @@ -1205,6 +1260,8 @@ #define RADEON_P2PLL_CNTL 0x002a /* P2PLL */ # define RADEON_P2PLL_RESET (1 << 0) # define RADEON_P2PLL_SLEEP (1 << 1) +# define RADEON_P2PLL_PVG_MASK (7 << 11) +# define RADEON_P2PLL_PVG_SHIFT 11 # define RADEON_P2PLL_ATOMIC_UPDATE_EN (1 << 16) # define RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN (1 << 17) # define RADEON_P2PLL_ATOMIC_UPDATE_VSYNC (1 << 18) @@ -1245,6 +1302,7 @@ # define R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF (1 << 23) #define RADEON_PLANE_3D_MASK_C 0x1d44 #define RADEON_PLL_TEST_CNTL 0x0013 /* PLL */ +# define RADEON_PLL_MASK_READ_B (1 << 9) #define RADEON_PMI_CAP_ID 0x0f5c /* PCI */ #define RADEON_PMI_DATA 0x0f63 /* PCI */ #define RADEON_PMI_NXT_CAP_PTR 0x0f5d /* PCI */ @@ -1254,6 +1312,8 @@ #define RADEON_PPLL_CNTL 0x0002 /* PLL */ # define RADEON_PPLL_RESET (1 << 0) # define RADEON_PPLL_SLEEP (1 << 1) +# define RADEON_PPLL_PVG_MASK (7 << 11) +# define RADEON_PPLL_PVG_SHIFT 11 # define RADEON_PPLL_ATOMIC_UPDATE_EN (1 << 16) # define RADEON_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17) # define RADEON_PPLL_ATOMIC_UPDATE_VSYNC (1 << 18) @@ -3056,9 +3116,15 @@ # define RADEON_TV_ASYNC_RST (1 << 0) # define RADEON_CRT_ASYNC_RST (1 << 1) # define RADEON_RESTART_PHASE_FIX (1 << 3) +# define RADEON_TV_FIFO_ASYNC_RST (1 << 4) +# define RADEON_VIN_ASYNC_RST (1 << 5) +# define RADEON_AUD_ASYNC_RST (1 << 6) +# define RADEON_DVS_ASYNC_RST (1 << 7) # define RADEON_CRT_FIFO_CE_EN (1 << 9) # define RADEON_TV_FIFO_CE_EN (1 << 10) +# define RADEON_RE_SYNC_NOW_SEL_MASK (3 << 14) # define RADEON_TVCLK_ALWAYS_ONb (1 << 30) +# define RADEON_TV_ON (1 << 31) #define RADEON_TV_PRE_DAC_MUX_CNTL 0x0888 # define RADEON_Y_RED_EN (1 << 0) # define RADEON_C_GRN_EN (1 << 1) @@ -3076,7 +3142,16 @@ # define RADEON_RGB_SRC_SEL_RMX (1 << 8) # define RADEON_RGB_SRC_SEL_CRTC2 (2 << 8) # define RADEON_RGB_CONVERT_BY_PASS (1 << 10) +# define RADEON_UVRAM_READ_MARGIN_SHIFT 16 +# define RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT 20 +# define RADEON_TVOUT_SCALE_EN (1 << 26) #define RADEON_TV_SYNC_CNTL 0x0808 +# define RADEON_SYNC_OE (1 << 0) +# define RADEON_SYNC_OUT (1 << 1) +# define RADEON_SYNC_IN (1 << 2) +# define RADEON_SYNC_PUB (1 << 3) +# define RADEON_SYNC_PD (1 << 4) +# define RADEON_TV_SYNC_IO_DRIVE (1 << 5) #define RADEON_TV_HTOTAL 0x080c #define RADEON_TV_HDISP 0x0810 #define RADEON_TV_HSTART 0x0818 @@ -3092,10 +3167,23 @@ #define RADEON_TV_HOST_READ_DATA 0x0840 #define RADEON_TV_HOST_WRITE_DATA 0x0844 #define RADEON_TV_HOST_RD_WT_CNTL 0x0848 +# define RADEON_HOST_FIFO_RD (1 << 12) +# define RADEON_HOST_FIFO_RD_ACK (1 << 13) +# define RADEON_HOST_FIFO_WT (1 << 14) +# define RADEON_HOST_FIFO_WT_ACK (1 << 15) #define RADEON_TV_VSCALER_CNTL1 0x084c +# define RADEON_UV_INC_MASK 0xffff +# define RADEON_UV_INC_SHIFT 0 +# define RADEON_Y_W_EN (1 << 24) # define RADEON_RESTART_FIELD (1 << 29) /* restart on field 0 */ # define RADEON_Y_DEL_W_SIG_SHIFT 26 #define RADEON_TV_TIMING_CNTL 0x0850 +# define RADEON_H_INC_MASK 0xfff +# define RADEON_H_INC_SHIFT 0 +# define RADEON_REQ_Y_FIRST (1 << 19) +# define RADEON_FORCE_BURST_ALWAYS (1 << 21) +# define RADEON_UV_POST_SCALE_BYPASS (1 << 23) +# define RADEON_UV_OUTPUT_POST_SCALE_SHIFT 24 #define RADEON_TV_VSCALER_CNTL2 0x0854 # define RADEON_DITHER_MODE (1 << 0) # define RADEON_Y_OUTPUT_DITHER_EN (1 << 1) @@ -3103,25 +3191,75 @@ # define RADEON_UV_TO_BUF_DITHER_EN (1 << 3) #define RADEON_TV_Y_FALL_CNTL 0x0858 # define RADEON_Y_FALL_PING_PONG (1 << 16) +# define RADEON_Y_COEF_EN (1 << 17) #define RADEON_TV_Y_RISE_CNTL 0x085c # define RADEON_Y_RISE_PING_PONG (1 << 16) #define RADEON_TV_Y_SAW_TOOTH_CNTL 0x0860 #define RADEON_TV_UPSAMP_AND_GAIN_CNTL 0x0864 +# define RADEON_YUPSAMP_EN (1 << 0) +# define RADEON_UVUPSAMP_EN (1 << 2) #define RADEON_TV_GAIN_LIMIT_SETTINGS 0x0868 +# define RADEON_Y_GAIN_LIMIT_SHIFT 0 +# define RADEON_UV_GAIN_LIMIT_SHIFT 16 #define RADEON_TV_LINEAR_GAIN_SETTINGS 0x086c +# define RADEON_Y_GAIN_SHIFT 0 +# define RADEON_UV_GAIN_SHIFT 16 #define RADEON_TV_MODULATOR_CNTL1 0x0870 +# define RADEON_YFLT_EN (1 << 2) +# define RADEON_UVFLT_EN (1 << 3) # define RADEON_ALT_PHASE_EN (1 << 6) # define RADEON_SYNC_TIP_LEVEL (1 << 7) +# define RADEON_BLANK_LEVEL_SHIFT 8 +# define RADEON_SET_UP_LEVEL_SHIFT 16 +# define RADEON_SLEW_RATE_LIMIT (1 << 23) +# define RADEON_CY_FILT_BLEND_SHIFT 28 #define RADEON_TV_MODULATOR_CNTL2 0x0874 +# define RADEON_TV_U_BURST_LEVEL_MASK 0x1ff +# define RADEON_TV_V_BURST_LEVEL_MASK 0x1ff +# define RADEON_TV_V_BURST_LEVEL_SHIFT 16 #define RADEON_TV_CRC_CNTL 0x0890 #define RADEON_TV_UV_ADR 0x08ac +# define RADEON_MAX_UV_ADR_MASK 0x000000ff +# define RADEON_MAX_UV_ADR_SHIFT 0 +# define RADEON_TABLE1_BOT_ADR_MASK 0x0000ff00 +# define RADEON_TABLE1_BOT_ADR_SHIFT 8 +# define RADEON_TABLE3_TOP_ADR_MASK 0x00ff0000 +# define RADEON_TABLE3_TOP_ADR_SHIFT 16 +# define RADEON_HCODE_TABLE_SEL_MASK 0x06000000 +# define RADEON_HCODE_TABLE_SEL_SHIFT 25 +# define RADEON_VCODE_TABLE_SEL_MASK 0x18000000 +# define RADEON_VCODE_TABLE_SEL_SHIFT 27 +# define RADEON_TV_MAX_FIFO_ADDR 0x1a7 +# define RADEON_TV_MAX_FIFO_ADDR_INTERNAL 0x1ff #define RADEON_TV_PLL_FINE_CNTL 0x0020 /* PLL */ #define RADEON_TV_PLL_CNTL 0x0021 /* PLL */ +# define RADEON_TV_M0LO_MASK 0xff +# define RADEON_TV_M0HI_MASK 0x3 +# define RADEON_TV_M0HI_SHIFT 18 +# define RADEON_TV_N0LO_MASK 0xff +# define RADEON_TV_N0LO_SHIFT 8 +# define RADEON_TV_N0HI_MASK 0x3 +# define RADEON_TV_N0HI_SHIFT 21 +# define RADEON_TV_P_MASK 0xf +# define RADEON_TV_P_SHIFT 24 # define RADEON_TV_SLIP_EN (1 << 23) # define RADEON_TV_DTO_EN (1 << 28) #define RADEON_TV_PLL_CNTL1 0x0022 /* PLL */ -# define RADEON_TVPLL_TEST_DIS (1 << 31) -# define RADEON_TVCLK_SRC_SEL_TVPLL (1 << 30) +# define RADEON_TVPLL_RESET (1 << 1) # define RADEON_TVPLL_SLEEP (1 << 3) # define RADEON_TVPLL_REFCLK_SEL (1 << 4) +# define RADEON_TVPCP_SHIFT 8 +# define RADEON_TVPCP_MASK (7 << 8) +# define RADEON_TVPVG_SHIFT 11 +# define RADEON_TVPVG_MASK (7 << 11) +# define RADEON_TVPDC_SHIFT 14 +# define RADEON_TVPDC_MASK (3 << 14) +# define RADEON_TVPLL_TEST_DIS (1 << 31) +# define RADEON_TVCLK_SRC_SEL_TVPLL (1 << 30) + +#define RADEON_RS480_UNK_e30 0xe30 +#define RADEON_RS480_UNK_e34 0xe34 +#define RADEON_RS480_UNK_e38 0xe38 +#define RADEON_RS480_UNK_e3c 0xe3c + #endif diff --git a/src/radeon_tv.c b/src/radeon_tv.c new file mode 100644 index 00000000..3a26a0a7 --- /dev/null +++ b/src/radeon_tv.c @@ -0,0 +1,759 @@ +/* + * Integrated TV out support based on the GATOS code by + * Federico Ulivi <fulivi@lycos.com> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdio.h> + +/* X and server generic header files */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "vgaHW.h" +#include "xf86Modes.h" + +/* Driver data structures */ +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_version.h" +#include "radeon_tv.h" + +/********************************************************************** + * + * ModeConstants + * + * Storage of constants related to a single video mode + * + **********************************************************************/ + +typedef struct +{ + CARD16 horResolution; + CARD16 verResolution; + TVStd standard; + CARD16 horTotal; + CARD16 verTotal; + CARD16 horStart; + CARD16 horSyncStart; + CARD16 verSyncStart; + unsigned defRestart; + CARD16 crtcPLL_N; + CARD8 crtcPLL_M; + CARD8 crtcPLL_postDiv; + unsigned pixToTV; +} TVModeConstants; + +static const CARD16 hor_timing_NTSC[] = +{ + 0x0007, + 0x003f, + 0x0263, + 0x0a24, + 0x2a6b, + 0x0a36, + 0x126d, /* H_TABLE_POS1 */ + 0x1bfe, + 0x1a8f, /* H_TABLE_POS2 */ + 0x1ec7, + 0x3863, + 0x1bfe, + 0x1bfe, + 0x1a2a, + 0x1e95, + 0x0e31, + 0x201b, + 0 +}; + +static const CARD16 vert_timing_NTSC[] = +{ + 0x2001, + 0x200d, + 0x1006, + 0x0c06, + 0x1006, + 0x1818, + 0x21e3, + 0x1006, + 0x0c06, + 0x1006, + 0x1817, + 0x21d4, + 0x0002, + 0 +}; + +static const CARD16 hor_timing_PAL[] = +{ + 0x0007, + 0x0058, + 0x027c, + 0x0a31, + 0x2a77, + 0x0a95, + 0x124f, /* H_TABLE_POS1 */ + 0x1bfe, + 0x1b22, /* H_TABLE_POS2 */ + 0x1ef9, + 0x387c, + 0x1bfe, + 0x1bfe, + 0x1b31, + 0x1eb5, + 0x0e43, + 0x201b, + 0 +}; + +static const CARD16 vert_timing_PAL[] = +{ + 0x2001, + 0x200c, + 0x1005, + 0x0c05, + 0x1005, + 0x1401, + 0x1821, + 0x2240, + 0x1005, + 0x0c05, + 0x1005, + 0x1401, + 0x1822, + 0x2230, + 0x0002, + 0 +}; + +/********************************************************************** + * + * availableModes + * + * Table of all allowed modes for tv output + * + **********************************************************************/ +static const TVModeConstants availableTVModes[] = +{ + { + 800, /* horResolution */ + 600, /* verResolution */ + TV_STD_NTSC, /* standard */ + 990, /* horTotal */ + 740, /* verTotal */ + 813, /* horStart */ + 824, /* horSyncStart */ + 632, /* verSyncStart */ + 625592, /* defRestart */ + 592, /* crtcPLL_N */ + 91, /* crtcPLL_M */ + 4, /* crtcPLL_postDiv */ + 1022, /* pixToTV */ + }, + { + 800, /* horResolution */ + 600, /* verResolution */ + TV_STD_PAL, /* standard */ + 1144, /* horTotal */ + 706, /* verTotal */ + 812, /* horStart */ + 824, /* horSyncStart */ + 669, /* verSyncStart */ + 696700, /* defRestart */ + 1382, /* crtcPLL_N */ + 231, /* crtcPLL_M */ + 4, /* crtcPLL_postDiv */ + 759, /* pixToTV */ + } +}; + +#define N_AVAILABLE_MODES (sizeof(availableModes) / sizeof(availableModes[ 0 ])) + +static long YCOEF_value[5] = { 2, 2, 0, 4, 0 }; +static long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 }; +static long SLOPE_value[5] = { 1, 2, 2, 4, 8 }; +static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 }; + + +/* Compute F,V,H restarts from default restart position and hPos & vPos + * Return TRUE when code timing table was changed + */ +static Bool RADEONInitTVRestarts(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int restart; + unsigned hTotal; + unsigned vTotal; + unsigned fTotal; + int vOffset; + int hOffset; + CARD16 p1; + CARD16 p2; + Bool hChanged; + CARD16 hInc; + const TVModeConstants *constPtr; + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + hTotal = constPtr->horTotal; + vTotal = constPtr->verTotal; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) + fTotal = NTSC_TV_VFTOTAL + 1; + else + fTotal = PAL_TV_VFTOTAL + 1; + + /* Adjust positions 1&2 in hor. code timing table */ + hOffset = radeon_output->hPos * H_POS_UNIT; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) { + p1 = hor_timing_NTSC[ H_TABLE_POS1 ]; + p2 = hor_timing_NTSC[ H_TABLE_POS2 ]; + } else { + p1 = hor_timing_PAL[ H_TABLE_POS1 ]; + p2 = hor_timing_PAL[ H_TABLE_POS2 ]; + } + + + p1 = (CARD16)((int)p1 + hOffset); + p2 = (CARD16)((int)p2 - hOffset); + + hChanged = (p1 != save->h_code_timing[ H_TABLE_POS1 ] || + p2 != save->h_code_timing[ H_TABLE_POS2 ]); + + save->h_code_timing[ H_TABLE_POS1 ] = p1; + save->h_code_timing[ H_TABLE_POS2 ] = p2; + + /* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */ + hOffset = (hOffset * (int)(constPtr->pixToTV)) / 1000; + + /* Adjust restart */ + restart = constPtr->defRestart; + + /* + * Convert vPos TV lines to n. of CRTC pixels + * Be verrrrry careful when mixing signed & unsigned values in C.. + */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) + vOffset = ((int)(vTotal * hTotal) * 2 * radeon_output->vPos) / (int)(NTSC_TV_LINES_PER_FRAME); + else + vOffset = ((int)(vTotal * hTotal) * 2 * radeon_output->vPos) / (int)(PAL_TV_LINES_PER_FRAME); + + restart -= vOffset + hOffset; + + ErrorF("computeRestarts: def = %u, h = %d, v = %d, p1=%04x, p2=%04x, restart = %d\n", + constPtr->defRestart , radeon_output->hPos , radeon_output->vPos , p1 , p2 , restart); + + save->tv_hrestart = restart % hTotal; + restart /= hTotal; + save->tv_vrestart = restart % vTotal; + restart /= vTotal; + save->tv_frestart = restart % fTotal; + + ErrorF("computeRestarts: F/H/V=%u,%u,%u\n", + (unsigned)save->tv_frestart, (unsigned)save->tv_vrestart, + (unsigned)save->tv_hrestart); + + /* Compute H_INC from hSize */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + hInc = (CARD16)((int)(constPtr->horResolution * 4096 * NTSC_TV_CLOCK_T) / + (radeon_output->hSize * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE))); + else + hInc = (CARD16)((int)(constPtr->horResolution * 4096 * PAL_TV_CLOCK_T) / + (radeon_output->hSize * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE))); + + save->tv_timing_cntl = (save->tv_timing_cntl & ~RADEON_H_INC_MASK) | + ((CARD32)hInc << RADEON_H_INC_SHIFT); + + ErrorF("computeRestarts: hSize=%d,hInc=%u\n" , radeon_output->hSize , hInc); + + return hChanged; +} + +/* intit TV-out regs */ +void RADEONInitTVRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned i; + unsigned long vert_space, flicker_removal; + CARD32 tmp; + const TVModeConstants *constPtr; + const CARD16 *hor_timing; + const CARD16 *vert_timing; + + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + save->tv_crc_cntl = 0; + + save->tv_gain_limit_settings = (0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) | + (0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT); + + save->tv_hdisp = constPtr->horResolution - 1; + save->tv_hstart = constPtr->horStart; + save->tv_htotal = constPtr->horTotal - 1; + + save->tv_linear_gain_settings = (0x100 << RADEON_UV_GAIN_SHIFT) | + (0x100 << RADEON_Y_GAIN_SHIFT); + + save->tv_master_cntl = (RADEON_VIN_ASYNC_RST + | RADEON_CRT_FIFO_CE_EN + | RADEON_TV_FIFO_CE_EN + | RADEON_TV_ON); + + if (!IS_R300_VARIANT) + save->tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J) + save->tv_master_cntl |= RADEON_RESTART_PHASE_FIX; + + save->tv_modulator_cntl1 = RADEON_SLEW_RATE_LIMIT + | RADEON_SYNC_TIP_LEVEL + | RADEON_YFLT_EN + | RADEON_UVFLT_EN + | (6 << RADEON_CY_FILT_BLEND_SHIFT); + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J) { + save->tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT) + | (0x3b << RADEON_BLANK_LEVEL_SHIFT); + save->tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) | + ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); + } else if (radeon_output->tvStd == TV_STD_SCART_PAL) { + save->tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN; + save->tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) | + ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); + } else { + save->tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN + | (0x3b << RADEON_SET_UP_LEVEL_SHIFT) + | (0x3b << RADEON_BLANK_LEVEL_SHIFT); + save->tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) | + ((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); + } + + save->pll_test_cntl = 0; + + save->tv_pre_dac_mux_cntl = (RADEON_Y_RED_EN + | RADEON_C_GRN_EN + | RADEON_CMP_BLU_EN + | RADEON_DAC_DITHER_EN); + + save->tv_rgb_cntl = (RADEON_RGB_DITHER_EN + | RADEON_TVOUT_SCALE_EN + | (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT) + | (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT)); + + if (IsPrimary) { + if (radeon_output->Flags & RADEON_USE_RMX) + save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX; + else + save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1; + } else { + save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2; + } + + save->tv_sync_cntl = RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE; + + save->tv_sync_size = constPtr->horResolution + 8; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) + vert_space = constPtr->verTotal * 2 * 10000 / NTSC_TV_LINES_PER_FRAME; + else + vert_space = constPtr->verTotal * 2 * 10000 / PAL_TV_LINES_PER_FRAME; + + save->tv_vscaler_cntl1 = RADEON_Y_W_EN; + save->tv_vscaler_cntl1 = + (save->tv_vscaler_cntl1 & 0xe3ff0000) | (vert_space * (1 << FRAC_BITS) / 10000); + save->tv_vscaler_cntl1 |= RADEON_RESTART_FIELD; + if (constPtr->horResolution == 1024) + save->tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT); + else + save->tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT); + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) + flicker_removal = + (float) constPtr->verTotal * 2.0 / NTSC_TV_LINES_PER_FRAME + 0.5; + else + flicker_removal = + (float) constPtr->verTotal * 2.0 / PAL_TV_LINES_PER_FRAME + 0.5; + + if (flicker_removal < 3) + flicker_removal = 3; + for (i = 0; i < 6; ++i) { + if (flicker_removal == SLOPE_limit[i]) + break; + } + save->tv_y_saw_tooth_cntl = + (vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) + 5001) / 10000 / 8 + | ((SLOPE_value[i] * (1 << (FRAC_BITS - 1)) / 8) << 16); + save->tv_y_fall_cntl = + (YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) | + RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) / + 1024; + save->tv_y_rise_cntl = + RADEON_Y_RISE_PING_PONG + | (flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024; + + save->tv_vscaler_cntl2 = ((save->tv_vscaler_cntl2 & 0x00fffff0) + | (0x10 << 24) + | RADEON_DITHER_MODE + | RADEON_Y_OUTPUT_DITHER_EN + | RADEON_UV_OUTPUT_DITHER_EN + | RADEON_UV_TO_BUF_DITHER_EN); + + tmp = (save->tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK; + tmp = ((16384 * 256 * 10) / tmp + 5) / 10; + tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000; + save->tv_timing_cntl = tmp; + + save->tv_dac_cntl = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | (8 << 16) | (6 << 20); + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J) + save->tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC; + else + save->tv_dac_cntl |= RADEON_TV_DAC_STD_PAL; + +#if 0 + /* needs fixes for r4xx */ + save->tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | RADEON_TV_DAC_GDACPD + | RADEON_TV_DAC_BDACPD); + + if (radeon_output->MonType == MT_CTV) { + save->tv_dac_cntl &= ~RADEON_TV_DAC_BDACPD; + } + + if (radeon_output->MonType == MT_STV) { + save->tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD); + } +#endif + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J) + save->tv_pll_cntl = (NTSC_TV_PLL_M & RADEON_TV_M0LO_MASK) | + (((NTSC_TV_PLL_M >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) | + ((NTSC_TV_PLL_N & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) | + (((NTSC_TV_PLL_N >> 8) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) | + ((NTSC_TV_PLL_P & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT); + else + save->tv_pll_cntl = (PAL_TV_PLL_M & RADEON_TV_M0LO_MASK) | + (((PAL_TV_PLL_M >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) | + ((PAL_TV_PLL_N & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) | + (((PAL_TV_PLL_N >> 8) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) | + ((PAL_TV_PLL_P & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT); + + save->tv_pll_cntl1 = (((4 & RADEON_TVPCP_MASK)<< RADEON_TVPCP_SHIFT) | + ((4 & RADEON_TVPVG_MASK) << RADEON_TVPVG_SHIFT) | + ((1 & RADEON_TVPDC_MASK)<< RADEON_TVPDC_SHIFT) | + RADEON_TVCLK_SRC_SEL_TVPLL | + RADEON_TVPLL_TEST_DIS); + + save->tv_upsamp_and_gain_cntl = RADEON_YUPSAMP_EN | RADEON_UVUPSAMP_EN; + + save->tv_uv_adr = 0xc8; + + save->tv_vdisp = constPtr->verResolution - 1; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) + save->tv_ftotal = NTSC_TV_VFTOTAL; + else + save->tv_ftotal = PAL_TV_VFTOTAL; + + save->tv_vtotal = constPtr->verTotal - 1; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) { + hor_timing = hor_timing_NTSC; + } else { + hor_timing = hor_timing_PAL; + } + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) { + vert_timing = vert_timing_NTSC; + } else { + vert_timing = vert_timing_PAL; + } + + for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) { + if ((save->h_code_timing[ i ] = hor_timing[ i ]) == 0) + break; + } + + for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) { + if ((save->v_code_timing[ i ] = vert_timing[ i ]) == 0) + break; + } + + /* + * This must be called AFTER loading timing tables as they are modified by this function + */ + RADEONInitTVRestarts(output, save, mode); + + save->dac_cntl &= ~RADEON_DAC_TVO_EN; + + if (IS_R300_VARIANT) + save->gpiopad_a = info->SavedReg.gpiopad_a & ~1; + + if (IsPrimary) { + save->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC + | RADEON_DISP_TV_SOURCE_CRTC); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + save->disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2; + } else { + save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + } + } else { + save->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC; + + if (info->ChipFamily >= CHIP_FAMILY_R200) { + save->disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2; + } else { + save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; + } + } +} + + +/* Set hw registers for a new h/v position & h size */ +void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + Bool reloadTable; + RADEONSavePtr restore = &info->ModeReg; + + reloadTable = RADEONInitTVRestarts(output, restore, mode); + + RADEONRestoreTVRestarts(pScrn, restore); + + OUTREG(RADEON_TV_TIMING_CNTL, restore->tv_timing_cntl); + + if (reloadTable) { + OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl + | RADEON_TV_ASYNC_RST + | RADEON_CRT_ASYNC_RST + | RADEON_RESTART_PHASE_FIX); + + RADEONRestoreTVTimingTables(pScrn, restore); + + OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl); + } +} + +void RADEONAdjustCrtcRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output) +{ + const TVModeConstants *constPtr; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + save->crtc_h_total_disp = (((constPtr->horResolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) | + (((constPtr->horTotal / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT); + + save->crtc_h_sync_strt_wid = (save->crtc_h_sync_strt_wid + & ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR)) | + (((constPtr->horSyncStart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) | + (constPtr->horSyncStart & 7); + + save->crtc_v_total_disp = ((constPtr->verResolution - 1) << RADEON_CRTC_V_DISP_SHIFT) | + ((constPtr->verTotal - 1) << RADEON_CRTC_V_TOTAL_SHIFT); + + save->crtc_v_sync_strt_wid = (save->crtc_v_sync_strt_wid & ~RADEON_CRTC_V_SYNC_STRT) | + ((constPtr->verSyncStart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT); + +} + +void RADEONAdjustPLLRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output) +{ + unsigned postDiv; + const TVModeConstants *constPtr; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + save->htotal_cntl = (constPtr->horTotal & 0x7 /*0xf*/) | RADEON_HTOT_CNTL_VGA_EN; + + save->ppll_ref_div = constPtr->crtcPLL_M; + + switch (constPtr->crtcPLL_postDiv) { + case 1: + postDiv = 0; + break; + case 2: + postDiv = 1; + break; + case 3: + postDiv = 4; + break; + case 4: + postDiv = 2; + break; + case 6: + postDiv = 6; + break; + case 8: + postDiv = 3; + break; + case 12: + postDiv = 7; + break; + case 16: + default: + postDiv = 5; + break; + } + + save->ppll_div_3 = (constPtr->crtcPLL_N & 0x7ff) | (postDiv << 16); + + save->pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL); + save->pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK; + +} + +void RADEONAdjustCrtc2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output) +{ + const TVModeConstants *constPtr; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + save->crtc2_h_total_disp = (((constPtr->horResolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) | + (((constPtr->horTotal / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT); + + save->crtc2_h_sync_strt_wid = (save->crtc2_h_sync_strt_wid + & ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR)) | + (((constPtr->horSyncStart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) | + (constPtr->horSyncStart & 7); + + save->crtc2_v_total_disp = ((constPtr->verResolution - 1) << RADEON_CRTC_V_DISP_SHIFT) | + ((constPtr->verTotal - 1) << RADEON_CRTC_V_TOTAL_SHIFT); + + save->crtc_v_sync_strt_wid = (save->crtc_v_sync_strt_wid & ~RADEON_CRTC_V_SYNC_STRT) | + ((constPtr->verSyncStart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT); + +} + +void RADEONAdjustPLL2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output) +{ + unsigned postDiv; + const TVModeConstants *constPtr; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + save->htotal_cntl2 = (constPtr->horTotal & 0x7); /* 0xf */ + + save->p2pll_ref_div = constPtr->crtcPLL_M; + + switch (constPtr->crtcPLL_postDiv) { + case 1: + postDiv = 0; + break; + case 2: + postDiv = 1; + break; + case 3: + postDiv = 4; + break; + case 4: + postDiv = 2; + break; + case 6: + postDiv = 6; + break; + case 8: + postDiv = 3; + break; + case 12: + postDiv = 7; + break; + case 16: + default: + postDiv = 5; + break; + } + + save->p2pll_div_0 = (constPtr->crtcPLL_N & 0x7ff) | (postDiv << 16); + + save->pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK; + save->pixclks_cntl |= (RADEON_PIX2CLK_SRC_SEL_P2PLLCLK + | RADEON_PIXCLK_TV_SRC_SEL); + +} diff --git a/src/radeon_tv.h b/src/radeon_tv.h new file mode 100644 index 00000000..5c8c8c97 --- /dev/null +++ b/src/radeon_tv.h @@ -0,0 +1,56 @@ +/* + * Integrated TV out support based on the GATOS code by + * Federico Ulivi <fulivi@lycos.com> + */ + +/* + * Maximum length of horizontal/vertical code timing tables for state storage + */ +#define MAX_H_CODE_TIMING_LEN 32 +#define MAX_V_CODE_TIMING_LEN 32 + +/* + * Limits of h/v positions (hPos & vPos) + */ +#define MAX_H_POSITION 5 /* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */ +#define MAX_V_POSITION 5 /* Range: [-5..5], negative is up, 0 is default, positive is down */ + +/* + * Unit for hPos (in TV clock periods) + */ +#define H_POS_UNIT 10 + +/* + * Indexes in h. code timing table for horizontal line position adjustment + */ +#define H_TABLE_POS1 6 +#define H_TABLE_POS2 8 + +/* + * Limits of hor. size (hSize) + */ +#define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */ + +/* tv standard constants */ +#define NTSC_TV_PLL_M 22 +#define NTSC_TV_PLL_N 175 +#define NTSC_TV_PLL_P 5 +#define NTSC_TV_CLOCK_T 233 +#define NTSC_TV_VFTOTAL 1 +#define NTSC_TV_LINES_PER_FRAME 525 +#define NTSC_TV_ZERO_H_SIZE 479166 +#define NTSC_TV_H_SIZE_UNIT 9478 + +#define PAL_TV_PLL_M 113 +#define PAL_TV_PLL_N 668 +#define PAL_TV_PLL_P 3 +#define PAL_TV_CLOCK_T 188 +#define PAL_TV_VFTOTAL 3 +#define PAL_TV_LINES_PER_FRAME 625 +#define PAL_TV_ZERO_H_SIZE 473200 +#define PAL_TV_H_SIZE_UNIT 9360 + + +#define VERT_LEAD_IN_LINES 2 +#define FRAC_BITS 0xe +#define FRAC_MASK 0x3fff diff --git a/src/radeon_version.h b/src/radeon_version.h index a1b24590..ccc1367a 100644 --- a/src/radeon_version.h +++ b/src/radeon_version.h @@ -41,7 +41,7 @@ #define RADEON_VERSION_MAJOR 4 #define RADEON_VERSION_MAJOR_TILED 5 -#define RADEON_VERSION_MINOR 2 +#define RADEON_VERSION_MINOR 3 #define RADEON_VERSION_PATCH 0 #ifndef RADEON_VERSION_EXTRA diff --git a/src/radeon_video.c b/src/radeon_video.c index 390df892..271f7fe8 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -12,7 +12,6 @@ #include "radeon_reg.h" #include "radeon_macros.h" #include "radeon_probe.h" -#include "radeon_mergedfb.h" #include "radeon_video.h" #include "xf86.h" @@ -100,14 +99,14 @@ static void RADEON_TDA9885_SetEncoding(RADEONPortPrivPtr pPriv); static void RADEON_FI1236_SetEncoding(RADEONPortPrivPtr pPriv); -#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v)) static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer; static Atom xvRedIntensity, xvGreenIntensity, xvBlueIntensity; static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults; static Atom xvGamma, xvColorspace; -static Atom xvSwitchCRT; +static Atom xvCRTC; static Atom xvEncoding, xvFrequency, xvVolume, xvMute, xvDecBrightness, xvDecContrast, xvDecHue, xvDecColor, xvDecSaturation, xvTunerStatus, xvSAP, xvOverlayDeinterlacingMethod, @@ -120,6 +119,114 @@ static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode; #define GET_PORT_PRIVATE(pScrn) \ (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr) +static void +radeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) +{ + dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; + dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; + dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; + dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; + + if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) + dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; +} + +static void +radeon_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) +{ + if (crtc->enabled) { + crtc_box->x1 = crtc->x; + crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); + crtc_box->y1 = crtc->y; + crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); + } else + crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; +} + +static int +radeon_box_area(BoxPtr box) +{ + return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); +} + +static xf86CrtcPtr +radeon_covering_crtc(ScrnInfoPtr pScrn, + BoxPtr box, + xf86CrtcPtr desired, + BoxPtr crtc_box_ret) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc, best_crtc; + int coverage, best_coverage; + int c; + BoxRec crtc_box, cover_box; + + best_crtc = NULL; + best_coverage = 0; + crtc_box_ret->x1 = 0; + crtc_box_ret->x2 = 0; + crtc_box_ret->y1 = 0; + crtc_box_ret->y2 = 0; + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + radeon_crtc_box(crtc, &crtc_box); + radeon_box_intersect(&cover_box, &crtc_box, box); + coverage = radeon_box_area(&cover_box); + if (coverage && crtc == desired) { + *crtc_box_ret = crtc_box; + return crtc; + } else if (coverage > best_coverage) { + *crtc_box_ret = crtc_box; + best_crtc = crtc; + best_coverage = coverage; + } + } + return best_crtc; +} + +static Bool +radeon_clip_video_helper(ScrnInfoPtr pScrn, + xf86CrtcPtr *crtc_ret, + xf86CrtcPtr desired_crtc, + BoxPtr dst, + INT32 *xa, + INT32 *xb, + INT32 *ya, + INT32 *yb, + RegionPtr reg, + INT32 width, + INT32 height) +{ + Bool ret; + RegionRec crtc_region_local; + RegionPtr crtc_region = reg; + + /* + * For overlay video, compute the relevant CRTC and + * clip video to that + */ + if (crtc_ret) { + BoxRec crtc_box; + xf86CrtcPtr crtc = radeon_covering_crtc(pScrn, dst, + desired_crtc, + &crtc_box); + + if (crtc) { + REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1); + crtc_region = &crtc_region_local; + REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg); + } + *crtc_ret = crtc; + } + + ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, + crtc_region, width, height); + + if (crtc_region != reg) + REGION_UNINIT (pScreen, &crtc_region_local); + + return ret; +} #ifdef USE_EXA static void @@ -227,7 +334,7 @@ static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"}, - {XvSettable | XvGettable, 0, 1, "XV_SWITCHCRT"}, + {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"}, {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, }; @@ -258,7 +365,7 @@ static XF86AttributeRec Attributes[NUM_DEC_ATTRIBUTES+1] = {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"}, - {XvSettable | XvGettable, 0, 1, "XV_SWITCHCRT"}, + {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"}, {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, @@ -1083,7 +1190,7 @@ RADEONResetVideo(ScrnInfoPtr pScrn) xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); - xvSwitchCRT = MAKE_ATOM("XV_SWITCHCRT"); + xvCRTC = MAKE_ATOM("XV_CRTC"); xvOvAlpha = MAKE_ATOM("XV_OVERLAY_ALPHA"); xvGrAlpha = MAKE_ATOM("XV_GRAPHICS_ALPHA"); @@ -1189,17 +1296,10 @@ static void RADEONSetupTheatre(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) /* Go and find Rage Theatre, if it exists */ - switch(info->Chipset){ - case PCI_CHIP_RADEON_LY: - case PCI_CHIP_RADEON_LZ: - xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility M6, not scanning for Rage Theatre\n"); - break; - case PCI_CHIP_RADEON_LW: - xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility M7, not scanning for Rage Theatre\n"); - break; - default: - pPriv->theatre=xf86_DetectTheatre(pPriv->VIP); - } + if (info->IsMobility) + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility, not scanning for Rage Theatre\n"); + else + pPriv->theatre=xf86_DetectTheatre(pPriv->VIP); if(pPriv->theatre==NULL)return; @@ -1225,21 +1325,21 @@ static void RADEONSetupTheatre(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) } else { t->wComp0Connector=RT_COMP1; } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Composite connector is port %ld\n", t->wComp0Connector); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Composite connector is port %u\n", (unsigned)t->wComp0Connector); break; case 3: if(a & 0x4){ t->wSVideo0Connector=RT_YCR_COMP4; } else { t->wSVideo0Connector=RT_YCF_COMP4; } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SVideo connector is port %ld\n", t->wSVideo0Connector); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SVideo connector is port %u\n", (unsigned)t->wSVideo0Connector); break; default: break; } } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rage Theatre: Connectors (detected): tuner=%ld, composite=%ld, svideo=%ld\n", - t->wTunerConnector, t->wComp0Connector, t->wSVideo0Connector); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rage Theatre: Connectors (detected): tuner=%u, composite=%u, svideo=%u\n", + (unsigned)t->wTunerConnector, (unsigned)t->wComp0Connector, (unsigned)t->wSVideo0Connector); } @@ -1247,8 +1347,8 @@ static void RADEONSetupTheatre(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) if(info->RageTheatreCompositePort>=0)t->wComp0Connector=info->RageTheatreCompositePort; if(info->RageTheatreSVideoPort>=0)t->wSVideo0Connector=info->RageTheatreSVideoPort; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RageTheatre: Connectors (using): tuner=%ld, composite=%ld, svideo=%ld\n", - t->wTunerConnector, t->wComp0Connector, t->wSVideo0Connector); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RageTheatre: Connectors (using): tuner=%u, composite=%u, svideo=%u\n", + (unsigned)t->wTunerConnector, (unsigned)t->wComp0Connector, (unsigned)t->wSVideo0Connector); switch((info->RageTheatreCrystal>=0)?info->RageTheatreCrystal:pll->reference_freq){ case 2700: @@ -1303,11 +1403,8 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) pPriv->currentBuffer = 0; pPriv->autopaint_colorkey = TRUE; pPriv->gamma = 1000; - if (info->OverlayOnCRTC2) - pPriv->crt2 = TRUE; - else - pPriv->crt2 = FALSE; - + pPriv->desired_crtc = NULL; + pPriv->ov_alpha = 255; pPriv->gr_alpha = 255; pPriv->alpha_mode = 0; @@ -1332,27 +1429,15 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) * 0 for PIXCLK < 175Mhz, and 1 (divide by 2) * for higher clocks, sure makes life nicer */ + dot_clock = info->ModeReg.dot_clock_freq; - /* Figure out which head we are on */ - if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) - dot_clock = info->ModeReg.dot_clock_freq_2; - else - dot_clock = info->ModeReg.dot_clock_freq; - - if(dot_clock < 17500) + if (dot_clock < 17500) info->ecp_div = 0; else info->ecp_div = 1; ecp = (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (info->ecp_div << 8); -#if 0 - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dotclock is %g Mhz, setting ecp_div to %d\n", info->ModeReg.dot_clock_freq/100.0, info->ecp_div); -#endif - - - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200) || - (info->ChipFamily == CHIP_FAMILY_RS300)) { + if (info->IsIGP) { /* Force the overlay clock on for integrated chips */ ecp |= (1<<18); @@ -1361,7 +1446,6 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, ecp); - /* Decide on tuner type */ if((info->tunerType<0) && (info->MM_TABLE_valid)) { pPriv->tuner_type = info->MM_TABLE.tuner_type; @@ -1478,7 +1562,7 @@ RADEONSetupImageVideo(ScreenPtr pScreen) return NULL; adapt->type = XvWindowMask | XvInputMask | XvImageMask; - adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/; adapt->name = "ATI Radeon Video Overlay"; adapt->nEncodings = 1; adapt->pEncodings = &DummyEncoding; @@ -1665,14 +1749,15 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, RADEONSetColorKey (pScrn, pPriv->colorKey); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); } - else if(attribute == xvSwitchCRT) + else if(attribute == xvCRTC) { - pPriv->crt2 = ClipValue (value, 0, 1); - pPriv->crt2 = value; - if (pPriv->crt2) - info->OverlayOnCRTC2 = TRUE; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + if ((value < -1) || (value > xf86_config->num_crtc)) + return BadValue; + if (value < 0) + pPriv->desired_crtc = NULL; else - info->OverlayOnCRTC2 = FALSE; + pPriv->desired_crtc = xf86_config->crtc[value]; } else if(attribute == xvOvAlpha) { @@ -1796,7 +1881,8 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, else if(attribute == xvAdjustment) { pPriv->adjustment=value; - xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Setting pPriv->adjustment to %ld\n", pPriv->adjustment); + xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Setting pPriv->adjustment to %u\n", + (unsigned)pPriv->adjustment); if(pPriv->tda9885!=0){ pPriv->tda9885->top_adjustment=value; RADEON_TDA9885_SetEncoding(pPriv); @@ -1862,8 +1948,16 @@ RADEONGetPortAttribute(ScrnInfoPtr pScrn, *value = pPriv->doubleBuffer ? 1 : 0; else if(attribute == xvColorKey) *value = pPriv->colorKey; - else if(attribute == xvSwitchCRT) - *value = pPriv->crt2 ? 1 : 0; + else if(attribute == xvCRTC) { + int c; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + for (c = 0; c < xf86_config->num_crtc; c++) + if (xf86_config->crtc[c] == pPriv->desired_crtc) + break; + if (c == xf86_config->num_crtc) + c = -1; + *value = c; + } else if(attribute == xvOvAlpha) *value = pPriv->ov_alpha; else if(attribute == xvGrAlpha) @@ -2396,7 +2490,8 @@ RADEONFreeMemory( static void RADEONDisplayVideo( ScrnInfoPtr pScrn, - RADEONPortPrivPtr pPriv, + xf86CrtcPtr crtc, + RADEONPortPrivPtr pPriv, int id, int offset1, int offset2, int offset3, int offset4, @@ -2410,6 +2505,7 @@ RADEONDisplayVideo( int deinterlacing_method ){ RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 v_inc, h_inc, h_inc_uv, step_by_y, step_by_uv, tmp; double h_inc_d; @@ -2423,7 +2519,6 @@ RADEONDisplayVideo( int y_off; CARD32 scaler_src; CARD32 dot_clock; - DisplayModePtr overlay_mode; int is_rgb; int is_planar; int i; @@ -2433,6 +2528,10 @@ RADEONDisplayVideo( int predownscale=0; int src_w_d; int leftuv = 0; + DisplayModePtr mode; + RADEONOutputPrivatePtr radeon_output; + xf86OutputPtr output; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; is_rgb=0; is_planar=0; switch(id){ @@ -2455,7 +2554,7 @@ RADEONDisplayVideo( workarounds for chip erratas */ /* Figure out which head we are on for dot clock */ - if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) + if (radeon_crtc->crtc_id == 1) dot_clock = info->ModeReg.dot_clock_freq_2; else dot_clock = info->ModeReg.dot_clock_freq; @@ -2480,34 +2579,26 @@ RADEONDisplayVideo( v_inc_shift = 20; y_mult = 1; - if (info->MergedFB) { - if (info->OverlayOnCRTC2) - overlay_mode = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2; - else - overlay_mode = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT1; - if (overlay_mode->Flags & V_INTERLACE) - v_inc_shift++; - if (overlay_mode->Flags & V_DBLSCAN) { - v_inc_shift--; - y_mult = 2; - } - if (overlay_mode->Flags & RADEON_USE_RMX) { - v_inc = ((src_h * overlay_mode->CrtcVDisplay / info->PanelYRes) << v_inc_shift) / drw_h; - } else { - v_inc = (src_h << v_inc_shift) / drw_h; - } - } else { - if (pScrn->currentMode->Flags & V_INTERLACE) - v_inc_shift++; - if (pScrn->currentMode->Flags & V_DBLSCAN) { - v_inc_shift--; - y_mult = 2; + mode = &crtc->mode; + + if (mode->Flags & V_INTERLACE) + v_inc_shift++; + if (mode->Flags & V_DBLSCAN) { + v_inc_shift--; + y_mult = 2; + } + + v_inc = (src_h << v_inc_shift) / drw_h; + + for (i = 0; i < xf86_config->num_output; i++) { + output = xf86_config->output[i]; + if (output->crtc == crtc) { + radeon_output = output->driver_private; + if (radeon_output->Flags & RADEON_USE_RMX) + v_inc = ((src_h * mode->CrtcVDisplay / + radeon_output->PanelYRes) << v_inc_shift) / drw_h; + break; } - if (pScrn->currentMode->Flags & RADEON_USE_RMX) { - v_inc = ((src_h * pScrn->currentMode->CrtcVDisplay / info->PanelYRes) << v_inc_shift) / drw_h; - } else { - v_inc = (src_h << v_inc_shift) / drw_h; - } } h_inc = (1 << (12 + ecp_div)); @@ -2593,14 +2684,6 @@ RADEONDisplayVideo( offset5 += ((left >> 16) & ~7) << 1; offset6 += ((left >> 16) & ~7) << 1; } - if (info->IsSecondary) { - offset1 += info->FbMapSize; - offset2 += info->FbMapSize; - offset3 += info->FbMapSize; - offset4 += info->FbMapSize; - offset5 += info->FbMapSize; - offset6 += info->FbMapSize; - } tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); p1_h_accum_init = ((tmp << 4) & 0x000f8000) | @@ -2651,19 +2734,15 @@ RADEONDisplayVideo( x_off = 0; /* needed to make the overlay work on crtc1 in leftof and above modes */ - if (info->MergedFB) { - RADEONScrn2Rel srel = - ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position; - overlay_mode = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2; - if (srel == radeonLeftOf) { - x_off -= overlay_mode->CrtcHDisplay; - /* y_off -= pScrn->frameY0; */ - } - if (srel == radeonAbove) { - y_off -= overlay_mode->CrtcVDisplay; - /* x_off -= pScrn->frameX0; */ - } + /* XXX: may need to adjust x_off/y_off for dualhead like mergedfb -- need to test */ + /* + if (srel == radeonLeftOf) { + x_off -= mode->CrtcHDisplay; + } + if (srel == radeonAbove) { + y_off -= mode->CrtcVDisplay; } + */ /* Put the hardware overlay on CRTC2: * @@ -2672,7 +2751,7 @@ RADEONDisplayVideo( * rendering for the second head. */ - if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) { + if (radeon_crtc->crtc_id == 1) { x_off = 0; OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1 + x_off) | ((dstBox->y1*y_mult) << 16))); @@ -2750,6 +2829,7 @@ RADEONDisplayVideo( | ((info->ChipFamily >= CHIP_FAMILY_R200) ? RADEON_SCALER_TEMPORAL_DEINT : 0); break; } + OUTREG(RADEON_OV0_SCALE_CNTL, scale_cntl); OUTREG(RADEON_OV0_REG_LOAD_CNTL, 0); } @@ -2789,6 +2869,7 @@ RADEONPutImage( int top, left, npixels, nlines, bpp; BoxRec dstBox; CARD32 tmp; + xf86CrtcPtr crtc; /* * s2offset, s3offset - byte offsets into U and V plane of the @@ -2821,24 +2902,15 @@ RADEONPutImage( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; - if (info->MergedFB) - RADEONChooseOverlayCRTC(pScrn, &dstBox); - - if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, - clipBoxes, width, height)) - return Success; - - if (info->MergedFB && info->OverlayOnCRTC2) { - dstBox.x1 -= info->CRT2pScrn->frameX0; - dstBox.x2 -= info->CRT2pScrn->frameX0; - dstBox.y1 -= info->CRT2pScrn->frameY0; - dstBox.y2 -= info->CRT2pScrn->frameY0; - } else { - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; - } + if (!radeon_clip_video_helper(pScrn, &crtc, pPriv->desired_crtc, + &dstBox, &xa, &xb, &ya, &yb, + clipBoxes, width, height)) + return Success; + + dstBox.x1 -= crtc->x; + dstBox.x2 -= crtc->x; + dstBox.y1 -= crtc->y; + dstBox.y2 -= crtc->y; bpp = pScrn->bitsPerPixel >> 3; @@ -2891,8 +2963,14 @@ RADEONPutImage( offset = (pPriv->video_offset) + (top * dstPitch); - if(pPriv->doubleBuffer) + if(pPriv->doubleBuffer) { + unsigned char *RADEONMMIO = info->MMIO; + + /* Wait for last flip to take effect */ + while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & RADEON_REG_LD_CTL_FLIP_READBACK)); + offset += pPriv->currentBuffer * new_size; + } dst_start = info->FB + offset; @@ -2962,7 +3040,7 @@ RADEONPutImage( /* FIXME: someone should look at these offsets, I don't think it makes sense how they are handled throughout the source. */ - RADEONDisplayVideo(pScrn, pPriv, id, offset, offset + d2line, offset + d3line, + RADEONDisplayVideo(pScrn, crtc, pPriv, id, offset, offset + d2line, offset + d3line, offset, offset + d2line, offset + d3line, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h, METHOD_BOB); @@ -3180,12 +3258,12 @@ RADEONDisplaySurface( ){ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; ScrnInfoPtr pScrn = surface->pScrn; - RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr portPriv = info->adaptor->pPortPrivates[0].ptr; INT32 xa, ya, xb, yb; BoxRec dstBox; + xf86CrtcPtr crtc; if (src_w > (drw_w << 4)) drw_w = src_w >> 4; @@ -3202,30 +3280,21 @@ RADEONDisplaySurface( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; - if (info->MergedFB) - RADEONChooseOverlayCRTC(pScrn, &dstBox); - - if (!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, - surface->width, surface->height)) - return Success; + if (!radeon_clip_video_helper(pScrn, &crtc, portPriv->desired_crtc, + &dstBox, &xa, &xb, &ya, &yb, clipBoxes, + surface->width, surface->height)) + return Success; - if (info->MergedFB && info->OverlayOnCRTC2) { - dstBox.x1 -= info->CRT2pScrn->frameX0; - dstBox.x2 -= info->CRT2pScrn->frameX0; - dstBox.y1 -= info->CRT2pScrn->frameY0; - dstBox.y2 -= info->CRT2pScrn->frameY0; - } else { - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; - } + dstBox.x1 -= crtc->x; + dstBox.x2 -= crtc->x; + dstBox.y1 -= crtc->y; + dstBox.y2 -= crtc->y; #if 0 /* this isn't needed */ RADEONResetVideo(pScrn); #endif - RADEONDisplayVideo(pScrn, portPriv, surface->id, + RADEONDisplayVideo(pScrn, crtc, portPriv, surface->id, surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->offsets[0], @@ -3261,8 +3330,8 @@ RADEONInitOffscreenImages(ScreenPtr pScreen) return; offscreenImages[0].image = &Images[0]; - offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | - VIDEO_CLIP_TO_VIEWPORT; + offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES /*| + VIDEO_CLIP_TO_VIEWPORT*/; offscreenImages[0].alloc_surface = RADEONAllocateSurface; offscreenImages[0].free_surface = RADEONFreeSurface; offscreenImages[0].display = RADEONDisplaySurface; @@ -3303,6 +3372,7 @@ RADEONPutVideo( int width, height; int mult; int vbi_line_width, vbi_start, vbi_end; + xf86CrtcPtr crtc; RADEON_SYNC(info, pScrn); /* @@ -3340,27 +3410,19 @@ RADEONPutVideo( vbi_line_width = 798*2; if(width<=640) - vbi_line_width = 0x640; /* 1600 actually */ - else - vbi_line_width = 2000; /* might need adjustment */ + vbi_line_width = 0x640; /* 1600 actually */ + else + vbi_line_width = 2000; /* might need adjustment */ - if (info->MergedFB) - RADEONChooseOverlayCRTC(pScrn, &dstBox); - - if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height)) - return Success; + if (!radeon_clip_video_helper(pScrn, &crtc, pPriv->desired_crtc, + &dstBox, &xa, &xb, &ya, &yb, + clipBoxes, width, height)) + return Success; - if (info->MergedFB && info->OverlayOnCRTC2) { - dstBox.x1 -= info->CRT2pScrn->frameX0; - dstBox.x2 -= info->CRT2pScrn->frameX0; - dstBox.y1 -= info->CRT2pScrn->frameY0; - dstBox.y2 -= info->CRT2pScrn->frameY0; - } else { - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; - } + dstBox.x1 -= crtc->x; + dstBox.x2 -= crtc->x; + dstBox.y1 -= crtc->y; + dstBox.y2 -= crtc->y; bpp = pScrn->bitsPerPixel >> 3; pitch = bpp * pScrn->displayWidth; @@ -3382,7 +3444,8 @@ RADEONPutVideo( id = FOURCC_YUY2; top = ya>>16; - +#if 0 + /* setting the ID above makes this useful - needs revisiting */ switch(id) { case FOURCC_YV12: case FOURCC_I420: @@ -3400,6 +3463,10 @@ RADEONPutVideo( srcPitch = (width<<1); break; } +#else + dstPitch = ((width<<1) + 15) & ~15; + srcPitch = (width<<1); +#endif new_size = dstPitch * height; new_size = new_size + 0x1f; /* for aligning */ @@ -3510,7 +3577,7 @@ RADEONPutVideo( RADEONFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes); } - RADEONDisplayVideo(pScrn, pPriv, id, offset1+top*srcPitch, offset2+top*srcPitch, + RADEONDisplayVideo(pScrn, crtc, pPriv, id, offset1+top*srcPitch, offset2+top*srcPitch, offset3+top*srcPitch, offset4+top*srcPitch, offset1+top*srcPitch, offset2+top*srcPitch, width, height, dstPitch*mult/2, xa, xb, ya, &dstBox, src_w, src_h*mult/2, drw_w, drw_h, pPriv->overlay_deinterlacing_method); diff --git a/src/radeon_video.h b/src/radeon_video.h index b6d5d2d9..072f40e1 100644 --- a/src/radeon_video.h +++ b/src/radeon_video.h @@ -11,6 +11,8 @@ #include "generic_bus.h" #include "theatre.h" +#include "xf86Crtc.h" + /* Xvideo port struct */ typedef struct { CARD32 transform_index; @@ -40,7 +42,7 @@ typedef struct { CARD8 tuner_type; MSP3430Ptr msp3430; TDA9885Ptr tda9885; - UDA1380Ptr uda1380; + UDA1380Ptr uda1380; /* VIP bus and devices */ GENERIC_BUS_Ptr VIP; @@ -77,7 +79,7 @@ typedef struct { Time offTime; Time freeTime; Bool autopaint_colorkey; - Bool crt2; /* 0=CRT1, 1=CRT2 */ + xf86CrtcPtr desired_crtc; #ifdef USE_EXA int size; diff --git a/src/theatre.c b/src/theatre.c index 0a635fa7..a5aadfb3 100644 --- a/src/theatre.c +++ b/src/theatre.c @@ -1796,7 +1796,9 @@ void RT_SetConnector (TheatrePtr t, CARD16 wConnector, int tunerFlag) counter++; } dwTempContrast = ReadRT_fld (fld_LP_CONTRAST); - if(counter>=10000)xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "Rage Theatre: timeout waiting for line count (%ld)\n", ReadRT_fld (fld_VS_LINE_COUNT)); + if(counter>=10000)xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "Rage Theatre: timeout waiting for line count (%u)\n", + (unsigned)ReadRT_fld (fld_VS_LINE_COUNT)); WriteRT_fld (fld_LP_CONTRAST, 0x0); @@ -1851,7 +1853,9 @@ void RT_SetConnector (TheatrePtr t, CARD16 wConnector, int tunerFlag) counter++; } WriteRT_fld (fld_LP_CONTRAST, dwTempContrast); - if(counter>=10000)xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "Rage Theatre: timeout waiting for line count (%ld)\n", ReadRT_fld (fld_VS_LINE_COUNT)); + if(counter>=10000)xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "Rage Theatre: timeout waiting for line count (%u)\n", + (unsigned)ReadRT_fld (fld_VS_LINE_COUNT)); @@ -1942,7 +1946,8 @@ void DumpRageTheatreRegs(TheatrePtr t) for(i=0;i<0x900;i+=4) { RT_regr(i, &data); - xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "register 0x%04x is equal to 0x%08lx\n", i, data); + xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "register 0x%04x is equal to 0x%08x\n", i, (unsigned)data); } } @@ -2147,7 +2152,9 @@ void DumpRageTheatreRegsByName(TheatrePtr t) for(i=0; rt_reg_list[i].name!=NULL;i++){ RT_regr(rt_reg_list[i].addr, &data); - xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "register (0x%04lx) %s is equal to 0x%08lx\n", rt_reg_list[i].addr, rt_reg_list[i].name, data); + xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "register (0x%04lx) %s is equal to 0x%08x\n", + rt_reg_list[i].addr, rt_reg_list[i].name, (unsigned)data); } } diff --git a/src/theatre200.c b/src/theatre200.c index ff863959..672f01e8 100644 --- a/src/theatre200.c +++ b/src/theatre200.c @@ -1799,10 +1799,12 @@ void RT_SetConnector (TheatrePtr t, CARD16 wConnector, int tunerFlag) t->wConnector = wConnector; theatre_read(t, VIP_GPIO_CNTL, &data); - xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_CNTL: %lx\n", data); + xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_CNTL: %x\n", + (unsigned)data); theatre_read(t, VIP_GPIO_INOUT, &data); - xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_INOUT: %lx\n", data); + xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_INOUT: %x\n", + (unsigned)data); switch (wConnector) { @@ -1851,10 +1853,12 @@ void RT_SetConnector (TheatrePtr t, CARD16 wConnector, int tunerFlag) } theatre_read(t, VIP_GPIO_CNTL, &data); - xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_CNTL: %lx\n", data); + xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_CNTL: %x\n", + (unsigned)data); theatre_read(t, VIP_GPIO_INOUT, &data); - xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_INOUT: %lx\n", data); + xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_INOUT: %x\n", + (unsigned)data); dsp_configure_i2s_port(t, 0, 0, 0); @@ -2007,7 +2011,8 @@ void DumpRageTheatreRegs(TheatrePtr t) for(i=0;i<0x900;i+=4) { RT_regr(i, &data); - xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "register 0x%04x is equal to 0x%08lx\n", i, data); + xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "register 0x%04x is equal to 0x%08x\n", i, (unsigned)data); } } @@ -2212,7 +2217,9 @@ void DumpRageTheatreRegsByName(TheatrePtr t) for(i=0; rt_reg_list[i].name!=NULL;i++){ RT_regr(rt_reg_list[i].addr, &data); - xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "register (0x%04lx) %s is equal to 0x%08lx\n", rt_reg_list[i].addr, rt_reg_list[i].name, data); + xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "register (0x%04lx) %s is equal to 0x%08x\n", + rt_reg_list[i].addr, rt_reg_list[i].name, (unsigned)data); } } diff --git a/src/theatre_detect.c b/src/theatre_detect.c index e7548327..87709119 100644 --- a/src/theatre_detect.c +++ b/src/theatre_detect.c @@ -67,7 +67,7 @@ static Bool theatre_write(TheatrePtr t,CARD32 reg, CARD32 data) TheatrePtr DetectTheatre(GENERIC_BUS_Ptr b) { TheatrePtr t; - CARD32 i; + int i; CARD32 val; char s[20]; @@ -88,7 +88,9 @@ TheatrePtr DetectTheatre(GENERIC_BUS_Ptr b) { if(b->read(b, ((i & 0x03)<<14) | VIP_VIP_VENDOR_DEVICE_ID, 4, (CARD8 *)&val)) { - if(val)xf86DrvMsg(b->scrnIndex, X_INFO, "Device %ld on VIP bus ids as 0x%08lx\n",i,val); + if(val)xf86DrvMsg(b->scrnIndex, X_INFO, + "Device %d on VIP bus ids as 0x%08x\n", i, + (unsigned)val); if(t->theatre_num>=0)continue; /* already found one instance */ switch(val){ case RT100_ATI_ID: @@ -101,10 +103,12 @@ TheatrePtr DetectTheatre(GENERIC_BUS_Ptr b) break; } } else { - xf86DrvMsg(b->scrnIndex, X_INFO, "No response from device %ld on VIP bus\n",i); + xf86DrvMsg(b->scrnIndex, X_INFO, "No response from device %d on VIP bus\n",i); } } - if(t->theatre_num>=0)xf86DrvMsg(b->scrnIndex, X_INFO, "Detected Rage Theatre as device %d on VIP bus with id 0x%08lx\n",t->theatre_num,t->theatre_id); + if(t->theatre_num>=0)xf86DrvMsg(b->scrnIndex, X_INFO, + "Detected Rage Theatre as device %d on VIP bus with id 0x%08x\n", + t->theatre_num, (unsigned)t->theatre_id); if(t->theatre_num < 0) { @@ -113,7 +117,8 @@ TheatrePtr DetectTheatre(GENERIC_BUS_Ptr b) } RT_regr(VIP_VIP_REVISION_ID, &val); - xf86DrvMsg(b->scrnIndex, X_INFO, "Detected Rage Theatre revision %8.8lX\n", val); + xf86DrvMsg(b->scrnIndex, X_INFO, "Detected Rage Theatre revision %8.8X\n", + (unsigned)val); #if 0 DumpRageTheatreRegsByName(t); |