diff options
Diffstat (limited to 'src')
80 files changed, 9323 insertions, 3877 deletions
@@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ati.c,v 1.21 2003/01/01 19:16:30 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ati.c,v 1.23 2003/04/25 14:37:35 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -41,7 +41,7 @@ * Mark Vojkovich, Huw D M Davies, Andrew C Aitchison, Ani Joshi, * Kostas Gewrgiou, Jakub Jelinek, David S. Miller, A E Lawrence, * Linus Torvalds, William Blew, Ignacio Garcia Etxebarria, Patrick Chase, - * Vladimir Dergachev + * Vladimir Dergachev, Egbert Eich, Mike A. Harris * * ... and, many, many others from around the world. * diff --git a/src/atiaccel.c b/src/atiaccel.c index 70b7e355..626cb34e 100644 --- a/src/atiaccel.c +++ b/src/atiaccel.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiaccel.c,v 1.11 2003/01/01 19:16:30 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiaccel.c,v 1.13 2003/04/24 21:19:22 tsi Exp $ */ /* * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -23,7 +23,7 @@ #include "atiaccel.h" #include "atiadapter.h" -#include "atimach64.h" +#include "atimach64accel.h" #include "atistruct.h" /* @@ -65,6 +65,11 @@ ATIInitializeAcceleration #endif /* AVOID_CPIO */ { + /* + * Note: If PixelArea exceeds the engine's maximum, the excess is + * never used, even though it would be useful for such things + * as XVideo buffers. + */ maxPixelArea = maxScanlines * pScreenInfo->displayWidth; PixelArea = pScreenInfo->videoRam * 1024 * 8 / pATI->bitsPerPixel; if (PixelArea > maxPixelArea) @@ -79,3 +84,50 @@ ATIInitializeAcceleration pATI->pXAAInfo = NULL; return FALSE; } + +FBLinearPtr +ATIResizeOffscreenLinear +( + ScreenPtr pScreen, + FBLinearPtr pLinear, + int Size +) +{ + if (Size <= 0) + { + xf86FreeOffscreenLinear(pLinear); + return NULL; + } + + if (pLinear) + { + if ((pLinear->size >= Size) || + xf86ResizeOffscreenLinear(pLinear, Size)) + { + pLinear->MoveLinearCallback = NULL; + pLinear->RemoveLinearCallback = NULL; + return pLinear; + } + + xf86FreeOffscreenLinear(pLinear); + } + + pLinear = xf86AllocateOffscreenLinear(pScreen, Size, 16, NULL, NULL, NULL); + + if (!pLinear) + { + int maxSize; + + xf86QueryLargestOffscreenLinear(pScreen, &maxSize, 16, + PRIORITY_EXTREME); + + if (maxSize < Size) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + pLinear = + xf86AllocateOffscreenLinear(pScreen, Size, 16, NULL, NULL, NULL); + } + + return pLinear; +} diff --git a/src/atiaccel.h b/src/atiaccel.h index df59ab0a..74cbdecd 100644 --- a/src/atiaccel.h +++ b/src/atiaccel.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiaccel.h,v 1.4 2003/01/01 19:16:30 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiaccel.h,v 1.5 2003/04/23 21:51:27 tsi Exp $ */ /* * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -28,9 +28,14 @@ #include "atiproto.h" #include "xf86str.h" +#include "xf86fbman.h" -extern Bool ATIInitializeAcceleration FunctionPrototype((ScreenPtr, - ScrnInfoPtr, - ATIPtr)); +extern Bool ATIInitializeAcceleration FunctionPrototype((ScreenPtr, + ScrnInfoPtr, + ATIPtr)); + +extern FBLinearPtr ATIResizeOffscreenLinear FunctionPrototype((ScreenPtr, + FBLinearPtr, + int)); #endif /* ___ATIACCEL_H___ */ diff --git a/src/atiadjust.c b/src/atiadjust.c index df2ac649..3db016d5 100644 --- a/src/atiadjust.c +++ b/src/atiadjust.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiadjust.c,v 1.14 2003/01/01 19:16:30 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiadjust.c,v 1.15 2003/04/23 21:51:27 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -38,7 +38,7 @@ */ /* - * ATIAjustPreInit -- + * ATIAjustPreInit -- * * This function calculates values needed to speed up the setting of the * display start address. @@ -90,11 +90,17 @@ ATIAdjustPreInit pATI->AdjustMaxBase <<= 1; } else if (!pATI->CPIO_VGAWonder) + { pATI->AdjustMaxBase = 0xFFFFU << 3; + } else if (pATI->Chip <= ATI_CHIP_28800_6) + { pATI->AdjustMaxBase = 0x03FFFFU << 3; + } else /* Mach32 & Mach64 */ + { pATI->AdjustMaxBase = 0x0FFFFFU << 3; + } break; #endif /* AVOID_CPIO */ diff --git a/src/atiaudio.c b/src/atiaudio.c new file mode 100644 index 00000000..ada83301 --- /dev/null +++ b/src/atiaudio.c @@ -0,0 +1,47 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiaudio.c,v 1.1 2003/07/24 22:08:27 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#include "atiaudio.h" + +/* + * Audio chip definitions. + */ +const char *ATIAudioNames[] = +{ + "Philips TEA5582", + "Mono with audio mux", + "Philips TDA9850", + "Sony CXA2020S", + "ITT MSP3410D", + "Crystal CS4236B", + "Philips TDA9851", + "ITT MSP3415", + "ITT MSP3430", + "Unknown type (9)", + "Unknown type (10)", + "Unknown type (11)", + "Unknown type (12)", + "Unknown type (13)", + "Unknown type (14)", + "No audio" +}; diff --git a/src/atiaudio.h b/src/atiaudio.h new file mode 100644 index 00000000..19080d2b --- /dev/null +++ b/src/atiaudio.h @@ -0,0 +1,52 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiaudio.h,v 1.1 2003/07/24 22:08:27 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#ifndef ___ATIAUDIO_H___ +#define ___ATIAUDIO_H___ 1 + +/* + * Audio chip definitions. + */ +typedef enum +{ + ATI_AUDIO_TEA5582, + ATI_AUDIO_MONO, + ATI_AUDIO_TDA9850, + ATI_AUDIO_CXA2020S, + ATI_AUDIO_MSP3410D, + ATI_AUDIO_CS4236B, + ATI_AUDIO_TDA9851, + ATI_AUDIO_MSP3415, + ATI_AUDIO_MSP3430, + ATI_AUDIO_9, + ATI_AUDIO_10, + ATI_AUDIO_11, + ATI_AUDIO_12, + ATI_AUDIO_13, + ATI_AUDIO_14, + ATI_AUDIO_NONE +} ATIAudioType; + +extern const char *ATIAudioNames[]; + +#endif /* ___ATIAUDIO_H___ */ diff --git a/src/atichip.c b/src/atichip.c index c27ca1f4..3c2b094a 100644 --- a/src/atichip.c +++ b/src/atichip.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.c,v 1.33 2003/02/19 15:07:46 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.c,v 1.37 2003/10/07 22:47:11 martin Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -84,15 +84,24 @@ const char *ATIChipNames[] = "ATI Rage 128 Mobility M3", "ATI Rage 128 Mobility M4", "ATI unknown Rage 128" - "ATI Radeon", - "ATI Radeon VE", + "ATI Radeon 7200", + "ATI Radeon 7000 (VE)", "ATI Radeon Mobility M6", - "ATI Radeon Mobility M7", - "ATI Radeon 8500", + "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 9700", + "ATI Radeon 9000 IGP", + "ATI Radeon 9200", + "ATI Radeon Mobility M9+", + "ATI Radeon 9700/9500", + "ATI Radeon 9600", + "ATI Radeon 9800", + "ATI Radeon 9800XT", "ATI Rage HDTV" }; @@ -629,6 +638,18 @@ ATIChipID 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; @@ -653,18 +674,29 @@ ATIChipID case NewChipID('Q', 'X'): return ATI_CHIP_RV200; - case NewChipID('I', 'd'): - case NewChipID('I', 'e'): case NewChipID('I', 'f'): case NewChipID('I', 'g'): return ATI_CHIP_RV250; case NewChipID('L', 'd'): - case NewChipID('L', 'e'): 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('Y', '\''): + case NewChipID('Y', 'a'): + case NewChipID('Y', 'b'): + case NewChipID('Y', 'd'): + 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'): @@ -675,6 +707,32 @@ ATIChipID 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', '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('H', 'D'): return ATI_CHIP_HDTV; diff --git a/src/atichip.h b/src/atichip.h index ce911c56..4cc30a0c 100644 --- a/src/atichip.h +++ b/src/atichip.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.h,v 1.22 2003/01/01 19:16:30 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.h,v 1.25 2003/10/07 22:47:11 martin Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -89,12 +89,21 @@ typedef enum 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_RV200, /* RV200 */ ATI_CHIP_RV250, /* RV250 */ ATI_CHIP_RADEONMOBILITY9, /* Radeon M9 */ + ATI_CHIP_RS300, /* Radoen 9000 IGP */ + ATI_CHIP_RV280, /* RV250 */ + ATI_CHIP_RADEONMOBILITY9PLUS, /* Radeon M9+ */ ATI_CHIP_R300, /* R300 */ + ATI_CHIP_RV350, /* RV350 */ + ATI_CHIP_R350, /* R350 */ + ATI_CHIP_R360, /* R360 */ ATI_CHIP_HDTV /* HDTV */ } ATIChipType; diff --git a/src/aticlock.c b/src/aticlock.c index 0fc3d6b3..e1201cb3 100644 --- a/src/aticlock.c +++ b/src/aticlock.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticlock.c,v 1.20 2003/01/01 19:16:31 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticlock.c,v 1.21 2003/04/23 21:51:27 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -499,7 +499,9 @@ ATIMatchClockLine continue; } else if (Gap > MaximumGap) + { MaximumGap = Gap; + } ClockCount++; } @@ -562,13 +564,17 @@ ATIClockPreInit /* Check for those that are not (yet) handled */ if ((pATI->ProgrammableClock == ATI_CLOCK_UNKNOWN) || (pATI->ProgrammableClock > NumberOf(ATIClockDescriptors))) + { xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0, "Unknown programmable clock generator type (0x%02X)" " detected.\n", pATI->ProgrammableClock); + } else if (pATI->ClockDescriptor.MaxN <= 0) + { xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0, "Unsupported programmable clock generator detected: %s.\n", pATI->ClockDescriptor.ClockName); + } else { /* @@ -624,11 +630,13 @@ ATIClockPreInit pScreenInfo->clock[1] = 28322; } else if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL) - /* - * The integrated PLL generates clocks as if the reference - * frequency were doubled. - */ + { + /* + * The integrated PLL generates clocks as if the reference + * frequency were doubled. + */ pATI->ReferenceNumerator <<= 1; + } return; /* ... to ATIPreInit() */ } @@ -759,11 +767,13 @@ ProbeClocks: for (ClockIndex = 0; ClockIndex < NumberOfUndividedClocks; ClockIndex++) + { if (CalibrationClockValue < pATI->BIOSClocks[ClockIndex]) { CalibrationClockNumber = ClockIndex; CalibrationClockValue = pATI->BIOSClocks[ClockIndex]; } + } CalibrationClockNumber = MapClockIndex(pATI->NewHW.ClockUnmap, CalibrationClockNumber); CalibrationClockValue *= 10; @@ -831,8 +841,10 @@ ProbeClocks: /* Set high-order bits */ if (pATI->Chip <= ATI_CHIP_18800) + { ATIModifyExtReg(pATI, 0xB2U, -1, 0xBFU, Index << 4); + } else { ATIModifyExtReg(pATI, 0xBEU, -1, 0xEFU, @@ -1061,7 +1073,9 @@ ProbeClocks: */ if (ATIMatchClockLine(pScreenInfo, pATI, InvalidClockLine, NumberOfClocks, -1, 0)) + { pATI->OptionProbeClocks = TRUE; + } else #ifndef AVOID_CPIO @@ -1124,17 +1138,23 @@ ProbeClocks: } if (pATI->ProgrammableClock != ATI_CLOCK_FIXED) + { pATI->ProgrammableClock = ATI_CLOCK_FIXED; + } else if (pATI->Clock == ATI_CLOCK_NONE) + { xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0, "Unknown clock generator detected.\n"); + } else #ifndef AVOID_CPIO if (pATI->Clock == ATI_CLOCK_CRYSTALS) + { xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "This adapter uses crystals to generate clock frequencies.\n"); + } else if (pATI->Clock != ATI_CLOCK_VGA) #endif /* AVOID_CPIO */ @@ -1403,8 +1423,10 @@ ATIClockCalculate { /* Set ATI clock select bits */ if (pATI->Chip <= ATI_CHIP_18800) + { pATIHW->b2 = (pATIHW->b2 & 0xBFU) | ((ClockSelect << 4) & 0x40U); + } else { pATIHW->be = (pATIHW->be & 0xEFU) | @@ -1516,31 +1538,31 @@ ATIClockSet case ATI_CLOCK_INTERNAL: /* Reset VCLK generator */ - ATIPutMach64PLLReg(PLL_VCLK_CNTL, pATIHW->pll_vclk_cntl); + ATIMach64PutPLLReg(PLL_VCLK_CNTL, pATIHW->pll_vclk_cntl); /* Set post-divider */ tmp2 = pATIHW->clock << 1; - tmp = ATIGetMach64PLLReg(PLL_VCLK_POST_DIV); + tmp = ATIMach64GetPLLReg(PLL_VCLK_POST_DIV); tmp &= ~(0x03U << tmp2); tmp |= SetBits(D, 0x03U) << tmp2; - ATIPutMach64PLLReg(PLL_VCLK_POST_DIV, tmp); + ATIMach64PutPLLReg(PLL_VCLK_POST_DIV, tmp); /* Set extended post-divider */ - tmp = ATIGetMach64PLLReg(PLL_XCLK_CNTL); + tmp = ATIMach64GetPLLReg(PLL_XCLK_CNTL); tmp &= ~(SetBits(1, PLL_VCLK0_XDIV) << pATIHW->clock); tmp |= SetBits(D >> 2, PLL_VCLK0_XDIV) << pATIHW->clock; - ATIPutMach64PLLReg(PLL_XCLK_CNTL, tmp); + ATIMach64PutPLLReg(PLL_XCLK_CNTL, tmp); /* Set feedback divider */ tmp = PLL_VCLK0_FB_DIV + pATIHW->clock; - ATIPutMach64PLLReg(tmp, SetBits(N, 0xFFU)); + ATIMach64PutPLLReg(tmp, SetBits(N, 0xFFU)); /* End VCLK generator reset */ - ATIPutMach64PLLReg(PLL_VCLK_CNTL, + ATIMach64PutPLLReg(PLL_VCLK_CNTL, pATIHW->pll_vclk_cntl & ~PLL_VCLK_RESET); /* Reset write bit */ - ATIAccessMach64PLLReg(pATI, 0, FALSE); + ATIMach64AccessPLLReg(pATI, 0, FALSE); break; case ATI_CLOCK_ATT20C408: diff --git a/src/aticonfig.c b/src/aticonfig.c index b0aa2beb..3cad3e2d 100644 --- a/src/aticonfig.c +++ b/src/aticonfig.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticonfig.c,v 1.12 2003/01/01 19:16:31 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticonfig.c,v 1.14 2003/04/30 21:43:31 tsi Exp $*/ /* * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -37,7 +37,7 @@ typedef enum ATI_OPTION_CRT_SCREEN, /* Legacy negation of "PanelDisplay" */ ATI_OPTION_DEVEL, /* Intentionally undocumented */ ATI_OPTION_BLEND, /* Force horizontal blending of small modes */ - ATI_OPTION_SYNC /* Use XF86Config panel mode porches */ + ATI_OPTION_LCDSYNC /* Use XF86Config panel mode porches */ } ATIPrivateOptionType; /* @@ -71,7 +71,7 @@ ATIProcessOptions FALSE }, { /* ON: Use XF86Config porch timings */ - ATI_OPTION_SYNC, /* OFF: Use porches from mode on entry */ + ATI_OPTION_LCDSYNC, /* OFF: Use porches from mode on entry */ "lcdsync", OPTV_BOOLEAN, {0, }, @@ -95,26 +95,27 @@ ATIProcessOptions (void)memcpy(PublicOption, ATIPublicOptions, ATIPublicOptionSize); -# define Accel PublicOption[ATI_OPTION_ACCEL].value.bool -# define Blend PrivateOption[ATI_OPTION_BLEND].value.bool -# define CRTDisplay PublicOption[ATI_OPTION_CRT_DISPLAY].value.bool -# define CRTScreen PrivateOption[ATI_OPTION_CRT_SCREEN].value.bool -# define CSync PublicOption[ATI_OPTION_CSYNC].value.bool -# define Devel PrivateOption[ATI_OPTION_DEVEL].value.bool -# define HWCursor PublicOption[ATI_OPTION_HWCURSOR].value.bool +# define Accel PublicOption[ATI_OPTION_ACCEL].value.bool +# define Blend PrivateOption[ATI_OPTION_BLEND].value.bool +# define CRTDisplay PublicOption[ATI_OPTION_CRT_DISPLAY].value.bool +# define CRTScreen PrivateOption[ATI_OPTION_CRT_SCREEN].value.bool +# define CSync PublicOption[ATI_OPTION_CSYNC].value.bool +# define Devel PrivateOption[ATI_OPTION_DEVEL].value.bool +# define HWCursor PublicOption[ATI_OPTION_HWCURSOR].value.bool #ifndef AVOID_CPIO -# define Linear PublicOption[ATI_OPTION_LINEAR].value.bool +# define Linear PublicOption[ATI_OPTION_LINEAR].value.bool #endif /* AVOID_CPIO */ -# define CacheMMIO PublicOption[ATI_OPTION_MMIO_CACHE].value.bool -# define PanelDisplay PublicOption[ATI_OPTION_PANEL_DISPLAY].value.bool -# define ProbeClocks PublicOption[ATI_OPTION_PROBE_CLOCKS].value.bool -# define ShadowFB PublicOption[ATI_OPTION_SHADOW_FB].value.bool -# define SWCursor PublicOption[ATI_OPTION_SWCURSOR].value.bool -# define Sync PrivateOption[ATI_OPTION_SYNC].value.bool +# define CacheMMIO PublicOption[ATI_OPTION_MMIO_CACHE].value.bool +# define TestCacheMMIO PublicOption[ATI_OPTION_TEST_MMIO_CACHE].value.bool +# define PanelDisplay PublicOption[ATI_OPTION_PANEL_DISPLAY].value.bool +# define ProbeClocks PublicOption[ATI_OPTION_PROBE_CLOCKS].value.bool +# define ShadowFB PublicOption[ATI_OPTION_SHADOW_FB].value.bool +# define SWCursor PublicOption[ATI_OPTION_SWCURSOR].value.bool +# define LCDSync PrivateOption[ATI_OPTION_LCDSYNC].value.bool # define ReferenceClock \ PublicOption[ATI_OPTION_REFERENCE_CLOCK].value.freq.freq @@ -187,9 +188,10 @@ ATIProcessOptions #endif /* AVOID_CPIO */ pATI->OptionMMIOCache = CacheMMIO; + pATI->OptionTestMMIOCache = TestCacheMMIO; pATI->OptionProbeClocks = ProbeClocks; pATI->OptionShadowFB = ShadowFB; - pATI->OptionSync = Sync; + pATI->OptionLCDSync = LCDSync; /* "CRTScreen" is now "NoPanelDisplay" */ if ((PanelDisplay != CRTScreen) || diff --git a/src/aticonsole.c b/src/aticonsole.c index cdd91f4a..5fe91021 100644 --- a/src/aticonsole.c +++ b/src/aticonsole.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticonsole.c,v 1.20 2003/01/01 19:16:31 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticonsole.c,v 1.22 2003/11/13 18:42:47 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -24,6 +24,7 @@ #include "atiadapter.h" #include "aticonsole.h" #include "aticrtc.h" +#include "atii2c.h" #include "atilock.h" #include "atimach64.h" #include "atimode.h" @@ -335,6 +336,9 @@ ATIFreeScreen ScrnInfoPtr pScreenInfo = xf86Screens[iScreen]; ATIPtr pATI = ATIPTR(pScreenInfo); + if (pATI->Closeable || (serverGeneration > 1)) + ATII2CFreeScreen(iScreen); + if (pATI->Closeable) (void)(*pScreen->CloseScreen)(iScreen, pScreen); diff --git a/src/aticursor.c b/src/aticursor.c index 627b05ef..a4837e47 100644 --- a/src/aticursor.c +++ b/src/aticursor.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticursor.c,v 1.3 2003/01/01 19:16:31 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/aticursor.c,v 1.4 2003/04/23 21:51:27 tsi Exp $ */ /* * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -23,7 +23,7 @@ #include "atiadapter.h" #include "aticursor.h" -#include "atimach64.h" +#include "atimach64cursor.h" #include "atistruct.h" #include "xf86.h" diff --git a/src/atidecoder.c b/src/atidecoder.c new file mode 100644 index 00000000..aee37416 --- /dev/null +++ b/src/atidecoder.c @@ -0,0 +1,47 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidecoder.c,v 1.1 2003/07/24 22:08:28 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#include "atidecoder.h" + +/* + * Video decoder definitions. + */ +const char *ATIDecoderNames[] = +{ + "No decoder", + "BrookTree BT819", + "Brooktree BT829", + "Brooktree BT829A", + "Philips SA7111", + "Philips SA7112", + "ATI Rage Theater", + "Unknown type (7)", + "Unknown type (8)", + "Unknown type (9)", + "Unknown type (10)", + "Unknown type (11)", + "Unknown type (12)", + "Unknown type (13)", + "Unknown type (14)", + "Unknown type (15)" +}; diff --git a/src/atidecoder.h b/src/atidecoder.h new file mode 100644 index 00000000..e88b89f7 --- /dev/null +++ b/src/atidecoder.h @@ -0,0 +1,52 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidecoder.h,v 1.1 2003/07/24 22:08:28 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#ifndef ___ATIDECODER_H___ +#define ___ATIDECODER_H___ 1 + +/* + * Video decoder definitions. + */ +typedef enum +{ + ATI_DECODER_NONE, + ATI_DECODER_BT819, + ATI_DECODER_BT829, + ATI_DECODER_BT829A, + ATI_DECODER_SA7111, + ATI_DECODER_SA7112, + ATI_DECODER_THEATER, + ATI_DECODER_7, + ATI_DECODER_8, + ATI_DECODER_9, + ATI_DECODER_10, + ATI_DECODER_11, + ATI_DECODER_12, + ATI_DECODER_13, + ATI_DECODER_14, + ATI_DECODER_15 +} ATIDecoderType; + +extern const char *ATIDecoderNames[]; + +#endif /* ___ATIDECODER_H___ */ diff --git a/src/atidga.c b/src/atidga.c index beca2d8e..9273f03a 100644 --- a/src/atidga.c +++ b/src/atidga.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidga.c,v 1.9 2003/01/01 19:16:31 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidga.c,v 1.10 2003/04/23 21:51:27 tsi Exp $ */ /* * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -387,8 +387,8 @@ ATIDGAAddModes Bool ATIDGAInit ( - ScrnInfoPtr pScreenInfo, ScreenPtr pScreen, + ScrnInfoPtr pScreenInfo, ATIPtr pATI ) { diff --git a/src/atidga.h b/src/atidga.h index 1011a89b..96664d99 100644 --- a/src/atidga.h +++ b/src/atidga.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidga.h,v 1.6 2003/01/01 19:16:31 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidga.h,v 1.7 2003/04/23 21:51:28 tsi Exp $ */ /* * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -31,7 +31,7 @@ #include "xf86str.h" -extern Bool ATIDGAInit FunctionPrototype((ScrnInfoPtr, ScreenPtr, ATIPtr)); +extern Bool ATIDGAInit FunctionPrototype((ScreenPtr, ScrnInfoPtr, ATIPtr)); #endif /* AVOID_DGA */ diff --git a/src/atidsp.c b/src/atidsp.c index 7ca23299..103d3dd3 100644 --- a/src/atidsp.c +++ b/src/atidsp.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidsp.c,v 1.19 2003/01/01 19:16:31 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidsp.c,v 1.21 2003/09/24 02:43:18 dawes Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -51,7 +51,7 @@ ATIDSPPreInit pATI->ClockDescriptor.NumD = 8; /* Retrieve XCLK settings */ - IOValue = ATIGetMach64PLLReg(PLL_XCLK_CNTL); + IOValue = ATIMach64GetPLLReg(PLL_XCLK_CNTL); pATI->XCLKPostDivider = GetBits(IOValue, PLL_XCLK_SRC_SEL); pATI->XCLKReferenceDivider = 1; switch (pATI->XCLKPostDivider) @@ -71,10 +71,10 @@ ATIDSPPreInit } pATI->XCLKPostDivider -= GetBits(IOValue, PLL_MFB_TIMES_4_2B); - pATI->XCLKFeedbackDivider = ATIGetMach64PLLReg(PLL_MCLK_FB_DIV); + pATI->XCLKFeedbackDivider = ATIMach64GetPLLReg(PLL_MCLK_FB_DIV); xf86DrvMsgVerb(iScreen, X_INFO, 2, - "Engine XCLK %.3f MHz; Refresh rate code %d.\n", + "Engine XCLK %.3f MHz; Refresh rate code %ld.\n", ATIDivide(pATI->XCLKFeedbackDivider * pATI->ReferenceNumerator, pATI->XCLKReferenceDivider * pATI->ClockDescriptor.MaxM * pATI->ReferenceDenominator, 1 - pATI->XCLKPostDivider, 0) / @@ -100,7 +100,9 @@ ATIDSPPreInit { case MEM_264_DRAM: if (pATI->VideoRAM <= 1024) + { pATI->DisplayLoopLatency = 10; + } else { pATI->DisplayLoopLatency = 8; @@ -111,7 +113,9 @@ ATIDSPPreInit case MEM_264_EDO: case MEM_264_PSEUDO_EDO: if (pATI->VideoRAM <= 1024) + { pATI->DisplayLoopLatency = 9; + } else { pATI->DisplayLoopLatency = 8; @@ -121,7 +125,9 @@ ATIDSPPreInit case MEM_264_SDRAM: if (pATI->VideoRAM <= 1024) + { pATI->DisplayLoopLatency = 11; + } else { pATI->DisplayLoopLatency = 10; diff --git a/src/atii2c.c b/src/atii2c.c new file mode 100644 index 00000000..95296537 --- /dev/null +++ b/src/atii2c.c @@ -0,0 +1,387 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atii2c.c,v 1.3 2003/11/10 18:41:20 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#include "atiadapter.h" +#include "atii2c.h" +#include "atiload.h" +#include "atimach64i2c.h" +#include "atistruct.h" + +#include "xf86.h" + +/* This is derived from GATOS code, with a liberal sprinkling of bug fixes */ + +/* + * Some local macros for use by the mid-level I2C functions. + */ + +#define ATII2CDelay \ + (*pI2CBus->I2CUDelay)(pI2CBus, pI2CBus->HoldTime) + + +#define ATII2CSCLDirOff \ + if (pATII2C->SCLDir != 0) \ + (*pATII2C->I2CSetBits)(pATII2C, pATI, \ + pATII2C->I2CCur & ~pATII2C->SCLDir) + +#define ATII2CSCLDirOn \ + if (pATII2C->SCLDir != 0) \ + (*pATII2C->I2CSetBits)(pATII2C, pATI, \ + pATII2C->I2CCur | pATII2C->SCLDir) + +#define ATII2CSDADirOff \ + if (pATII2C->SDADir != 0) \ + (*pATII2C->I2CSetBits)(pATII2C, pATI, \ + pATII2C->I2CCur & ~pATII2C->SDADir) + +#define ATII2CSDADirOn \ + if (pATII2C->SDADir != 0) \ + (*pATII2C->I2CSetBits)(pATII2C, pATI, \ + pATII2C->I2CCur | pATII2C->SDADir) + + +#define ATII2CSCLBitGet \ + ((*pATII2C->I2CGetBits)(pATI) & pATII2C->SCLGet) + +#define ATII2CSCLBitOff \ + do \ + { \ + (*pATII2C->I2CSetBits)(pATII2C, pATI, \ + pATII2C->I2CCur & ~pATII2C->SCLSet); \ + ATII2CDelay; \ + } while (0) + +#define ATII2CSCLBitOn \ + do \ + { \ + (*pATII2C->I2CSetBits)(pATII2C, pATI, \ + pATII2C->I2CCur | pATII2C->SCLSet); \ + do /* Wait until all devices have released SCL */ \ + { \ + ATII2CDelay; \ + } while (ATII2CSCLBitGet == 0); \ + } while (0) + + +#define ATII2CSDABitGet \ + ((*pATII2C->I2CGetBits)(pATI) & pATII2C->SDAGet) + +#define ATII2CSDABitOff \ + do \ + { \ + (*pATII2C->I2CSetBits)(pATII2C, pATI, \ + pATII2C->I2CCur & ~pATII2C->SDASet); \ + ATII2CDelay; \ + } while (0) + +#define ATII2CSDABitOn \ + do \ + { \ + (*pATII2C->I2CSetBits)(pATII2C, pATI, \ + pATII2C->I2CCur | pATII2C->SDASet); \ + ATII2CDelay; \ + } while (0) + +#define ATII2CSDABitSet(_flag) \ + do \ + { \ + if (_flag) \ + ATII2CSDABitOn; \ + else \ + ATII2CSDABitOff; \ + } while (0) + + +/* + * ATII2CAddress -- + * + * This function puts a Start bit and an 8-bit address on the I2C bus. + */ +static Bool +ATII2CAddress +( + I2CDevPtr pI2CDev, + I2CSlaveAddr Address +) +{ + I2CBusPtr pI2CBus = pI2CDev->pI2CBus; + ATII2CPtr pATII2C = pI2CBus->DriverPrivate.ptr; + ATIPtr pATI = pATII2C->pATI; + + /* + * Set I2C line directions to out-bound. SCL will remain out-bound until + * next I2C Stop. + */ + ATII2CSCLDirOn; + ATII2CSDADirOn; + + /* + * Send Start bit. This is a pull-down of the data line while the clock + * line is pulled up. + */ + ATII2CSDABitOn; + ATII2CSCLBitOn; + ATII2CSDABitOff; + ATII2CSCLBitOff; + + /* Send low byte of device address */ + if ((*pI2CBus->I2CPutByte)(pI2CDev, (I2CByte)Address)) + { + /* Send top byte of address, if appropriate */ + if (((Address & 0x00F8U) != 0x00F0U) && + ((Address & 0x00FEU) != 0x0000U)) + return TRUE; + + if ((*pI2CBus->I2CPutByte)(pI2CDev, (I2CByte)(Address >> 8))) + return TRUE; + } + + /* Kill I2C transaction on failure */ + (*pI2CBus->I2CStop)(pI2CDev); + return FALSE; +} + +/* + * ATII2CStop -- + * + * This function puts a stop signal on the I2C bus. + */ +static void +ATII2CStop +( + I2CDevPtr pI2CDev +) +{ + I2CBusPtr pI2CBus = pI2CDev->pI2CBus; + ATII2CPtr pATII2C = pI2CBus->DriverPrivate.ptr; + ATIPtr pATI = pATII2C->pATI; + + ATII2CSDADirOn; /* Set data line direction to out-bound */ + + /* + * Send Stop bit. This is a pull-up of the data line while the clock line + * is pulled up. + */ + ATII2CSDABitOff; + ATII2CSCLBitOn; + ATII2CSDABitOn; + ATII2CSCLBitOff; + + /* Reset I2C line directions to in-bound */ + ATII2CSCLDirOff; + ATII2CSDADirOff; +} + +/* + * ATII2CPutByte -- + * + * This function puts an 8-bit value on the I2C bus, starting with its MSB. + */ +static Bool +ATII2CPutByte +( + I2CDevPtr pI2CDev, + I2CByte Data +) +{ + I2CBusPtr pI2CBus = pI2CDev->pI2CBus; + ATII2CPtr pATII2C = pI2CBus->DriverPrivate.ptr; + ATIPtr pATI = pATII2C->pATI; + int i; + Bool Result; + + ATII2CSDADirOn; /* Set data line direction to out-bound */ + + /* Send data byte */ + for (i = 0; i < 8; i++) + { + ATII2CSDABitSet(Data & 0x80U); + ATII2CSCLBitOn; + ATII2CSCLBitOff; + + Data <<= 1; + } + + ATII2CSDABitOn; /* Release data line */ + + ATII2CSDADirOff; /* Set data line direction to in-bound */ + + ATII2CSCLBitOn; /* Start bit-read clock pulse */ + + /* Get [N]ACK bit */ + if (ATII2CSDABitGet) + Result = FALSE; + else + Result = TRUE; + + ATII2CSCLBitOff; /* End clock pulse */ + + return Result; +} + +/* + * ATII2CGetByte -- + * + * This function retrieves an 8-bit value from the I2C bus. + */ +static Bool +ATII2CGetByte +( + I2CDevPtr pI2CDev, + I2CByte *pData, + Bool Last +) +{ + I2CBusPtr pI2CBus = pI2CDev->pI2CBus; + ATII2CPtr pATII2C = pI2CBus->DriverPrivate.ptr; + ATIPtr pATI = pATII2C->pATI; + unsigned long Value = 1; + + do + { + ATII2CSCLBitOn; /* Start bit-read clock pulse */ + + /* Accumulate bit into byte value */ + Value <<= 1; + if (ATII2CSDABitGet) + Value++; + + ATII2CSCLBitOff; /* End clock pulse */ + } while (Value <= (unsigned long)((I2CByte)(-1))); + + *pData = (I2CByte)Value; + + ATII2CSDADirOn; /* Set data line direction to out-bound */ + + /* Send [N]ACK bit */ + ATII2CSDABitSet(Last); + ATII2CSCLBitOn; + ATII2CSCLBitOff; + + if (!Last) + ATII2CSDABitOn; /* Release data line */ + + ATII2CSDADirOff; /* Set data line direction to in-bound */ + + return TRUE; +} + +/* + * ATICreateI2CBusRec -- + * + * This function is called to initialise an I2CBusRec. + */ +I2CBusPtr +ATICreateI2CBusRec +( + int iScreen, + ATIPtr pATI, + char *BusName +) +{ + I2CBusPtr pI2CBus; + ATII2CPtr pATII2C = xnfcalloc(1, SizeOf(ATII2CRec)); + + if (!(pI2CBus = xf86CreateI2CBusRec())) + { + xf86DrvMsg(iScreen, X_WARNING, "Unable to allocate I2C Bus record.\n"); + xfree(pATII2C); + return NULL; + } + + /* Fill in generic structure fields */ + pI2CBus->BusName = BusName; + pI2CBus->scrnIndex = iScreen; + + pI2CBus->I2CAddress = ATII2CAddress; + pI2CBus->I2CStop = ATII2CStop; + pI2CBus->I2CPutByte = ATII2CPutByte; + pI2CBus->I2CGetByte = ATII2CGetByte; + + pI2CBus->DriverPrivate.ptr = pATII2C; + + pATII2C->pATI = pATI; + + if (xf86I2CBusInit(pI2CBus)) + return pI2CBus; + + xf86DrvMsg(iScreen, X_WARNING, + "I2C bus %s initialisation failure.\n", BusName); + xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE); + xfree(pATII2C); + return NULL; +} + +/* + * ATII2CPreInit -- + * + * This is called by ATIPreInit() to create I2C bus record(s) for the adapter. + */ +void +ATII2CPreInit +( + ScrnInfoPtr pScreenInfo, + ATIPtr pATI +) +{ + switch (pATI->Adapter) + { + case ATI_ADAPTER_MACH64: + if (!ATILoadModule(pScreenInfo, "i2c", ATIi2cSymbols)) + return; + + ATIMach64I2CPreInit(pScreenInfo, pATI); + break; + + default: + break; + } +} + +/* + * ATII2CFreeScreen -- + * + * This is called by ATIFreeScreen() to remove the driver's I2C interface. + */ +void +ATII2CFreeScreen +( + int iScreen +) +{ + I2CBusPtr pI2CBus, *ppI2CBus; + ATII2CPtr pATII2C; + int nI2CBus; + + nI2CBus = xf86I2CGetScreenBuses(iScreen, &ppI2CBus); + while (--nI2CBus >= 0) + { + pI2CBus = ppI2CBus[nI2CBus]; + pATII2C = pI2CBus->DriverPrivate.ptr; + + xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE); + xfree(pATII2C); + } + + xfree(ppI2CBus); +} diff --git a/src/atii2c.h b/src/atii2c.h new file mode 100644 index 00000000..ddc0d977 --- /dev/null +++ b/src/atii2c.h @@ -0,0 +1,50 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atii2c.h,v 1.1 2003/07/24 22:08:28 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#ifndef ___ATII2C_H___ +#define ___ATII2C_H___ 1 + +#include "atipriv.h" +#include "atiproto.h" + +#include "xf86str.h" + +#include "xf86i2c.h" + +typedef struct _ATII2CRec ATII2CRec, *ATII2CPtr; + +struct _ATII2CRec +{ + ATIPtr pATI; + void (*I2CSetBits) FunctionPrototype((ATII2CPtr, ATIPtr, CARD32)); + CARD32 (*I2CGetBits) FunctionPrototype((ATIPtr)); + CARD32 SCLDir, SCLGet, SCLSet; + CARD32 SDADir, SDAGet, SDASet; + CARD32 I2CCur; +}; + +extern void ATII2CPreInit FunctionPrototype((ScrnInfoPtr, ATIPtr)); +extern I2CBusPtr ATICreateI2CBusRec FunctionPrototype((int, ATIPtr, char *)); +extern void ATII2CFreeScreen FunctionPrototype((int)); + +#endif /* ___ATII2C_H___ */ diff --git a/src/atiload.c b/src/atiload.c index 83b53311..a7eebd1d 100644 --- a/src/atiload.c +++ b/src/atiload.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiload.c,v 1.12 2003/01/01 19:16:32 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiload.c,v 1.15 2003/08/29 21:07:57 tsi Exp $ */ /* * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -98,7 +98,17 @@ const char *ATIramdacSymbols[] = "xf86CreateCursorInfoRec", "xf86DestroyCursorInfoRec", "xf86InitCursor", - "xf86ForceHWCursor", + NULL +}; + +const char *ATIi2cSymbols[] = +{ + "xf86CreateI2CBusRec", + "xf86DestroyI2CBusRec", + "xf86I2CBusInit", + "xf86I2CDevInit", + "xf86I2CFindDev", + "xf86I2CGetScreenBuses", NULL }; diff --git a/src/atiload.h b/src/atiload.h index 050404e1..a695579e 100644 --- a/src/atiload.h +++ b/src/atiload.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiload.h,v 1.5 2003/01/01 19:16:32 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiload.h,v 1.6 2003/07/24 22:08:28 tsi Exp $ */ /* * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -40,7 +40,7 @@ extern const char *ATIint10Symbols[], *ATIddcSymbols[], *ATIvbeSymbols[], #endif /* AVOID_CPIO */ *ATIfbSymbols[], *ATIshadowfbSymbols[], *ATIxaaSymbols[], - *ATIramdacSymbols[]; + *ATIramdacSymbols[], *ATIi2cSymbols[]; extern pointer ATILoadModule FunctionPrototype((ScrnInfoPtr, const char *, const char **)); diff --git a/src/atilock.c b/src/atilock.c index 336696cb..b07744d4 100644 --- a/src/atilock.c +++ b/src/atilock.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atilock.c,v 1.18 2003/01/10 20:57:57 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atilock.c,v 1.19 2003/04/23 21:51:28 tsi Exp $ */ /* * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -250,20 +250,19 @@ ATIUnlock saved_lcd_gen_ctrl = inr(LCD_GEN_CTRL); /* Setup to unlock non-shadow registers */ - lcd_gen_ctrl = saved_lcd_gen_ctrl & - ~(SHADOW_EN | SHADOW_RW_EN); + lcd_gen_ctrl = saved_lcd_gen_ctrl & ~SHADOW_RW_EN; outr(LCD_GEN_CTRL, lcd_gen_ctrl); } else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ { - saved_lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL); + saved_lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); /* Setup to unlock non-shadow registers */ lcd_gen_ctrl = saved_lcd_gen_ctrl & - ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN); - ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); + ~(CRTC_RW_SELECT | SHADOW_RW_EN); + ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); } } @@ -322,14 +321,14 @@ ATIUnlock if (pATI->LCDPanelID >= 0) { /* Setup to unlock shadow registers */ - lcd_gen_ctrl |= SHADOW_EN | SHADOW_RW_EN; + lcd_gen_ctrl |= SHADOW_RW_EN; if (pATI->Chip == ATI_CHIP_264LT) outr(LCD_GEN_CTRL, lcd_gen_ctrl); else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ - ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); + ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); /* Unlock shadow registers */ ATISetVGAIOBase(pATI, inb(R_GENMO)); @@ -344,7 +343,9 @@ ATIUnlock pATI->LockData.shadow_crt11 = tmp = GetReg(CRTX(pATI->CPIO_VGABase), 0x11U); if (tmp & 0x80U) /* Unprotect CRTC[0-7] */ + { outb(CRTD(pATI->CPIO_VGABase), tmp & 0x7FU); + } else if (!tmp && pATI->LockData.crt11) { pATI->LockData.shadow_crt11 = tmp = pATI->LockData.crt11; @@ -386,12 +387,14 @@ ATIUnlock /* Restore selection */ if (pATI->Chip == ATI_CHIP_264LT) + { outr(LCD_GEN_CTRL, saved_lcd_gen_ctrl); + } else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ { - ATIPutMach64LCDReg(LCD_GEN_CNTL, saved_lcd_gen_ctrl); + ATIMach64PutLCDReg(LCD_GEN_CNTL, saved_lcd_gen_ctrl); /* Restore LCD index */ out8(LCD_INDEX, GetByte(pATI->LockData.lcd_index, 0)); @@ -436,20 +439,19 @@ ATILock saved_lcd_gen_ctrl = inr(LCD_GEN_CTRL); /* Setup to lock non-shadow registers */ - lcd_gen_ctrl = saved_lcd_gen_ctrl & - ~(SHADOW_EN | SHADOW_RW_EN); + lcd_gen_ctrl = saved_lcd_gen_ctrl & ~SHADOW_RW_EN; outr(LCD_GEN_CTRL, lcd_gen_ctrl); } else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ { - saved_lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL); + saved_lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); /* Setup to lock non-shadow registers */ lcd_gen_ctrl = saved_lcd_gen_ctrl & - ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN); - ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); + ~(CRTC_RW_SELECT | SHADOW_RW_EN); + ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); } } @@ -462,14 +464,14 @@ ATILock if (pATI->LCDPanelID >= 0) { /* Setup to lock shadow registers */ - lcd_gen_ctrl |= SHADOW_EN | SHADOW_RW_EN; + lcd_gen_ctrl |= SHADOW_RW_EN; if (pATI->Chip == ATI_CHIP_264LT) outr(LCD_GEN_CTRL, lcd_gen_ctrl); else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ - ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); + ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); /* Lock shadow registers */ ATISetVGAIOBase(pATI, inb(R_GENMO)); @@ -485,7 +487,7 @@ ATILock else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ - ATIPutMach64LCDReg(LCD_GEN_CNTL, saved_lcd_gen_ctrl); + ATIMach64PutLCDReg(LCD_GEN_CNTL, saved_lcd_gen_ctrl); } if (pATI->CPIO_VGAWonder) diff --git a/src/atimach64.c b/src/atimach64.c index 1f457e80..89ee7c96 100644 --- a/src/atimach64.c +++ b/src/atimach64.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.c,v 1.51 2003/02/24 20:46:54 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.c,v 1.52 2003/04/23 21:51:28 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -20,69 +20,22 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ -/* - * Copyright 1999-2000 Precision Insight, Inc., Cedar Park, Texas. - * 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 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 - * PRECISION INSIGHT AND/OR ITS 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. - */ #include "ati.h" #include "atibus.h" #include "atichip.h" #include "atidac.h" #include "atimach64.h" +#include "atimach64accel.h" #include "atimach64io.h" #include "atirgb514.h" -#include "miline.h" - #ifndef DPMS_SERVER # define DPMS_SERVER #endif #include "extensions/dpms.h" /* - * X-to-Mach64 mix translation table. - */ -static CARD8 ATIMach64ALU[16] = -{ - MIX_0, - MIX_AND, - MIX_SRC_AND_NOT_DST, - MIX_SRC, - MIX_NOT_SRC_AND_DST, - MIX_DST, - MIX_XOR, - MIX_OR, - MIX_NOR, - MIX_XNOR, - MIX_NOT_DST, - MIX_SRC_OR_NOT_DST, - MIX_NOT_SRC, - MIX_NOT_SRC_OR_DST, - MIX_NAND, - MIX_1 -}; - -/* * ATIMach64PreInit -- * * This function fills in the Mach64 portion of an ATIHWRec that is common to @@ -102,7 +55,9 @@ ATIMach64PreInit #ifndef AVOID_CPIO if (pATI->depth <= 4) + { pATIHW->crtc_off_pitch = SetBits(pATI->displayWidth >> 4, CRTC_PITCH); + } else #endif /* AVOID_CPIO */ @@ -170,7 +125,9 @@ ATIMach64PreInit #ifndef AVOID_CPIO if (pATI->UseSmallApertures) + { pATIHW->config_cntl |= CFG_MEM_VGA_AP_EN; + } else #endif /* AVOID_CPIO */ @@ -230,7 +187,7 @@ ATIMach64PreInit } /* Draw engine setup */ - if (pATI->OptionAccel) + if (pATI->Block0Base) { /* Ensure apertures are enabled */ outr(BUS_CNTL, pATIHW->bus_cntl); @@ -255,14 +212,14 @@ ATIMach64PreInit /* Initialise scissor, allowing for offscreen areas */ pATIHW->sc_right = (pATI->displayWidth * pATI->XModifier) - 1; - tmp = (pScreenInfo->videoRam * (1024 * 8) / - pATI->displayWidth / pATI->bitsPerPixel) - 1; + tmp = pATI->displayWidth * pATI->bitsPerPixel; + tmp = (((pScreenInfo->videoRam * (1024 * 8)) + tmp - 1) / tmp) - 1; if (tmp > ATIMach64MaxY) tmp = ATIMach64MaxY; pATIHW->sc_bottom = tmp; pATI->sc_left_right = SetWord(pATI->NewHW.sc_right, 1) | SetWord(pATI->NewHW.sc_left, 0); - pATI->sc_top_bottom = SetWord(pATI->NewHW.sc_bottom, 1) | + pATI->sc_top_bottom = SetWord(pATI->NewHW.sc_bottom, 1) | SetWord(pATI->NewHW.sc_top, 0); /* Initialise data path */ @@ -332,6 +289,42 @@ ATIMach64PreInit /* Initialise colour compare */ pATIHW->clr_cmp_msk = (1 << pATI->depth) - 1; + if (pATI->Block1Base) + { + pATIHW->overlay_y_x_start = SetBits(0, OVERLAY_Y_START) | + SetBits(0, OVERLAY_X_START) | OVERLAY_LOCK_START; + pATIHW->overlay_y_x_end = SetBits(0, OVERLAY_Y_END) | + SetBits(0, OVERLAY_X_END) | OVERLAY_LOCK_END; + + pATIHW->overlay_graphics_key_clr = + (3 << ((2 * pATI->depth) / 3)) | + (2 << ((1 * pATI->depth) / 3)) | + (1 << ((0 * pATI->depth) / 3)); + pATIHW->overlay_graphics_key_msk = (1 << pATI->depth) - 1; + + pATIHW->overlay_key_cntl = + SetBits(OVERLAY_MIX_FALSE, OVERLAY_VIDEO_FN) | + SetBits(OVERLAY_MIX_EQUAL, OVERLAY_GRAPHICS_FN); + + pATIHW->overlay_scale_cntl = SCALE_EN; + + pATIHW->video_format = VIDEO_IN_VYUY422 | SCALER_IN_VYUY422; + + if (pATI->Chip >= ATI_CHIP_264GTPRO) + { + /* These values are documented voodoo */ + pATIHW->scaler_h_coeff0 = SetByte(0x20U, 1); + pATIHW->scaler_h_coeff1 = SetByte(0x0DU, 0) | + SetByte(0x20U, 1) | SetByte(0x06U, 2) | SetByte(0x0DU, 3); + pATIHW->scaler_h_coeff2 = SetByte(0x0DU, 0) | + SetByte(0x1CU, 1) | SetByte(0x0AU, 2) | SetByte(0x0DU, 3); + pATIHW->scaler_h_coeff3 = SetByte(0x0CU, 0) | + SetByte(0x1AU, 1) | SetByte(0x0EU, 2) | SetByte(0x0CU, 3); + pATIHW->scaler_h_coeff4 = SetByte(0x0CU, 0) | + SetByte(0x14U, 1) | SetByte(0x14U, 2) | SetByte(0x0CU, 3); + } + } + /* Restore aperture enablement */ outr(BUS_CNTL, bus_cntl); outr(CONFIG_CNTL, config_cntl); @@ -392,7 +385,7 @@ ATIMach64Save } /* Save draw engine state */ - if (pATI->OptionAccel && (pATIHW == &pATI->OldHW)) + if (pATI->Block0Base && (pATIHW == &pATI->OldHW)) { /* Ensure apertures are enabled */ outr(BUS_CNTL, pATI->NewHW.bus_cntl); @@ -457,6 +450,60 @@ ATIMach64Save /* Save context */ pATIHW->context_mask = inm(CONTEXT_MASK); + if (pATI->Block1Base) + { + /* Save overlay & scaler registers */ + pATIHW->overlay_y_x_start = inm(OVERLAY_Y_X_START); + pATIHW->overlay_y_x_end = inm(OVERLAY_Y_X_END); + + pATIHW->overlay_graphics_key_clr = inm(OVERLAY_GRAPHICS_KEY_CLR); + pATIHW->overlay_graphics_key_msk = inm(OVERLAY_GRAPHICS_KEY_MSK); + + pATIHW->overlay_key_cntl = inm(OVERLAY_KEY_CNTL); + + pATIHW->overlay_scale_inc = inm(OVERLAY_SCALE_INC); + pATIHW->overlay_scale_cntl = inm(OVERLAY_SCALE_CNTL); + + pATIHW->scaler_height_width = inm(SCALER_HEIGHT_WIDTH); + + pATIHW->scaler_test = inm(SCALER_TEST); + + pATIHW->video_format = inm(VIDEO_FORMAT); + + if (pATI->Chip < ATI_CHIP_264VTB) + { + pATIHW->buf0_offset = inm(BUF0_OFFSET); + pATIHW->buf0_pitch = inm(BUF0_PITCH); + pATIHW->buf1_offset = inm(BUF1_OFFSET); + pATIHW->buf1_pitch = inm(BUF1_PITCH); + } + else + { + pATIHW->scaler_buf0_offset = inm(SCALER_BUF0_OFFSET); + pATIHW->scaler_buf1_offset = inm(SCALER_BUF1_OFFSET); + pATIHW->scaler_buf_pitch = inm(SCALER_BUF_PITCH); + + pATIHW->overlay_exclusive_horz = inm(OVERLAY_EXCLUSIVE_HORZ); + pATIHW->overlay_exclusive_vert = inm(OVERLAY_EXCLUSIVE_VERT); + + if (pATI->Chip >= ATI_CHIP_264GTPRO) + { + pATIHW->scaler_colour_cntl = inm(SCALER_COLOUR_CNTL); + + pATIHW->scaler_h_coeff0 = inm(SCALER_H_COEFF0); + pATIHW->scaler_h_coeff1 = inm(SCALER_H_COEFF1); + pATIHW->scaler_h_coeff2 = inm(SCALER_H_COEFF2); + pATIHW->scaler_h_coeff3 = inm(SCALER_H_COEFF3); + pATIHW->scaler_h_coeff4 = inm(SCALER_H_COEFF4); + + pATIHW->scaler_buf0_offset_u = inm(SCALER_BUF0_OFFSET_U); + pATIHW->scaler_buf0_offset_v = inm(SCALER_BUF0_OFFSET_V); + pATIHW->scaler_buf1_offset_u = inm(SCALER_BUF1_OFFSET_U); + pATIHW->scaler_buf1_offset_v = inm(SCALER_BUF1_OFFSET_V); + } + } + } + /* Restore aperture enablement */ outr(BUS_CNTL, pATIHW->bus_cntl); outr(CONFIG_CNTL, pATIHW->config_cntl); @@ -491,8 +538,10 @@ ATIMach64Calculate /* Make adjustments if sync pulse width is out-of-bounds */ if ((pMode->CrtcHSyncEnd - pMode->CrtcHSyncStart) > (int)MaxBits(CRTC_H_SYNC_WID)) + { pMode->CrtcHSyncEnd = pMode->CrtcHSyncStart + MaxBits(CRTC_H_SYNC_WID); + } else if (pMode->CrtcHSyncStart == pMode->CrtcHSyncEnd) { if (pMode->CrtcHDisplay < pMode->CrtcHSyncStart) @@ -656,48 +705,54 @@ ATIMach64Set ATIHWPtr pATIHW ) { - /* First, turn off the display */ - outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl & ~CRTC_EN); - - if ((pATIHW->FeedbackDivider > 0) && - (pATI->ProgrammableClock != ATI_CLOCK_NONE)) - ATIClockSet(pATI, pATIHW); /* Programme clock */ - - if (pATI->DAC == ATI_DAC_IBMRGB514) - ATIRGB514Set(pATI, pATIHW); - /* Load Mach64 CRTC registers */ - outr(CRTC_H_TOTAL_DISP, pATIHW->crtc_h_total_disp); - outr(CRTC_H_SYNC_STRT_WID, pATIHW->crtc_h_sync_strt_wid); - outr(CRTC_V_TOTAL_DISP, pATIHW->crtc_v_total_disp); - outr(CRTC_V_SYNC_STRT_WID, pATIHW->crtc_v_sync_strt_wid); - - outr(CRTC_OFF_PITCH, pATIHW->crtc_off_pitch); - - /* Load overscan registers */ - outr(OVR_CLR, pATIHW->ovr_clr); - outr(OVR_WID_LEFT_RIGHT, pATIHW->ovr_wid_left_right); - outr(OVR_WID_TOP_BOTTOM, pATIHW->ovr_wid_top_bottom); - - /* Load hardware cursor registers */ - outr(CUR_CLR0, pATIHW->cur_clr0); - outr(CUR_CLR1, pATIHW->cur_clr1); - outr(CUR_OFFSET, pATIHW->cur_offset); - outr(CUR_HORZ_VERT_POSN, pATIHW->cur_horz_vert_posn); - outr(CUR_HORZ_VERT_OFF, pATIHW->cur_horz_vert_off); +#ifndef AVOID_CPIO - /* Set pixel clock */ - outr(CLOCK_CNTL, pATIHW->clock_cntl | CLOCK_STROBE); + if (pATIHW->crtc == ATI_CRTC_MACH64) - outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN); - outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl); - outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN); +#endif /* AVOID_CPIO */ - /* Finalise CRTC setup and turn on the screen */ - outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl); + { + if ((pATIHW->FeedbackDivider > 0) && + (pATI->ProgrammableClock != ATI_CLOCK_NONE)) + ATIClockSet(pATI, pATIHW); /* Programme clock */ + + if (pATI->DAC == ATI_DAC_IBMRGB514) + ATIRGB514Set(pATI, pATIHW); + + /* Load Mach64 CRTC registers */ + outr(CRTC_H_TOTAL_DISP, pATIHW->crtc_h_total_disp); + outr(CRTC_H_SYNC_STRT_WID, pATIHW->crtc_h_sync_strt_wid); + outr(CRTC_V_TOTAL_DISP, pATIHW->crtc_v_total_disp); + outr(CRTC_V_SYNC_STRT_WID, pATIHW->crtc_v_sync_strt_wid); + + outr(CRTC_OFF_PITCH, pATIHW->crtc_off_pitch); + + /* Load overscan registers */ + outr(OVR_CLR, pATIHW->ovr_clr); + outr(OVR_WID_LEFT_RIGHT, pATIHW->ovr_wid_left_right); + outr(OVR_WID_TOP_BOTTOM, pATIHW->ovr_wid_top_bottom); + + /* Load hardware cursor registers */ + outr(CUR_CLR0, pATIHW->cur_clr0); + outr(CUR_CLR1, pATIHW->cur_clr1); + outr(CUR_OFFSET, pATIHW->cur_offset); + outr(CUR_HORZ_VERT_POSN, pATIHW->cur_horz_vert_posn); + outr(CUR_HORZ_VERT_OFF, pATIHW->cur_horz_vert_off); + + /* Set pixel clock */ + outr(CLOCK_CNTL, pATIHW->clock_cntl | CLOCK_STROBE); + + outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN); + outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl); + outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN); + + /* Finalise CRTC setup and turn on the screen */ + outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl); + } /* Load draw engine */ - if (pATI->OptionAccel) + if (pATI->Block0Base) { /* Clobber MMIO cache */ (void)memset(pATI->MMIOCached, 0, SizeOf(pATI->MMIOCached)); @@ -791,6 +846,64 @@ ATIMach64Set ATIMach64WaitForFIFO(pATI, 1); outf(CONTEXT_MASK, pATIHW->context_mask); + if (pATI->Block1Base) + { + /* Load overlay & scaler registers */ + ATIMach64WaitForFIFO(pATI, 10); + outf(OVERLAY_Y_X_START, pATIHW->overlay_y_x_start); + outf(OVERLAY_Y_X_END, pATIHW->overlay_y_x_end); + + outf(OVERLAY_GRAPHICS_KEY_CLR, pATIHW->overlay_graphics_key_clr); + outf(OVERLAY_GRAPHICS_KEY_MSK, pATIHW->overlay_graphics_key_msk); + + outf(OVERLAY_KEY_CNTL, pATIHW->overlay_key_cntl); + + outf(OVERLAY_SCALE_INC, pATIHW->overlay_scale_inc); + outf(OVERLAY_SCALE_CNTL, pATIHW->overlay_scale_cntl); + + outf(SCALER_HEIGHT_WIDTH, pATIHW->scaler_height_width); + + outf(SCALER_TEST, pATIHW->scaler_test); + + outf(VIDEO_FORMAT, pATIHW->video_format); + + if (pATI->Chip < ATI_CHIP_264VTB) + { + ATIMach64WaitForFIFO(pATI, 4); + outf(BUF0_OFFSET, pATIHW->buf0_offset); + outf(BUF0_PITCH, pATIHW->buf0_pitch); + outf(BUF1_OFFSET, pATIHW->buf1_offset); + outf(BUF1_PITCH, pATIHW->buf1_pitch); + } + else + { + ATIMach64WaitForFIFO(pATI, 5); + outf(SCALER_BUF0_OFFSET, pATIHW->scaler_buf0_offset); + outf(SCALER_BUF1_OFFSET, pATIHW->scaler_buf1_offset); + outf(SCALER_BUF_PITCH, pATIHW->scaler_buf_pitch); + + outf(OVERLAY_EXCLUSIVE_HORZ, pATIHW->overlay_exclusive_horz); + outf(OVERLAY_EXCLUSIVE_VERT, pATIHW->overlay_exclusive_vert); + + if (pATI->Chip >= ATI_CHIP_264GTPRO) + { + ATIMach64WaitForFIFO(pATI, 10); + outf(SCALER_COLOUR_CNTL, pATIHW->scaler_colour_cntl); + + outf(SCALER_H_COEFF0, pATIHW->scaler_h_coeff0); + outf(SCALER_H_COEFF1, pATIHW->scaler_h_coeff1); + outf(SCALER_H_COEFF2, pATIHW->scaler_h_coeff2); + outf(SCALER_H_COEFF3, pATIHW->scaler_h_coeff3); + outf(SCALER_H_COEFF4, pATIHW->scaler_h_coeff4); + + outf(SCALER_BUF0_OFFSET_U, pATIHW->scaler_buf0_offset_u); + outf(SCALER_BUF0_OFFSET_V, pATIHW->scaler_buf0_offset_v); + outf(SCALER_BUF1_OFFSET_U, pATIHW->scaler_buf1_offset_u); + outf(SCALER_BUF1_OFFSET_V, pATIHW->scaler_buf1_offset_v); + } + } + } + ATIMach64WaitForIdle(pATI); if (pATI->OptionMMIOCache) @@ -820,24 +933,85 @@ ATIMach64Set CacheRegister(CLR_CMP_CLR); CacheRegister(CLR_CMP_MSK); CacheRegister(CLR_CMP_CNTL); + + if (pATI->Block1Base) + { + CacheRegister(OVERLAY_Y_X_START); + CacheRegister(OVERLAY_Y_X_END); + + CacheRegister(OVERLAY_GRAPHICS_KEY_CLR); + CacheRegister(OVERLAY_GRAPHICS_KEY_MSK); + + CacheRegister(OVERLAY_KEY_CNTL); + + CacheRegister(OVERLAY_SCALE_INC); + CacheRegister(OVERLAY_SCALE_CNTL); + + CacheRegister(SCALER_HEIGHT_WIDTH); + + CacheRegister(SCALER_TEST); + + CacheRegister(VIDEO_FORMAT); + + if (pATI->Chip < ATI_CHIP_264VTB) + { + CacheRegister(BUF0_OFFSET); + CacheRegister(BUF0_PITCH); + CacheRegister(BUF1_OFFSET); + CacheRegister(BUF1_PITCH); + } + else + { + CacheRegister(SCALER_BUF0_OFFSET); + CacheRegister(SCALER_BUF1_OFFSET); + CacheRegister(SCALER_BUF_PITCH); + + CacheRegister(OVERLAY_EXCLUSIVE_HORZ); + CacheRegister(OVERLAY_EXCLUSIVE_VERT); + + if (pATI->Chip >= ATI_CHIP_264GTPRO) + { + CacheRegister(SCALER_COLOUR_CNTL); + + CacheRegister(SCALER_H_COEFF0); + CacheRegister(SCALER_H_COEFF1); + CacheRegister(SCALER_H_COEFF2); + CacheRegister(SCALER_H_COEFF3); + CacheRegister(SCALER_H_COEFF4); + + CacheRegister(SCALER_BUF0_OFFSET_U); + CacheRegister(SCALER_BUF0_OFFSET_V); + CacheRegister(SCALER_BUF1_OFFSET_U); + CacheRegister(SCALER_BUF1_OFFSET_V); + } + } + } } } - /* Aperture setup */ - outr(MEM_VGA_WP_SEL, pATIHW->mem_vga_wp_sel); - outr(MEM_VGA_RP_SEL, pATIHW->mem_vga_rp_sel); +#ifndef AVOID_CPIO - outr(DAC_CNTL, pATIHW->dac_cntl); + if (pATIHW->crtc == ATI_CRTC_MACH64) - outr(CONFIG_CNTL, pATIHW->config_cntl); - outr(BUS_CNTL, pATIHW->bus_cntl); +#endif /* AVOID_CPIO */ - if (pATI->Chip >= ATI_CHIP_264VTB) { - outr(MEM_CNTL, pATIHW->mem_cntl); - outr(MPP_CONFIG, pATIHW->mpp_config); - outr(MPP_STROBE_SEQ, pATIHW->mpp_strobe_seq); - outr(TVO_CNTL, pATIHW->tvo_cntl); + /* Aperture setup */ + outr(MEM_VGA_WP_SEL, pATIHW->mem_vga_wp_sel); + outr(MEM_VGA_RP_SEL, pATIHW->mem_vga_rp_sel); + + outr(DAC_CNTL, pATIHW->dac_cntl); + + outr(CONFIG_CNTL, pATIHW->config_cntl); + outr(BUS_CNTL, pATIHW->bus_cntl); + + if (pATI->Chip >= ATI_CHIP_264VTB) + { + outr(MEM_CNTL, pATIHW->mem_cntl); + outr(MPP_CONFIG, pATIHW->mpp_config); + outr(MPP_STROBE_SEQ, pATIHW->mpp_strobe_seq); + outr(TVO_CNTL, pATIHW->tvo_cntl); + } } } @@ -909,8 +1083,7 @@ ATIMach64SetDPMSMode return; } - if (pATI->pXAAInfo && pATI->pXAAInfo->NeedToSync) - (*pATI->pXAAInfo->Sync)(pScreenInfo); + ATIMach64Sync(pScreenInfo); outr(CRTC_GEN_CNTL, crtc_gen_cntl); @@ -927,13 +1100,15 @@ ATIMach64SetDPMSMode CARD32 power_management; if (pATI->Chip == ATI_CHIP_264LT) + { power_management = inr(POWER_MANAGEMENT); + } else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ { lcd_index = inr(LCD_INDEX); - power_management = ATIGetMach64LCDReg(LCD_POWER_MANAGEMENT); + power_management = ATIMach64GetLCDReg(LCD_POWER_MANAGEMENT); } power_management &= ~(STANDBY_NOW | SUSPEND_NOW); @@ -960,12 +1135,14 @@ ATIMach64SetDPMSMode } if (pATI->Chip == ATI_CHIP_264LT) + { outr(POWER_MANAGEMENT, power_management); + } else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ { - ATIPutMach64LCDReg(LCD_POWER_MANAGEMENT, power_management); + ATIMach64PutLCDReg(LCD_POWER_MANAGEMENT, power_management); outr(LCD_INDEX, lcd_index); } } @@ -974,13 +1151,15 @@ ATIMach64SetDPMSMode CARD32 lcd_gen_ctrl; if (pATI->Chip == ATI_CHIP_264LT) + { lcd_gen_ctrl = inr(LCD_GEN_CTRL); + } else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ { lcd_index = inr(LCD_INDEX); - lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL); + lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); } if (DPMSMode == DPMSModeOn) @@ -994,1171 +1173,9 @@ ATIMach64SetDPMSMode (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ { - ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); + ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); outr(LCD_INDEX, lcd_index); } } } } - -/* - * ATIMach64ValidateClip -- - * - * This function ensures the current scissor settings do not interfere with - * the current draw request. - */ -static void -ATIMach64ValidateClip -( - ATIPtr pATI, - int sc_left, - int sc_right, - int sc_top, - int sc_bottom -) -{ - if ((sc_left < (int)pATI->sc_left) || (sc_right > (int)pATI->sc_right)) - { - outf(SC_LEFT_RIGHT, pATI->sc_left_right); - pATI->sc_left = pATI->NewHW.sc_left; - pATI->sc_right = pATI->NewHW.sc_right; - } - - if ((sc_top < (int)pATI->sc_top) || (sc_bottom > (int)pATI->sc_bottom)) - { - outf(SC_TOP_BOTTOM, pATI->sc_top_bottom); - pATI->sc_top = pATI->NewHW.sc_top; - pATI->sc_bottom = pATI->NewHW.sc_bottom; - } -} - -/* - * ATIMach64Sync -- - * - * This is called to wait for the draw engine to become idle. - */ -static void -ATIMach64Sync -( - ScrnInfoPtr pScreenInfo -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - ATIMach64WaitForIdle(pATI); - - if (pATI->OptionMMIOCache) - { - /* - * For debugging purposes, attempt to verify that each cached register - * should actually be cached. - */ - if (RegisterIsCached(SRC_CNTL) && - (CacheSlot(SRC_CNTL) != inm(SRC_CNTL))) - { - UncacheRegister(SRC_CNTL); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "SRC_CNTL write cache disabled!\n"); - } - - if (RegisterIsCached(HOST_CNTL) && - (CacheSlot(HOST_CNTL) != inm(HOST_CNTL))) - { - UncacheRegister(HOST_CNTL); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "HOST_CNTL write cache disabled!\n"); - } - - if (RegisterIsCached(PAT_REG0) && - (CacheSlot(PAT_REG0) != inm(PAT_REG0))) - { - UncacheRegister(PAT_REG0); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "PAT_REG0 write cache disabled!\n"); - } - - if (RegisterIsCached(PAT_REG1) && - (CacheSlot(PAT_REG1) != inm(PAT_REG1))) - { - UncacheRegister(PAT_REG1); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "PAT_REG1 write cache disabled!\n"); - } - - if (RegisterIsCached(PAT_CNTL) && - (CacheSlot(PAT_CNTL) != inm(PAT_CNTL))) - { - UncacheRegister(PAT_CNTL); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "PAT_CNTL write cache disabled!\n"); - } - - if (RegisterIsCached(SC_LEFT_RIGHT) && - (CacheSlot(SC_LEFT_RIGHT) != - (SetWord(inm(SC_RIGHT), 1) | SetWord(inm(SC_LEFT), 0)))) - { - UncacheRegister(SC_LEFT_RIGHT); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "SC_LEFT_RIGHT write cache disabled!\n"); - } - - if (RegisterIsCached(SC_TOP_BOTTOM) && - (CacheSlot(SC_TOP_BOTTOM) != - (SetWord(inm(SC_BOTTOM), 1) | SetWord(inm(SC_TOP), 0)))) - { - UncacheRegister(SC_TOP_BOTTOM); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "SC_TOP_BOTTOM write cache disabled!\n"); - } - - if (RegisterIsCached(DP_BKGD_CLR) && - (CacheSlot(DP_BKGD_CLR) != inm(DP_BKGD_CLR))) - { - UncacheRegister(DP_BKGD_CLR); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "DP_BKGD_CLR write cache disabled!\n"); - } - - if (RegisterIsCached(DP_FRGD_CLR) && - (CacheSlot(DP_FRGD_CLR) != inm(DP_FRGD_CLR))) - { - UncacheRegister(DP_FRGD_CLR); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "DP_FRGD_CLR write cache disabled!\n"); - } - - if (RegisterIsCached(DP_WRITE_MASK) && - (CacheSlot(DP_WRITE_MASK) != inm(DP_WRITE_MASK))) - { - UncacheRegister(DP_WRITE_MASK); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "DP_WRITE_MASK write cache disabled!\n"); - } - - if (RegisterIsCached(DP_MIX) && - (CacheSlot(DP_MIX) != inm(DP_MIX))) - { - UncacheRegister(DP_MIX); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "DP_MIX write cache disabled!\n"); - } - - if (RegisterIsCached(CLR_CMP_CLR) && - (CacheSlot(CLR_CMP_CLR) != inm(CLR_CMP_CLR))) - { - UncacheRegister(CLR_CMP_CLR); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "CLR_CMP_CLR write cache disabled!\n"); - } - - if (RegisterIsCached(CLR_CMP_MSK) && - (CacheSlot(CLR_CMP_MSK) != inm(CLR_CMP_MSK))) - { - UncacheRegister(CLR_CMP_MSK); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "CLR_CMP_MSK write cache disabled!\n"); - } - - if (RegisterIsCached(CLR_CMP_CNTL) && - (CacheSlot(CLR_CMP_CNTL) != inm(CLR_CMP_CNTL))) - { - UncacheRegister(CLR_CMP_CNTL); - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "CLR_CMP_CNTL write cache disabled!\n"); - } - } - - /* - * For VTB's and later, the first CPU read of the framebuffer will return - * zeroes, so do it here. This appears to be due to some kind of engine - * caching of framebuffer data I haven't found any way of disabling, or - * otherwise circumventing. Thanks to Mark Vojkovich for the suggestion. - */ - pATI->pXAAInfo->NeedToSync = FALSE; - pATI = *(volatile ATIPtr *)pATI->pMemory; -} - -/* - * ATIMach64SetupForScreenToScreenCopy -- - * - * This function sets up the draw engine for a series of screen-to-screen copy - * operations. - */ -static void -ATIMach64SetupForScreenToScreenCopy -( - ScrnInfoPtr pScreenInfo, - int xdir, - int ydir, - int rop, - unsigned int planemask, - int TransparencyColour -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - ATIMach64WaitForFIFO(pATI, 3); - outf(DP_WRITE_MASK, planemask); - outf(DP_SRC, DP_MONO_SRC_ALLONES | - SetBits(SRC_BLIT, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC)); - outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX)); - -#ifdef AVOID_DGA - - if (TransparencyColour == -1) - -#else /* AVOID_DGA */ - - if (!pATI->XAAForceTransBlit && (TransparencyColour == -1)) - -#endif /* AVOID_DGA */ - - outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); - else - { - ATIMach64WaitForFIFO(pATI, 2); - outf(CLR_CMP_CLR, TransparencyColour); - outf(CLR_CMP_CNTL, CLR_CMP_FN_EQUAL | CLR_CMP_SRC_2D); - } - - pATI->dst_cntl = 0; - - if (ydir > 0) - pATI->dst_cntl |= DST_Y_DIR; - if (xdir > 0) - pATI->dst_cntl |= DST_X_DIR; - - if (pATI->XModifier == 1) - outf(DST_CNTL, pATI->dst_cntl); - else - pATI->dst_cntl |= DST_24_ROT_EN; -} - -/* - * ATIMach64SubsequentScreenToScreenCopy -- - * - * This function performs a screen-to-screen copy operation. - */ -static void -ATIMach64SubsequentScreenToScreenCopy -( - ScrnInfoPtr pScreenInfo, - int xSrc, - int ySrc, - int xDst, - int yDst, - int w, - int h -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - xSrc *= pATI->XModifier; - xDst *= pATI->XModifier; - w *= pATI->XModifier; - - /* Disable clipping if it gets in the way */ - ATIMach64ValidateClip(pATI, xDst, xDst + w - 1, yDst, yDst + h - 1); - - if (!(pATI->dst_cntl & DST_X_DIR)) - { - xSrc += w - 1; - xDst += w - 1; - } - - if (!(pATI->dst_cntl & DST_Y_DIR)) - { - ySrc += h - 1; - yDst += h - 1; - } - - if (pATI->XModifier != 1) - outf(DST_CNTL, pATI->dst_cntl | SetBits((xDst / 4) % 6, DST_24_ROT)); - - ATIMach64WaitForFIFO(pATI, 4); - outf(SRC_Y_X, SetWord(xSrc, 1) | SetWord(ySrc, 0)); - outf(SRC_WIDTH1, w); - outf(DST_Y_X, SetWord(xDst, 1) | SetWord(yDst, 0)); - outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0)); -} - -/* - * ATIMach64SetupForSolidFill -- - * - * This function sets up the draw engine for a series of solid fills. - */ -static void -ATIMach64SetupForSolidFill -( - ScrnInfoPtr pScreenInfo, - int colour, - int rop, - unsigned int planemask -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - ATIMach64WaitForFIFO(pATI, 5); - outf(DP_WRITE_MASK, planemask); - outf(DP_SRC, DP_MONO_SRC_ALLONES | - SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC)); - outf(DP_FRGD_CLR, colour); - outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX)); - - outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); - - if (pATI->XModifier == 1) - outf(DST_CNTL, DST_X_DIR | DST_Y_DIR); -} - -/* - * ATIMach64SubsequentSolidFillRect -- - * - * This function performs a solid rectangle fill. - */ -static void -ATIMach64SubsequentSolidFillRect -( - ScrnInfoPtr pScreenInfo, - int x, - int y, - int w, - int h -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - if (pATI->XModifier != 1) - { - x *= pATI->XModifier; - w *= pATI->XModifier; - - outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) | - (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)); - } - - /* Disable clipping if it gets in the way */ - ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1); - - ATIMach64WaitForFIFO(pATI, 2); - outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); - outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0)); -} - -/* - * ATIMach64SetupForSolidLine -- - * - * This function sets up the draw engine for a series of solid lines. It is - * not used for 24bpp because the engine doesn't support it. - */ -static void -ATIMach64SetupForSolidLine -( - ScrnInfoPtr pScreenInfo, - int colour, - int rop, - unsigned int planemask -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - ATIMach64WaitForFIFO(pATI, 5); - outf(DP_WRITE_MASK, planemask); - outf(DP_SRC, DP_MONO_SRC_ALLONES | - SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC)); - outf(DP_FRGD_CLR, colour); - outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX)); - - outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); - - ATIMach64ValidateClip(pATI, pATI->NewHW.sc_left, pATI->NewHW.sc_right, - pATI->NewHW.sc_top, pATI->NewHW.sc_bottom); -} - -/* - * ATIMach64SubsequentSolidHorVertLine -- - * - * This is called to draw a solid horizontal or vertical line. This does a - * one-pixel wide solid fill. - */ -static void -ATIMach64SubsequentSolidHorVertLine -( - ScrnInfoPtr pScreenInfo, - int x, - int y, - int len, - int dir -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - ATIMach64WaitForFIFO(pATI, 3); - outf(DST_CNTL, DST_X_DIR | DST_Y_DIR); - outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); - - if (dir == DEGREES_0) - outf(DST_HEIGHT_WIDTH, SetWord(len, 1) | SetWord(1, 0)); - else /* if (dir == DEGREES_270) */ - outf(DST_HEIGHT_WIDTH, SetWord(1, 1) | SetWord(len, 0)); -} - -/* - * ATIMach64SubsequentSolidBresenhamLine -- - * - * This function draws a line using the Bresenham line engine. - */ -static void -ATIMach64SubsequentSolidBresenhamLine -( - ScrnInfoPtr pScreenInfo, - int x, - int y, - int major, - int minor, - int err, - int len, - int octant -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - CARD32 dst_cntl = DST_LAST_PEL; - - if (octant & YMAJOR) - dst_cntl |= DST_Y_MAJOR; - - if (!(octant & XDECREASING)) - dst_cntl |= DST_X_DIR; - - if (!(octant & YDECREASING)) - dst_cntl |= DST_Y_DIR; - - ATIMach64WaitForFIFO(pATI, 6); - outf(DST_CNTL, dst_cntl); - outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); - outf(DST_BRES_ERR, minor + err); - outf(DST_BRES_INC, minor); - outf(DST_BRES_DEC, minor - major); - outf(DST_BRES_LNTH, len); -} - -/* - * ATIMach64SetupForMono8x8PatternFill -- - * - * This function sets up the draw engine for a series of 8x8 1bpp pattern - * fills. - */ -static void -ATIMach64SetupForMono8x8PatternFill -( - ScrnInfoPtr pScreenInfo, - int patx, - int paty, - int fg, - int bg, - int rop, - unsigned int planemask -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - ATIMach64WaitForFIFO(pATI, 3); - outf(DP_WRITE_MASK, planemask); - outf(DP_SRC, DP_MONO_SRC_PATTERN | - SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC)); - outf(DP_FRGD_CLR, fg); - - if (bg == -1) - outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) | - SetBits(MIX_DST, DP_BKGD_MIX)); - else - { - ATIMach64WaitForFIFO(pATI, 2); - outf(DP_BKGD_CLR, bg); - outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) | - SetBits(ATIMach64ALU[rop], DP_BKGD_MIX)); - } - - ATIMach64WaitForFIFO(pATI, 4); - outf(PAT_REG0, patx); - outf(PAT_REG1, paty); - outf(PAT_CNTL, PAT_MONO_EN); - - outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); - - if (pATI->XModifier == 1) - outf(DST_CNTL, DST_X_DIR | DST_Y_DIR); -} - -/* - * ATIMach64SubsequentMono8x8PatternFillRect -- - * - * This function performs an 8x8 1bpp pattern fill. - */ -static void -ATIMach64SubsequentMono8x8PatternFillRect -( - ScrnInfoPtr pScreenInfo, - int patx, - int paty, - int x, - int y, - int w, - int h -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - if (pATI->XModifier != 1) - { - x *= pATI->XModifier; - w *= pATI->XModifier; - - outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) | - (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)); - } - - /* Disable clipping if it gets in the way */ - ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1); - - ATIMach64WaitForFIFO(pATI, 2); - outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); - outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0)); -} - -/* - * ATIMach64SetupForScanlineCPUToScreenColorExpandFill -- - * - * This function sets up the engine for a series of colour expansion fills. - */ -static void -ATIMach64SetupForScanlineCPUToScreenColorExpandFill -( - ScrnInfoPtr pScreenInfo, - int fg, - int bg, - int rop, - unsigned int planemask -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - ATIMach64WaitForFIFO(pATI, 3); - outf(DP_WRITE_MASK, planemask); - outf(DP_SRC, DP_MONO_SRC_HOST | - SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC)); - outf(DP_FRGD_CLR, fg); - - if (bg == -1) - outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) | - SetBits(MIX_DST, DP_BKGD_MIX)); - else - { - ATIMach64WaitForFIFO(pATI, 2); - outf(DP_BKGD_CLR, bg); - outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) | - SetBits(ATIMach64ALU[rop], DP_BKGD_MIX)); - } - - outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); - - if (pATI->XModifier == 1) - outf(DST_CNTL, DST_X_DIR | DST_Y_DIR); -} - -/* - * ATIMach64SubsequentScanlineCPUToScreenColorExpandFill -- - * - * This function sets up the engine for a single colour expansion fill. - */ -static void -ATIMach64SubsequentScanlineCPUToScreenColorExpandFill -( - ScrnInfoPtr pScreenInfo, - int x, - int y, - int w, - int h, - int skipleft -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - if (pATI->XModifier != 1) - { - x *= pATI->XModifier; - w *= pATI->XModifier; - skipleft *= pATI->XModifier; - - outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) | - (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)); - } - - pATI->ExpansionBitmapWidth = (w + 31) / 32; - - ATIMach64WaitForFIFO(pATI, 3); - pATI->sc_left = x + skipleft; - pATI->sc_right = x + w - 1; - outf(SC_LEFT_RIGHT, - SetWord(pATI->sc_right, 1) | SetWord(pATI->sc_left, 0)); - outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); - outf(DST_HEIGHT_WIDTH, - SetWord(pATI->ExpansionBitmapWidth * 32, 1) | SetWord(h, 0)); -} - -/* - * ATIMach64SubsequentColorExpandScanline -- - * - * This function feeds a bitmap scanline to the engine for a colour expansion - * fill. This is written to do burst transfers for those platforms that can do - * them, and to improve CPU/engine concurrency. - */ -static void -ATIMach64SubsequentColorExpandScanline -( - ScrnInfoPtr pScreenInfo, - int iBuffer -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - CARD32 *pBitmapData = pATI->ExpansionBitmapScanlinePtr[iBuffer]; - int w = pATI->ExpansionBitmapWidth; - int nDWord; - - while (w > 0) - { - /* - * Transfers are done in chunks of up to 64 bytes in length (32 on - * earlier controllers). - */ - nDWord = w; - if (nDWord > pATI->nHostFIFOEntries) - nDWord = pATI->nHostFIFOEntries; - - /* Make enough FIFO slots available */ - ATIMach64WaitForFIFO(pATI, nDWord); - - /* - * Always start transfers on a chuck-sized boundary. Note that - * HOST_DATA_0 is actually on a 512-byte boundary, but *pBitmapData can - * only be guaranteed to be on a chunk-sized boundary. - * - * Transfer current chunk. With any luck, the compiler won't mangle - * this too badly... - */ - -# if defined(ATIMove32) - - ATIMove32(pATI->pHOST_DATA, pBitmapData, nDWord); - -# else - - { - volatile CARD32 *pDst; - CARD32 *pSrc; - unsigned int iDWord; - - iDWord = 16 - nDWord; - pDst = (volatile CARD32 *)pATI->pHOST_DATA - iDWord; - pSrc = pBitmapData - iDWord; - - switch (iDWord) - { - case 0: MMIO_MOVE32(pDst + 0, 0, *(pSrc + 0)); - case 1: MMIO_MOVE32(pDst + 1, 0, *(pSrc + 1)); - case 2: MMIO_MOVE32(pDst + 2, 0, *(pSrc + 2)); - case 3: MMIO_MOVE32(pDst + 3, 0, *(pSrc + 3)); - case 4: MMIO_MOVE32(pDst + 4, 0, *(pSrc + 4)); - case 5: MMIO_MOVE32(pDst + 5, 0, *(pSrc + 5)); - case 6: MMIO_MOVE32(pDst + 6, 0, *(pSrc + 6)); - case 7: MMIO_MOVE32(pDst + 7, 0, *(pSrc + 7)); - case 8: MMIO_MOVE32(pDst + 8, 0, *(pSrc + 8)); - case 9: MMIO_MOVE32(pDst + 9, 0, *(pSrc + 9)); - case 10: MMIO_MOVE32(pDst + 10, 0, *(pSrc + 10)); - case 11: MMIO_MOVE32(pDst + 11, 0, *(pSrc + 11)); - case 12: MMIO_MOVE32(pDst + 12, 0, *(pSrc + 12)); - case 13: MMIO_MOVE32(pDst + 13, 0, *(pSrc + 13)); - case 14: MMIO_MOVE32(pDst + 14, 0, *(pSrc + 14)); - case 15: MMIO_MOVE32(pDst + 15, 0, *(pSrc + 15)); - - default: /* Muffle compiler */ - break; - } - } - -# endif - - /* Step to next chunk */ - pBitmapData += nDWord; - w -= nDWord; - pATI->nAvailableFIFOEntries -= nDWord; - } - - pATI->EngineIsBusy = TRUE; -} - -/* - * ATIMach64AccelInit -- - * - * This function fills in structure fields needed for acceleration on Mach64 - * variants. - */ -int -ATIMach64AccelInit -( - ATIPtr pATI, - XAAInfoRecPtr pXAAInfo -) -{ - /* This doesn't seem quite right... */ - if (pATI->XModifier == 1) - { - pXAAInfo->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS; - -#ifndef AVOID_CPIO - - if (!pATI->BankInfo.BankSize) - -#endif /* AVOID_CPIO */ - - { - pXAAInfo->Flags |= LINEAR_FRAMEBUFFER; - } - } - - /* Sync */ - pXAAInfo->Sync = ATIMach64Sync; - - /* Screen-to-screen copy */ - pXAAInfo->SetupForScreenToScreenCopy = ATIMach64SetupForScreenToScreenCopy; - pXAAInfo->SubsequentScreenToScreenCopy = - ATIMach64SubsequentScreenToScreenCopy; - - /* Solid fills */ - pXAAInfo->SetupForSolidFill = ATIMach64SetupForSolidFill; - pXAAInfo->SubsequentSolidFillRect = ATIMach64SubsequentSolidFillRect; - - /* 8x8 mono pattern fills */ - pXAAInfo->Mono8x8PatternFillFlags = - -#if X_BYTE_ORDER != X_LITTLE_ENDIAN - - BIT_ORDER_IN_BYTE_MSBFIRST | - -#endif /* X_BYTE_ORDER */ - - HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_SCREEN_ORIGIN; - pXAAInfo->SetupForMono8x8PatternFill = ATIMach64SetupForMono8x8PatternFill; - pXAAInfo->SubsequentMono8x8PatternFillRect = - ATIMach64SubsequentMono8x8PatternFillRect; - - /* - * Use scanline version of colour expansion, not only for the non-ix86 - * case, but also to avoid PCI retries. - */ - pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags = - LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X | - CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD; - if (pATI->XModifier != 1) - pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags |= TRIPLE_BITS_24BPP; - pXAAInfo->NumScanlineColorExpandBuffers = 1; - - /* Align bitmap data on a 64-byte boundary */ - pATI->ExpansionBitmapWidth = /* DWord size in bits */ - ((pATI->displayWidth * pATI->XModifier) + 31) & ~31U; - pATI->ExpansionBitmapScanlinePtr[1] = - (CARD32 *)xnfalloc((pATI->ExpansionBitmapWidth >> 3) + 63); - pATI->ExpansionBitmapScanlinePtr[0] = - (pointer)(((unsigned long)pATI->ExpansionBitmapScanlinePtr[1] + 63) & - ~63UL); - pXAAInfo->ScanlineColorExpandBuffers = - (CARD8 **)pATI->ExpansionBitmapScanlinePtr; - pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill = - ATIMach64SetupForScanlineCPUToScreenColorExpandFill; - pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill = - ATIMach64SubsequentScanlineCPUToScreenColorExpandFill; - pXAAInfo->SubsequentColorExpandScanline = - ATIMach64SubsequentColorExpandScanline; - - /* The engine does not support the following primitives for 24bpp */ - if (pATI->XModifier != 1) - return ATIMach64MaxY; - - /* Solid lines */ - pXAAInfo->SetupForSolidLine = ATIMach64SetupForSolidLine; - pXAAInfo->SubsequentSolidHorVertLine = ATIMach64SubsequentSolidHorVertLine; - pXAAInfo->SubsequentSolidBresenhamLine = - ATIMach64SubsequentSolidBresenhamLine; - - return ATIMach64MaxY; -} - -/* - * ATIMach64SetCursorColours -- - * - * Set hardware cursor foreground and background colours. - */ -static void -ATIMach64SetCursorColours -( - ScrnInfoPtr pScreenInfo, - int fg, - int bg -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - outr(CUR_CLR0, SetBits(fg, CUR_CLR)); - outr(CUR_CLR1, SetBits(bg, CUR_CLR)); -} - -/* - * ATIMach64SetCursorPosition -- - * - * Set position of hardware cursor. - */ -static void -ATIMach64SetCursorPosition -( - ScrnInfoPtr pScreenInfo, - int x, - int y -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - CARD16 CursorXOffset, CursorYOffset; - - /* Adjust x & y when the cursor is partially obscured */ - if (x < 0) - { - if ((CursorXOffset = -x) > 63) - CursorXOffset = 63; - x = 0; - } - else - { - CursorXOffset = pScreenInfo->frameX1 - pScreenInfo->frameX0; - if (x > CursorXOffset) - x = CursorXOffset; - CursorXOffset = 0; - } - - if (y < 0) - { - if ((CursorYOffset = -y) > 63) - CursorYOffset = 63; - y = 0; - } - else - { - CursorYOffset = pScreenInfo->frameY1 - pScreenInfo->frameY0; - if (y > CursorYOffset) - y = CursorYOffset; - CursorYOffset = 0; - } - - /* Adjust for multiscanned modes */ - if (pScreenInfo->currentMode->Flags & V_DBLSCAN) - y *= 2; - if (pScreenInfo->currentMode->VScan > 1) - y *= pScreenInfo->currentMode->VScan; - - do - { - if (CursorYOffset != pATI->CursorYOffset) - { - pATI->CursorYOffset = CursorYOffset; - outr(CUR_OFFSET, ((CursorYOffset << 4) + pATI->CursorOffset) >> 3); - } - else if (CursorXOffset == pATI->CursorXOffset) - break; - - pATI->CursorXOffset = CursorXOffset; - outr(CUR_HORZ_VERT_OFF, SetBits(CursorXOffset, CUR_HORZ_OFF) | - SetBits(CursorYOffset, CUR_VERT_OFF)); - } while (0); - - outr(CUR_HORZ_VERT_POSN, - SetBits(x, CUR_HORZ_POSN) | SetBits(y, CUR_VERT_POSN)); -} - -/* - * ATIMach64LoadCursorImage -- - * - * Copy hardware cursor image into offscreen video memory. - */ -static void -ATIMach64LoadCursorImage -( - ScrnInfoPtr pScreenInfo, - CARD8 *pImage -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo; - CARD32 *pSrc = (pointer)pImage; - volatile CARD32 *pDst = pATI->pCursorImage; - - /* Synchronise video memory accesses */ - if (pXAAInfo && pXAAInfo->NeedToSync) - (*pXAAInfo->Sync)(pScreenInfo); - -# if defined(ATIMove32) - - ATIMove32(pDst, pSrc, 256); - -# else - - /* This is lengthy, but it does maximise burst modes */ - pDst[ 0] = pSrc[ 0]; pDst[ 1] = pSrc[ 1]; - pDst[ 2] = pSrc[ 2]; pDst[ 3] = pSrc[ 3]; - pDst[ 4] = pSrc[ 4]; pDst[ 5] = pSrc[ 5]; - pDst[ 6] = pSrc[ 6]; pDst[ 7] = pSrc[ 7]; - pDst[ 8] = pSrc[ 8]; pDst[ 9] = pSrc[ 9]; - pDst[ 10] = pSrc[ 10]; pDst[ 11] = pSrc[ 11]; - pDst[ 12] = pSrc[ 12]; pDst[ 13] = pSrc[ 13]; - pDst[ 14] = pSrc[ 14]; pDst[ 15] = pSrc[ 15]; - pDst[ 16] = pSrc[ 16]; pDst[ 17] = pSrc[ 17]; - pDst[ 18] = pSrc[ 18]; pDst[ 19] = pSrc[ 19]; - pDst[ 20] = pSrc[ 20]; pDst[ 21] = pSrc[ 21]; - pDst[ 22] = pSrc[ 22]; pDst[ 23] = pSrc[ 23]; - pDst[ 24] = pSrc[ 24]; pDst[ 25] = pSrc[ 25]; - pDst[ 26] = pSrc[ 26]; pDst[ 27] = pSrc[ 27]; - pDst[ 28] = pSrc[ 28]; pDst[ 29] = pSrc[ 29]; - pDst[ 30] = pSrc[ 30]; pDst[ 31] = pSrc[ 31]; - pDst[ 32] = pSrc[ 32]; pDst[ 33] = pSrc[ 33]; - pDst[ 34] = pSrc[ 34]; pDst[ 35] = pSrc[ 35]; - pDst[ 36] = pSrc[ 36]; pDst[ 37] = pSrc[ 37]; - pDst[ 38] = pSrc[ 38]; pDst[ 39] = pSrc[ 39]; - pDst[ 40] = pSrc[ 40]; pDst[ 41] = pSrc[ 41]; - pDst[ 42] = pSrc[ 42]; pDst[ 43] = pSrc[ 43]; - pDst[ 44] = pSrc[ 44]; pDst[ 45] = pSrc[ 45]; - pDst[ 46] = pSrc[ 46]; pDst[ 47] = pSrc[ 47]; - pDst[ 48] = pSrc[ 48]; pDst[ 49] = pSrc[ 49]; - pDst[ 50] = pSrc[ 50]; pDst[ 51] = pSrc[ 51]; - pDst[ 52] = pSrc[ 52]; pDst[ 53] = pSrc[ 53]; - pDst[ 54] = pSrc[ 54]; pDst[ 55] = pSrc[ 55]; - pDst[ 56] = pSrc[ 56]; pDst[ 57] = pSrc[ 57]; - pDst[ 58] = pSrc[ 58]; pDst[ 59] = pSrc[ 59]; - pDst[ 60] = pSrc[ 60]; pDst[ 61] = pSrc[ 61]; - pDst[ 62] = pSrc[ 62]; pDst[ 63] = pSrc[ 63]; - pDst[ 64] = pSrc[ 64]; pDst[ 65] = pSrc[ 65]; - pDst[ 66] = pSrc[ 66]; pDst[ 67] = pSrc[ 67]; - pDst[ 68] = pSrc[ 68]; pDst[ 69] = pSrc[ 69]; - pDst[ 70] = pSrc[ 70]; pDst[ 71] = pSrc[ 71]; - pDst[ 72] = pSrc[ 72]; pDst[ 73] = pSrc[ 73]; - pDst[ 74] = pSrc[ 74]; pDst[ 75] = pSrc[ 75]; - pDst[ 76] = pSrc[ 76]; pDst[ 77] = pSrc[ 77]; - pDst[ 78] = pSrc[ 78]; pDst[ 79] = pSrc[ 79]; - pDst[ 80] = pSrc[ 80]; pDst[ 81] = pSrc[ 81]; - pDst[ 82] = pSrc[ 82]; pDst[ 83] = pSrc[ 83]; - pDst[ 84] = pSrc[ 84]; pDst[ 85] = pSrc[ 85]; - pDst[ 86] = pSrc[ 86]; pDst[ 87] = pSrc[ 87]; - pDst[ 88] = pSrc[ 88]; pDst[ 89] = pSrc[ 89]; - pDst[ 90] = pSrc[ 90]; pDst[ 91] = pSrc[ 91]; - pDst[ 92] = pSrc[ 92]; pDst[ 93] = pSrc[ 93]; - pDst[ 94] = pSrc[ 94]; pDst[ 95] = pSrc[ 95]; - pDst[ 96] = pSrc[ 96]; pDst[ 97] = pSrc[ 97]; - pDst[ 98] = pSrc[ 98]; pDst[ 99] = pSrc[ 99]; - pDst[100] = pSrc[100]; pDst[101] = pSrc[101]; - pDst[102] = pSrc[102]; pDst[103] = pSrc[103]; - pDst[104] = pSrc[104]; pDst[105] = pSrc[105]; - pDst[106] = pSrc[106]; pDst[107] = pSrc[107]; - pDst[108] = pSrc[108]; pDst[109] = pSrc[109]; - pDst[110] = pSrc[110]; pDst[111] = pSrc[111]; - pDst[112] = pSrc[112]; pDst[113] = pSrc[113]; - pDst[114] = pSrc[114]; pDst[115] = pSrc[115]; - pDst[116] = pSrc[116]; pDst[117] = pSrc[117]; - pDst[118] = pSrc[118]; pDst[119] = pSrc[119]; - pDst[120] = pSrc[120]; pDst[121] = pSrc[121]; - pDst[122] = pSrc[122]; pDst[123] = pSrc[123]; - pDst[124] = pSrc[124]; pDst[125] = pSrc[125]; - pDst[126] = pSrc[126]; pDst[127] = pSrc[127]; - pDst[128] = pSrc[128]; pDst[129] = pSrc[129]; - pDst[130] = pSrc[130]; pDst[131] = pSrc[131]; - pDst[132] = pSrc[132]; pDst[133] = pSrc[133]; - pDst[134] = pSrc[134]; pDst[135] = pSrc[135]; - pDst[136] = pSrc[136]; pDst[137] = pSrc[137]; - pDst[138] = pSrc[138]; pDst[139] = pSrc[139]; - pDst[140] = pSrc[140]; pDst[141] = pSrc[141]; - pDst[142] = pSrc[142]; pDst[143] = pSrc[143]; - pDst[144] = pSrc[144]; pDst[145] = pSrc[145]; - pDst[146] = pSrc[146]; pDst[147] = pSrc[147]; - pDst[148] = pSrc[148]; pDst[149] = pSrc[149]; - pDst[150] = pSrc[150]; pDst[151] = pSrc[151]; - pDst[152] = pSrc[152]; pDst[153] = pSrc[153]; - pDst[154] = pSrc[154]; pDst[155] = pSrc[155]; - pDst[156] = pSrc[156]; pDst[157] = pSrc[157]; - pDst[158] = pSrc[158]; pDst[159] = pSrc[159]; - pDst[160] = pSrc[160]; pDst[161] = pSrc[161]; - pDst[162] = pSrc[162]; pDst[163] = pSrc[163]; - pDst[164] = pSrc[164]; pDst[165] = pSrc[165]; - pDst[166] = pSrc[166]; pDst[167] = pSrc[167]; - pDst[168] = pSrc[168]; pDst[169] = pSrc[169]; - pDst[170] = pSrc[170]; pDst[171] = pSrc[171]; - pDst[172] = pSrc[172]; pDst[173] = pSrc[173]; - pDst[174] = pSrc[174]; pDst[175] = pSrc[175]; - pDst[176] = pSrc[176]; pDst[177] = pSrc[177]; - pDst[178] = pSrc[178]; pDst[179] = pSrc[179]; - pDst[180] = pSrc[180]; pDst[181] = pSrc[181]; - pDst[182] = pSrc[182]; pDst[183] = pSrc[183]; - pDst[184] = pSrc[184]; pDst[185] = pSrc[185]; - pDst[186] = pSrc[186]; pDst[187] = pSrc[187]; - pDst[188] = pSrc[188]; pDst[189] = pSrc[189]; - pDst[190] = pSrc[190]; pDst[191] = pSrc[191]; - pDst[192] = pSrc[192]; pDst[193] = pSrc[193]; - pDst[194] = pSrc[194]; pDst[195] = pSrc[195]; - pDst[196] = pSrc[196]; pDst[197] = pSrc[197]; - pDst[198] = pSrc[198]; pDst[199] = pSrc[199]; - pDst[200] = pSrc[200]; pDst[201] = pSrc[201]; - pDst[202] = pSrc[202]; pDst[203] = pSrc[203]; - pDst[204] = pSrc[204]; pDst[205] = pSrc[205]; - pDst[206] = pSrc[206]; pDst[207] = pSrc[207]; - pDst[208] = pSrc[208]; pDst[209] = pSrc[209]; - pDst[210] = pSrc[210]; pDst[211] = pSrc[211]; - pDst[212] = pSrc[212]; pDst[213] = pSrc[213]; - pDst[214] = pSrc[214]; pDst[215] = pSrc[215]; - pDst[216] = pSrc[216]; pDst[217] = pSrc[217]; - pDst[218] = pSrc[218]; pDst[219] = pSrc[219]; - pDst[220] = pSrc[220]; pDst[221] = pSrc[221]; - pDst[222] = pSrc[222]; pDst[223] = pSrc[223]; - pDst[224] = pSrc[224]; pDst[225] = pSrc[225]; - pDst[226] = pSrc[226]; pDst[227] = pSrc[227]; - pDst[228] = pSrc[228]; pDst[229] = pSrc[229]; - pDst[230] = pSrc[230]; pDst[231] = pSrc[231]; - pDst[232] = pSrc[232]; pDst[233] = pSrc[233]; - pDst[234] = pSrc[234]; pDst[235] = pSrc[235]; - pDst[236] = pSrc[236]; pDst[237] = pSrc[237]; - pDst[238] = pSrc[238]; pDst[239] = pSrc[239]; - pDst[240] = pSrc[240]; pDst[241] = pSrc[241]; - pDst[242] = pSrc[242]; pDst[243] = pSrc[243]; - pDst[244] = pSrc[244]; pDst[245] = pSrc[245]; - pDst[246] = pSrc[246]; pDst[247] = pSrc[247]; - pDst[248] = pSrc[248]; pDst[249] = pSrc[249]; - pDst[250] = pSrc[250]; pDst[251] = pSrc[251]; - pDst[252] = pSrc[252]; pDst[253] = pSrc[253]; - pDst[254] = pSrc[254]; pDst[255] = pSrc[255]; - -#endif - -} - -/* - * ATIMach64HideCursor -- - * - * Turn off hardware cursor. - */ -static void -ATIMach64HideCursor -( - ScrnInfoPtr pScreenInfo -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - if (!(pATI->NewHW.gen_test_cntl & GEN_CUR_EN)) - return; - - pATI->NewHW.gen_test_cntl &= ~GEN_CUR_EN; - out8(GEN_TEST_CNTL, GetByte(pATI->NewHW.gen_test_cntl, 0)); -} - -/* - * ATIMach64ShowCursor -- - * - * Turn on hardware cursor. - */ -static void -ATIMach64ShowCursor -( - ScrnInfoPtr pScreenInfo -) -{ - ATIPtr pATI = ATIPTR(pScreenInfo); - - if (pATI->NewHW.gen_test_cntl & GEN_CUR_EN) - return; - - pATI->NewHW.gen_test_cntl |= GEN_CUR_EN; - out8(GEN_TEST_CNTL, GetByte(pATI->NewHW.gen_test_cntl, 0)); -} - -/* - * ATIMach64UseHWCursor -- - * - * Notify cursor layer whether a hardware cursor is configured. - */ -static Bool -ATIMach64UseHWCursor -( - ScreenPtr pScreen, - CursorPtr pCursor -) -{ - ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; - ATIPtr pATI = ATIPTR(pScreenInfo); - - if (!pATI->CursorBase) - return FALSE; - -#ifndef AVOID_CPIO - - /* - * For some reason, the hardware cursor isn't vertically scaled when a VGA - * doublescanned or multiscanned mode is in effect. - */ - if (pATI->NewHW.crtc == ATI_CRTC_MACH64) - return TRUE; - if ((pScreenInfo->currentMode->Flags & V_DBLSCAN) || - (pScreenInfo->currentMode->VScan > 1)) - return FALSE; - -#endif /* AVOID_CPIO */ - - return TRUE; -} - -/* - * ATIMach64CursorInit -- - * - * Initialise xf86CursorInfoRec fields with information specific to Mach64 - * variants. - */ -Bool -ATIMach64CursorInit -( - xf86CursorInfoPtr pCursorInfo -) -{ - /* - * For Mach64 variants, toggling hardware cursors on and off causes - * display artifacts. Ask the cursor support layers to always paint the - * cursor (whether or not it is entirely transparent) and to not hide the - * cursor when reloading its image. The three reasons behind turning off - * the hardware cursor that remain are when it moves to a different screen, - * on a switch to a software cursor or to a different virtual console. - */ - pCursorInfo->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | - HARDWARE_CURSOR_INVERT_MASK | - HARDWARE_CURSOR_SHOW_TRANSPARENT | - HARDWARE_CURSOR_UPDATE_UNHIDDEN | - HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | - -#if X_BYTE_ORDER != X_LITTLE_ENDIAN - - HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | - -#endif /* X_BYTE_ORDER */ - - HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1; - pCursorInfo->MaxWidth = pCursorInfo->MaxHeight = 64; - - pCursorInfo->SetCursorColors = ATIMach64SetCursorColours; - pCursorInfo->SetCursorPosition = ATIMach64SetCursorPosition; - pCursorInfo->LoadCursorImage = ATIMach64LoadCursorImage; - pCursorInfo->HideCursor = ATIMach64HideCursor; - pCursorInfo->ShowCursor = ATIMach64ShowCursor; - pCursorInfo->UseHWCursor = ATIMach64UseHWCursor; - - return TRUE; -} diff --git a/src/atimach64.h b/src/atimach64.h index e6e1eaa7..dd2e9a9b 100644 --- a/src/atimach64.h +++ b/src/atimach64.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.h,v 1.16 2003/01/01 19:16:32 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.h,v 1.17 2003/04/23 21:51:28 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -27,12 +27,6 @@ #include "atipriv.h" #include "atiproto.h" -#include "xaa.h" -#include "xf86Cursor.h" - -#define ATIMach64MaxX 8191 -#define ATIMach64MaxY 32767 - extern void ATIMach64PreInit FunctionPrototype((ScrnInfoPtr, ATIPtr, ATIHWPtr)); extern void ATIMach64Save FunctionPrototype((ATIPtr, ATIHWPtr)); @@ -43,8 +37,4 @@ extern void ATIMach64Set FunctionPrototype((ATIPtr, ATIHWPtr)); extern void ATIMach64SaveScreen FunctionPrototype((ATIPtr, int)); extern void ATIMach64SetDPMSMode FunctionPrototype((ScrnInfoPtr, ATIPtr, int)); -extern int ATIMach64AccelInit FunctionPrototype((ATIPtr, XAAInfoRecPtr)); - -extern Bool ATIMach64CursorInit FunctionPrototype((xf86CursorInfoPtr)); - #endif /* ___ATIMACH64_H___ */ diff --git a/src/atimach64accel.c b/src/atimach64accel.c new file mode 100644 index 00000000..12029187 --- /dev/null +++ b/src/atimach64accel.c @@ -0,0 +1,862 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64accel.c,v 1.1 2003/04/23 21:51:28 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ +/* + * Copyright 1999-2000 Precision Insight, Inc., Cedar Park, Texas. + * 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 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 + * PRECISION INSIGHT AND/OR ITS 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. + */ + +#include "ati.h" +#include "atichip.h" +#include "atimach64accel.h" +#include "atimach64io.h" +#include "atipriv.h" +#include "atiregs.h" + +#include "miline.h" + +/* Used to test MMIO cache integrity in ATIMach64Sync() */ +#define TestRegisterCaching(_Register) \ + if (RegisterIsCached(_Register) && \ + (CacheSlot(_Register) != inm(_Register))) \ + { \ + UncacheRegister(_Register); \ + xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, \ + #_Register " MMIO write cache disabled!\n"); \ + } + +/* + * X-to-Mach64 mix translation table. + */ +static CARD8 ATIMach64ALU[16] = +{ + MIX_0, /* GXclear */ + MIX_AND, /* GXand */ + MIX_SRC_AND_NOT_DST, /* GXandReverse */ + MIX_SRC, /* GXcopy */ + MIX_NOT_SRC_AND_DST, /* GXandInverted */ + MIX_DST, /* GXnoop */ + MIX_XOR, /* GXxor */ + MIX_OR, /* GXor */ + MIX_NOR, /* GXnor */ + MIX_XNOR, /* GXequiv */ + MIX_NOT_DST, /* GXinvert */ + MIX_SRC_OR_NOT_DST, /* GXorReverse */ + MIX_NOT_SRC, /* GXcopyInverted */ + MIX_NOT_SRC_OR_DST, /* GXorInverted */ + MIX_NAND, /* GXnand */ + MIX_1 /* GXset */ +}; + +/* + * ATIMach64ValidateClip -- + * + * This function ensures the current scissor settings do not interfere with + * the current draw request. + */ +static void +ATIMach64ValidateClip +( + ATIPtr pATI, + int sc_left, + int sc_right, + int sc_top, + int sc_bottom +) +{ + if ((sc_left < (int)pATI->sc_left) || (sc_right > (int)pATI->sc_right)) + { + outf(SC_LEFT_RIGHT, pATI->sc_left_right); + pATI->sc_left = pATI->NewHW.sc_left; + pATI->sc_right = pATI->NewHW.sc_right; + } + + if ((sc_top < (int)pATI->sc_top) || (sc_bottom > (int)pATI->sc_bottom)) + { + outf(SC_TOP_BOTTOM, pATI->sc_top_bottom); + pATI->sc_top = pATI->NewHW.sc_top; + pATI->sc_bottom = pATI->NewHW.sc_bottom; + } +} + +/* + * ATIMach64Sync -- + * + * This is called to wait for the draw engine to become idle. + */ +void +ATIMach64Sync +( + ScrnInfoPtr pScreenInfo +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + ATIMach64WaitForIdle(pATI); + if (pATI->pXAAInfo) + pATI->pXAAInfo->NeedToSync = FALSE; + + if (pATI->OptionMMIOCache && pATI->OptionTestMMIOCache) + { + /* + * For debugging purposes, attempt to verify that each cached register + * should actually be cached. + */ + TestRegisterCaching(SRC_CNTL); + + TestRegisterCaching(HOST_CNTL); + + TestRegisterCaching(PAT_REG0); + TestRegisterCaching(PAT_REG1); + TestRegisterCaching(PAT_CNTL); + + if (RegisterIsCached(SC_LEFT_RIGHT) && /* Special case */ + (CacheSlot(SC_LEFT_RIGHT) != + (SetWord(inm(SC_RIGHT), 1) | SetWord(inm(SC_LEFT), 0)))) + { + UncacheRegister(SC_LEFT_RIGHT); + xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, + "SC_LEFT_RIGHT write cache disabled!\n"); + } + + if (RegisterIsCached(SC_TOP_BOTTOM) && /* Special case */ + (CacheSlot(SC_TOP_BOTTOM) != + (SetWord(inm(SC_BOTTOM), 1) | SetWord(inm(SC_TOP), 0)))) + { + UncacheRegister(SC_TOP_BOTTOM); + xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, + "SC_TOP_BOTTOM write cache disabled!\n"); + } + + TestRegisterCaching(DP_BKGD_CLR); + TestRegisterCaching(DP_FRGD_CLR); + TestRegisterCaching(DP_WRITE_MASK); + TestRegisterCaching(DP_MIX); + + TestRegisterCaching(CLR_CMP_CLR); + TestRegisterCaching(CLR_CMP_MSK); + TestRegisterCaching(CLR_CMP_CNTL); + + if (pATI->Block1Base) + { + TestRegisterCaching(OVERLAY_Y_X_START); + TestRegisterCaching(OVERLAY_Y_X_END); + + TestRegisterCaching(OVERLAY_GRAPHICS_KEY_CLR); + TestRegisterCaching(OVERLAY_GRAPHICS_KEY_MSK); + + TestRegisterCaching(OVERLAY_KEY_CNTL); + + TestRegisterCaching(OVERLAY_SCALE_INC); + TestRegisterCaching(OVERLAY_SCALE_CNTL); + + TestRegisterCaching(SCALER_HEIGHT_WIDTH); + + TestRegisterCaching(SCALER_TEST); + + TestRegisterCaching(VIDEO_FORMAT); + + if (pATI->Chip < ATI_CHIP_264VTB) + { + TestRegisterCaching(BUF0_OFFSET); + TestRegisterCaching(BUF0_PITCH); + TestRegisterCaching(BUF1_OFFSET); + TestRegisterCaching(BUF1_PITCH); + } + else + { + TestRegisterCaching(SCALER_BUF0_OFFSET); + TestRegisterCaching(SCALER_BUF1_OFFSET); + TestRegisterCaching(SCALER_BUF_PITCH); + + TestRegisterCaching(OVERLAY_EXCLUSIVE_HORZ); + TestRegisterCaching(OVERLAY_EXCLUSIVE_VERT); + + if (pATI->Chip >= ATI_CHIP_264GTPRO) + { + TestRegisterCaching(SCALER_COLOUR_CNTL); + + TestRegisterCaching(SCALER_H_COEFF0); + TestRegisterCaching(SCALER_H_COEFF1); + TestRegisterCaching(SCALER_H_COEFF2); + TestRegisterCaching(SCALER_H_COEFF3); + TestRegisterCaching(SCALER_H_COEFF4); + + TestRegisterCaching(SCALER_BUF0_OFFSET_U); + TestRegisterCaching(SCALER_BUF0_OFFSET_V); + TestRegisterCaching(SCALER_BUF1_OFFSET_U); + TestRegisterCaching(SCALER_BUF1_OFFSET_V); + } + } + } + } + + /* + * For VTB's and later, the first CPU read of the framebuffer will return + * zeroes, so do it here. This appears to be due to some kind of engine + * caching of framebuffer data I haven't found any way of disabling, or + * otherwise circumventing. Thanks to Mark Vojkovich for the suggestion. + */ + pATI = *(volatile ATIPtr *)pATI->pMemory; +} + +/* + * ATIMach64SetupForScreenToScreenCopy -- + * + * This function sets up the draw engine for a series of screen-to-screen copy + * operations. + */ +static void +ATIMach64SetupForScreenToScreenCopy +( + ScrnInfoPtr pScreenInfo, + int xdir, + int ydir, + int rop, + unsigned int planemask, + int TransparencyColour +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + ATIMach64WaitForFIFO(pATI, 3); + outf(DP_WRITE_MASK, planemask); + outf(DP_SRC, DP_MONO_SRC_ALLONES | + SetBits(SRC_BLIT, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC)); + outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX)); + +#ifdef AVOID_DGA + + if (TransparencyColour == -1) + +#else /* AVOID_DGA */ + + if (!pATI->XAAForceTransBlit && (TransparencyColour == -1)) + +#endif /* AVOID_DGA */ + + { + outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); + } + else + { + ATIMach64WaitForFIFO(pATI, 2); + outf(CLR_CMP_CLR, TransparencyColour); + outf(CLR_CMP_CNTL, CLR_CMP_FN_EQUAL | CLR_CMP_SRC_2D); + } + + pATI->dst_cntl = 0; + + if (ydir > 0) + pATI->dst_cntl |= DST_Y_DIR; + if (xdir > 0) + pATI->dst_cntl |= DST_X_DIR; + + if (pATI->XModifier == 1) + outf(DST_CNTL, pATI->dst_cntl); + else + pATI->dst_cntl |= DST_24_ROT_EN; +} + +/* + * ATIMach64SubsequentScreenToScreenCopy -- + * + * This function performs a screen-to-screen copy operation. + */ +static void +ATIMach64SubsequentScreenToScreenCopy +( + ScrnInfoPtr pScreenInfo, + int xSrc, + int ySrc, + int xDst, + int yDst, + int w, + int h +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + xSrc *= pATI->XModifier; + xDst *= pATI->XModifier; + w *= pATI->XModifier; + + /* Disable clipping if it gets in the way */ + ATIMach64ValidateClip(pATI, xDst, xDst + w - 1, yDst, yDst + h - 1); + + if (!(pATI->dst_cntl & DST_X_DIR)) + { + xSrc += w - 1; + xDst += w - 1; + } + + if (!(pATI->dst_cntl & DST_Y_DIR)) + { + ySrc += h - 1; + yDst += h - 1; + } + + if (pATI->XModifier != 1) + outf(DST_CNTL, pATI->dst_cntl | SetBits((xDst / 4) % 6, DST_24_ROT)); + + ATIMach64WaitForFIFO(pATI, 4); + outf(SRC_Y_X, SetWord(xSrc, 1) | SetWord(ySrc, 0)); + outf(SRC_WIDTH1, w); + outf(DST_Y_X, SetWord(xDst, 1) | SetWord(yDst, 0)); + outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0)); +} + +/* + * ATIMach64SetupForSolidFill -- + * + * This function sets up the draw engine for a series of solid fills. + */ +static void +ATIMach64SetupForSolidFill +( + ScrnInfoPtr pScreenInfo, + int colour, + int rop, + unsigned int planemask +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + ATIMach64WaitForFIFO(pATI, 5); + outf(DP_WRITE_MASK, planemask); + outf(DP_SRC, DP_MONO_SRC_ALLONES | + SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC)); + outf(DP_FRGD_CLR, colour); + outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX)); + + outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); + + if (pATI->XModifier == 1) + outf(DST_CNTL, DST_X_DIR | DST_Y_DIR); +} + +/* + * ATIMach64SubsequentSolidFillRect -- + * + * This function performs a solid rectangle fill. + */ +static void +ATIMach64SubsequentSolidFillRect +( + ScrnInfoPtr pScreenInfo, + int x, + int y, + int w, + int h +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + if (pATI->XModifier != 1) + { + x *= pATI->XModifier; + w *= pATI->XModifier; + + outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) | + (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)); + } + + /* Disable clipping if it gets in the way */ + ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1); + + ATIMach64WaitForFIFO(pATI, 2); + outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); + outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0)); +} + +/* + * ATIMach64SetupForSolidLine -- + * + * This function sets up the draw engine for a series of solid lines. It is + * not used for 24bpp because the engine doesn't support it. + */ +static void +ATIMach64SetupForSolidLine +( + ScrnInfoPtr pScreenInfo, + int colour, + int rop, + unsigned int planemask +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + ATIMach64WaitForFIFO(pATI, 5); + outf(DP_WRITE_MASK, planemask); + outf(DP_SRC, DP_MONO_SRC_ALLONES | + SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC)); + outf(DP_FRGD_CLR, colour); + outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX)); + + outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); + + ATIMach64ValidateClip(pATI, pATI->NewHW.sc_left, pATI->NewHW.sc_right, + pATI->NewHW.sc_top, pATI->NewHW.sc_bottom); +} + +/* + * ATIMach64SubsequentSolidHorVertLine -- + * + * This is called to draw a solid horizontal or vertical line. This does a + * one-pixel wide solid fill. + */ +static void +ATIMach64SubsequentSolidHorVertLine +( + ScrnInfoPtr pScreenInfo, + int x, + int y, + int len, + int dir +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + ATIMach64WaitForFIFO(pATI, 3); + outf(DST_CNTL, DST_X_DIR | DST_Y_DIR); + outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); + + if (dir == DEGREES_0) + outf(DST_HEIGHT_WIDTH, SetWord(len, 1) | SetWord(1, 0)); + else /* if (dir == DEGREES_270) */ + outf(DST_HEIGHT_WIDTH, SetWord(1, 1) | SetWord(len, 0)); +} + +/* + * ATIMach64SubsequentSolidBresenhamLine -- + * + * This function draws a line using the Bresenham line engine. + */ +static void +ATIMach64SubsequentSolidBresenhamLine +( + ScrnInfoPtr pScreenInfo, + int x, + int y, + int major, + int minor, + int err, + int len, + int octant +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + CARD32 dst_cntl = DST_LAST_PEL; + + if (octant & YMAJOR) + dst_cntl |= DST_Y_MAJOR; + + if (!(octant & XDECREASING)) + dst_cntl |= DST_X_DIR; + + if (!(octant & YDECREASING)) + dst_cntl |= DST_Y_DIR; + + ATIMach64WaitForFIFO(pATI, 6); + outf(DST_CNTL, dst_cntl); + outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); + outf(DST_BRES_ERR, minor + err); + outf(DST_BRES_INC, minor); + outf(DST_BRES_DEC, minor - major); + outf(DST_BRES_LNTH, len); +} + +/* + * ATIMach64SetupForMono8x8PatternFill -- + * + * This function sets up the draw engine for a series of 8x8 1bpp pattern + * fills. + */ +static void +ATIMach64SetupForMono8x8PatternFill +( + ScrnInfoPtr pScreenInfo, + int patx, + int paty, + int fg, + int bg, + int rop, + unsigned int planemask +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + ATIMach64WaitForFIFO(pATI, 3); + outf(DP_WRITE_MASK, planemask); + outf(DP_SRC, DP_MONO_SRC_PATTERN | + SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC)); + outf(DP_FRGD_CLR, fg); + + if (bg == -1) + { + outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) | + SetBits(MIX_DST, DP_BKGD_MIX)); + } + else + { + ATIMach64WaitForFIFO(pATI, 2); + outf(DP_BKGD_CLR, bg); + outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) | + SetBits(ATIMach64ALU[rop], DP_BKGD_MIX)); + } + + ATIMach64WaitForFIFO(pATI, 4); + outf(PAT_REG0, patx); + outf(PAT_REG1, paty); + outf(PAT_CNTL, PAT_MONO_EN); + + outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); + + if (pATI->XModifier == 1) + outf(DST_CNTL, DST_X_DIR | DST_Y_DIR); +} + +/* + * ATIMach64SubsequentMono8x8PatternFillRect -- + * + * This function performs an 8x8 1bpp pattern fill. + */ +static void +ATIMach64SubsequentMono8x8PatternFillRect +( + ScrnInfoPtr pScreenInfo, + int patx, + int paty, + int x, + int y, + int w, + int h +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + if (pATI->XModifier != 1) + { + x *= pATI->XModifier; + w *= pATI->XModifier; + + outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) | + (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)); + } + + /* Disable clipping if it gets in the way */ + ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1); + + ATIMach64WaitForFIFO(pATI, 2); + outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); + outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0)); +} + +/* + * ATIMach64SetupForScanlineCPUToScreenColorExpandFill -- + * + * This function sets up the engine for a series of colour expansion fills. + */ +static void +ATIMach64SetupForScanlineCPUToScreenColorExpandFill +( + ScrnInfoPtr pScreenInfo, + int fg, + int bg, + int rop, + unsigned int planemask +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + ATIMach64WaitForFIFO(pATI, 3); + outf(DP_WRITE_MASK, planemask); + outf(DP_SRC, DP_MONO_SRC_HOST | + SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC)); + outf(DP_FRGD_CLR, fg); + + if (bg == -1) + { + outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) | + SetBits(MIX_DST, DP_BKGD_MIX)); + } + else + { + ATIMach64WaitForFIFO(pATI, 2); + outf(DP_BKGD_CLR, bg); + outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) | + SetBits(ATIMach64ALU[rop], DP_BKGD_MIX)); + } + + outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE); + + if (pATI->XModifier == 1) + outf(DST_CNTL, DST_X_DIR | DST_Y_DIR); +} + +/* + * ATIMach64SubsequentScanlineCPUToScreenColorExpandFill -- + * + * This function sets up the engine for a single colour expansion fill. + */ +static void +ATIMach64SubsequentScanlineCPUToScreenColorExpandFill +( + ScrnInfoPtr pScreenInfo, + int x, + int y, + int w, + int h, + int skipleft +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + if (pATI->XModifier != 1) + { + x *= pATI->XModifier; + w *= pATI->XModifier; + skipleft *= pATI->XModifier; + + outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) | + (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN)); + } + + pATI->ExpansionBitmapWidth = (w + 31) / 32; + + ATIMach64WaitForFIFO(pATI, 3); + pATI->sc_left = x + skipleft; + pATI->sc_right = x + w - 1; + outf(SC_LEFT_RIGHT, + SetWord(pATI->sc_right, 1) | SetWord(pATI->sc_left, 0)); + outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); + outf(DST_HEIGHT_WIDTH, + SetWord(pATI->ExpansionBitmapWidth * 32, 1) | SetWord(h, 0)); +} + +/* + * ATIMach64SubsequentColorExpandScanline -- + * + * This function feeds a bitmap scanline to the engine for a colour expansion + * fill. This is written to do burst transfers for those platforms that can do + * them, and to improve CPU/engine concurrency. + */ +static void +ATIMach64SubsequentColorExpandScanline +( + ScrnInfoPtr pScreenInfo, + int iBuffer +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + CARD32 *pBitmapData = pATI->ExpansionBitmapScanlinePtr[iBuffer]; + int w = pATI->ExpansionBitmapWidth; + int nDWord; + + while (w > 0) + { + /* + * Transfers are done in chunks of up to 64 bytes in length (32 on + * earlier controllers). + */ + nDWord = w; + if (nDWord > pATI->nHostFIFOEntries) + nDWord = pATI->nHostFIFOEntries; + + /* Make enough FIFO slots available */ + ATIMach64WaitForFIFO(pATI, nDWord); + + /* + * Always start transfers on a chuck-sized boundary. Note that + * HOST_DATA_0 is actually on a 512-byte boundary, but *pBitmapData can + * only be guaranteed to be on a chunk-sized boundary. + * + * Transfer current chunk. With any luck, the compiler won't mangle + * this too badly... + */ + +# if defined(ATIMove32) + + { + ATIMove32(pATI->pHOST_DATA, pBitmapData, nDWord); + } + +# else + + { + volatile CARD32 *pDst; + CARD32 *pSrc; + unsigned int iDWord; + + iDWord = 16 - nDWord; + pDst = (volatile CARD32 *)pATI->pHOST_DATA - iDWord; + pSrc = pBitmapData - iDWord; + + switch (iDWord) + { + case 0: MMIO_MOVE32(pDst + 0, 0, *(pSrc + 0)); + case 1: MMIO_MOVE32(pDst + 1, 0, *(pSrc + 1)); + case 2: MMIO_MOVE32(pDst + 2, 0, *(pSrc + 2)); + case 3: MMIO_MOVE32(pDst + 3, 0, *(pSrc + 3)); + case 4: MMIO_MOVE32(pDst + 4, 0, *(pSrc + 4)); + case 5: MMIO_MOVE32(pDst + 5, 0, *(pSrc + 5)); + case 6: MMIO_MOVE32(pDst + 6, 0, *(pSrc + 6)); + case 7: MMIO_MOVE32(pDst + 7, 0, *(pSrc + 7)); + case 8: MMIO_MOVE32(pDst + 8, 0, *(pSrc + 8)); + case 9: MMIO_MOVE32(pDst + 9, 0, *(pSrc + 9)); + case 10: MMIO_MOVE32(pDst + 10, 0, *(pSrc + 10)); + case 11: MMIO_MOVE32(pDst + 11, 0, *(pSrc + 11)); + case 12: MMIO_MOVE32(pDst + 12, 0, *(pSrc + 12)); + case 13: MMIO_MOVE32(pDst + 13, 0, *(pSrc + 13)); + case 14: MMIO_MOVE32(pDst + 14, 0, *(pSrc + 14)); + case 15: MMIO_MOVE32(pDst + 15, 0, *(pSrc + 15)); + + default: /* Muffle compiler */ + break; + } + } + +# endif + + /* Step to next chunk */ + pBitmapData += nDWord; + w -= nDWord; + pATI->nAvailableFIFOEntries -= nDWord; + } + + pATI->EngineIsBusy = TRUE; +} + +/* + * ATIMach64AccelInit -- + * + * This function fills in structure fields needed for acceleration on Mach64 + * variants. + */ +int +ATIMach64AccelInit +( + ATIPtr pATI, + XAAInfoRecPtr pXAAInfo +) +{ + /* This doesn't seem quite right... */ + if (pATI->XModifier == 1) + { + pXAAInfo->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS; + +#ifndef AVOID_CPIO + + if (!pATI->BankInfo.BankSize) + +#endif /* AVOID_CPIO */ + + { + pXAAInfo->Flags |= LINEAR_FRAMEBUFFER; + } + } + + /* Sync */ + pXAAInfo->Sync = ATIMach64Sync; + + /* Screen-to-screen copy */ + pXAAInfo->SetupForScreenToScreenCopy = ATIMach64SetupForScreenToScreenCopy; + pXAAInfo->SubsequentScreenToScreenCopy = + ATIMach64SubsequentScreenToScreenCopy; + + /* Solid fills */ + pXAAInfo->SetupForSolidFill = ATIMach64SetupForSolidFill; + pXAAInfo->SubsequentSolidFillRect = ATIMach64SubsequentSolidFillRect; + + /* 8x8 mono pattern fills */ + pXAAInfo->Mono8x8PatternFillFlags = + +#if X_BYTE_ORDER != X_LITTLE_ENDIAN + + BIT_ORDER_IN_BYTE_MSBFIRST | + +#endif /* X_BYTE_ORDER */ + + HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_SCREEN_ORIGIN; + pXAAInfo->SetupForMono8x8PatternFill = ATIMach64SetupForMono8x8PatternFill; + pXAAInfo->SubsequentMono8x8PatternFillRect = + ATIMach64SubsequentMono8x8PatternFillRect; + + /* + * Use scanline version of colour expansion, not only for the non-ix86 + * case, but also to avoid PCI retries. + */ + pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags = + LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X | + CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD; + if (pATI->XModifier != 1) + pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags |= TRIPLE_BITS_24BPP; + pXAAInfo->NumScanlineColorExpandBuffers = 1; + + /* Align bitmap data on a 64-byte boundary */ + pATI->ExpansionBitmapWidth = /* DWord size in bits */ + ((pATI->displayWidth * pATI->XModifier) + 31) & ~31U; + pATI->ExpansionBitmapScanlinePtr[1] = + (CARD32 *)xnfalloc((pATI->ExpansionBitmapWidth >> 3) + 63); + pATI->ExpansionBitmapScanlinePtr[0] = + (pointer)(((unsigned long)pATI->ExpansionBitmapScanlinePtr[1] + 63) & + ~63UL); + pXAAInfo->ScanlineColorExpandBuffers = + (CARD8 **)pATI->ExpansionBitmapScanlinePtr; + pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill = + ATIMach64SetupForScanlineCPUToScreenColorExpandFill; + pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill = + ATIMach64SubsequentScanlineCPUToScreenColorExpandFill; + pXAAInfo->SubsequentColorExpandScanline = + ATIMach64SubsequentColorExpandScanline; + + /* The engine does not support the following primitives for 24bpp */ + if (pATI->XModifier != 1) + return ATIMach64MaxY; + + /* Solid lines */ + pXAAInfo->SetupForSolidLine = ATIMach64SetupForSolidLine; + pXAAInfo->SubsequentSolidHorVertLine = ATIMach64SubsequentSolidHorVertLine; + pXAAInfo->SubsequentSolidBresenhamLine = + ATIMach64SubsequentSolidBresenhamLine; + + return ATIMach64MaxY; +} diff --git a/src/atimach64accel.h b/src/atimach64accel.h new file mode 100644 index 00000000..88f90a05 --- /dev/null +++ b/src/atimach64accel.h @@ -0,0 +1,38 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64accel.h,v 1.1 2003/04/23 21:51:29 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#ifndef ___ATIMACH64ACCEL_H___ +#define ___ATIMACH64ACCEL_H___ 1 + +#include "atipriv.h" +#include "atiproto.h" + +#include "xaa.h" + +#define ATIMach64MaxX 8191 +#define ATIMach64MaxY 32767 + +extern int ATIMach64AccelInit FunctionPrototype((ATIPtr, XAAInfoRecPtr)); +extern void ATIMach64Sync FunctionPrototype((ScrnInfoPtr)); + +#endif /* ___ATIMACH64ACCEL_H___ */ diff --git a/src/atimach64cursor.c b/src/atimach64cursor.c new file mode 100644 index 00000000..8cd76dba --- /dev/null +++ b/src/atimach64cursor.c @@ -0,0 +1,400 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64cursor.c,v 1.1 2003/04/23 21:51:29 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#include "ati.h" +#include "aticrtc.h" +#include "atimach64accel.h" +#include "atimach64cursor.h" +#include "atimach64io.h" + +/* + * ATIMach64SetCursorColours -- + * + * Set hardware cursor foreground and background colours. + */ +static void +ATIMach64SetCursorColours +( + ScrnInfoPtr pScreenInfo, + int fg, + int bg +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + outr(CUR_CLR0, SetBits(fg, CUR_CLR)); + outr(CUR_CLR1, SetBits(bg, CUR_CLR)); +} + +/* + * ATIMach64SetCursorPosition -- + * + * Set position of hardware cursor. + */ +static void +ATIMach64SetCursorPosition +( + ScrnInfoPtr pScreenInfo, + int x, + int y +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + CARD16 CursorXOffset, CursorYOffset; + + /* Adjust x & y when the cursor is partially obscured */ + if (x < 0) + { + if ((CursorXOffset = -x) > 63) + CursorXOffset = 63; + x = 0; + } + else + { + CursorXOffset = pScreenInfo->frameX1 - pScreenInfo->frameX0; + if (x > CursorXOffset) + x = CursorXOffset; + CursorXOffset = 0; + } + + if (y < 0) + { + if ((CursorYOffset = -y) > 63) + CursorYOffset = 63; + y = 0; + } + else + { + CursorYOffset = pScreenInfo->frameY1 - pScreenInfo->frameY0; + if (y > CursorYOffset) + y = CursorYOffset; + CursorYOffset = 0; + } + + /* Adjust for multiscanned modes */ + if (pScreenInfo->currentMode->Flags & V_DBLSCAN) + y *= 2; + if (pScreenInfo->currentMode->VScan > 1) + y *= pScreenInfo->currentMode->VScan; + + do + { + if (CursorYOffset != pATI->CursorYOffset) + { + pATI->CursorYOffset = CursorYOffset; + outr(CUR_OFFSET, ((CursorYOffset << 4) + pATI->CursorOffset) >> 3); + } + else if (CursorXOffset == pATI->CursorXOffset) + break; + + pATI->CursorXOffset = CursorXOffset; + outr(CUR_HORZ_VERT_OFF, SetBits(CursorXOffset, CUR_HORZ_OFF) | + SetBits(CursorYOffset, CUR_VERT_OFF)); + } while (0); + + outr(CUR_HORZ_VERT_POSN, + SetBits(x, CUR_HORZ_POSN) | SetBits(y, CUR_VERT_POSN)); +} + +/* + * ATIMach64LoadCursorImage -- + * + * Copy hardware cursor image into offscreen video memory. + */ +static void +ATIMach64LoadCursorImage +( + ScrnInfoPtr pScreenInfo, + CARD8 *pImage +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + CARD32 *pSrc = (pointer)pImage; + volatile CARD32 *pDst = pATI->pCursorImage; + + /* Synchronise video memory accesses */ + ATIMach64Sync(pScreenInfo); + +# if defined(ATIMove32) + + { + ATIMove32(pDst, pSrc, 256); + } + +# else + + { + /* This is lengthy, but it does maximise burst modes */ + pDst[ 0] = pSrc[ 0]; pDst[ 1] = pSrc[ 1]; + pDst[ 2] = pSrc[ 2]; pDst[ 3] = pSrc[ 3]; + pDst[ 4] = pSrc[ 4]; pDst[ 5] = pSrc[ 5]; + pDst[ 6] = pSrc[ 6]; pDst[ 7] = pSrc[ 7]; + pDst[ 8] = pSrc[ 8]; pDst[ 9] = pSrc[ 9]; + pDst[ 10] = pSrc[ 10]; pDst[ 11] = pSrc[ 11]; + pDst[ 12] = pSrc[ 12]; pDst[ 13] = pSrc[ 13]; + pDst[ 14] = pSrc[ 14]; pDst[ 15] = pSrc[ 15]; + pDst[ 16] = pSrc[ 16]; pDst[ 17] = pSrc[ 17]; + pDst[ 18] = pSrc[ 18]; pDst[ 19] = pSrc[ 19]; + pDst[ 20] = pSrc[ 20]; pDst[ 21] = pSrc[ 21]; + pDst[ 22] = pSrc[ 22]; pDst[ 23] = pSrc[ 23]; + pDst[ 24] = pSrc[ 24]; pDst[ 25] = pSrc[ 25]; + pDst[ 26] = pSrc[ 26]; pDst[ 27] = pSrc[ 27]; + pDst[ 28] = pSrc[ 28]; pDst[ 29] = pSrc[ 29]; + pDst[ 30] = pSrc[ 30]; pDst[ 31] = pSrc[ 31]; + pDst[ 32] = pSrc[ 32]; pDst[ 33] = pSrc[ 33]; + pDst[ 34] = pSrc[ 34]; pDst[ 35] = pSrc[ 35]; + pDst[ 36] = pSrc[ 36]; pDst[ 37] = pSrc[ 37]; + pDst[ 38] = pSrc[ 38]; pDst[ 39] = pSrc[ 39]; + pDst[ 40] = pSrc[ 40]; pDst[ 41] = pSrc[ 41]; + pDst[ 42] = pSrc[ 42]; pDst[ 43] = pSrc[ 43]; + pDst[ 44] = pSrc[ 44]; pDst[ 45] = pSrc[ 45]; + pDst[ 46] = pSrc[ 46]; pDst[ 47] = pSrc[ 47]; + pDst[ 48] = pSrc[ 48]; pDst[ 49] = pSrc[ 49]; + pDst[ 50] = pSrc[ 50]; pDst[ 51] = pSrc[ 51]; + pDst[ 52] = pSrc[ 52]; pDst[ 53] = pSrc[ 53]; + pDst[ 54] = pSrc[ 54]; pDst[ 55] = pSrc[ 55]; + pDst[ 56] = pSrc[ 56]; pDst[ 57] = pSrc[ 57]; + pDst[ 58] = pSrc[ 58]; pDst[ 59] = pSrc[ 59]; + pDst[ 60] = pSrc[ 60]; pDst[ 61] = pSrc[ 61]; + pDst[ 62] = pSrc[ 62]; pDst[ 63] = pSrc[ 63]; + pDst[ 64] = pSrc[ 64]; pDst[ 65] = pSrc[ 65]; + pDst[ 66] = pSrc[ 66]; pDst[ 67] = pSrc[ 67]; + pDst[ 68] = pSrc[ 68]; pDst[ 69] = pSrc[ 69]; + pDst[ 70] = pSrc[ 70]; pDst[ 71] = pSrc[ 71]; + pDst[ 72] = pSrc[ 72]; pDst[ 73] = pSrc[ 73]; + pDst[ 74] = pSrc[ 74]; pDst[ 75] = pSrc[ 75]; + pDst[ 76] = pSrc[ 76]; pDst[ 77] = pSrc[ 77]; + pDst[ 78] = pSrc[ 78]; pDst[ 79] = pSrc[ 79]; + pDst[ 80] = pSrc[ 80]; pDst[ 81] = pSrc[ 81]; + pDst[ 82] = pSrc[ 82]; pDst[ 83] = pSrc[ 83]; + pDst[ 84] = pSrc[ 84]; pDst[ 85] = pSrc[ 85]; + pDst[ 86] = pSrc[ 86]; pDst[ 87] = pSrc[ 87]; + pDst[ 88] = pSrc[ 88]; pDst[ 89] = pSrc[ 89]; + pDst[ 90] = pSrc[ 90]; pDst[ 91] = pSrc[ 91]; + pDst[ 92] = pSrc[ 92]; pDst[ 93] = pSrc[ 93]; + pDst[ 94] = pSrc[ 94]; pDst[ 95] = pSrc[ 95]; + pDst[ 96] = pSrc[ 96]; pDst[ 97] = pSrc[ 97]; + pDst[ 98] = pSrc[ 98]; pDst[ 99] = pSrc[ 99]; + pDst[100] = pSrc[100]; pDst[101] = pSrc[101]; + pDst[102] = pSrc[102]; pDst[103] = pSrc[103]; + pDst[104] = pSrc[104]; pDst[105] = pSrc[105]; + pDst[106] = pSrc[106]; pDst[107] = pSrc[107]; + pDst[108] = pSrc[108]; pDst[109] = pSrc[109]; + pDst[110] = pSrc[110]; pDst[111] = pSrc[111]; + pDst[112] = pSrc[112]; pDst[113] = pSrc[113]; + pDst[114] = pSrc[114]; pDst[115] = pSrc[115]; + pDst[116] = pSrc[116]; pDst[117] = pSrc[117]; + pDst[118] = pSrc[118]; pDst[119] = pSrc[119]; + pDst[120] = pSrc[120]; pDst[121] = pSrc[121]; + pDst[122] = pSrc[122]; pDst[123] = pSrc[123]; + pDst[124] = pSrc[124]; pDst[125] = pSrc[125]; + pDst[126] = pSrc[126]; pDst[127] = pSrc[127]; + pDst[128] = pSrc[128]; pDst[129] = pSrc[129]; + pDst[130] = pSrc[130]; pDst[131] = pSrc[131]; + pDst[132] = pSrc[132]; pDst[133] = pSrc[133]; + pDst[134] = pSrc[134]; pDst[135] = pSrc[135]; + pDst[136] = pSrc[136]; pDst[137] = pSrc[137]; + pDst[138] = pSrc[138]; pDst[139] = pSrc[139]; + pDst[140] = pSrc[140]; pDst[141] = pSrc[141]; + pDst[142] = pSrc[142]; pDst[143] = pSrc[143]; + pDst[144] = pSrc[144]; pDst[145] = pSrc[145]; + pDst[146] = pSrc[146]; pDst[147] = pSrc[147]; + pDst[148] = pSrc[148]; pDst[149] = pSrc[149]; + pDst[150] = pSrc[150]; pDst[151] = pSrc[151]; + pDst[152] = pSrc[152]; pDst[153] = pSrc[153]; + pDst[154] = pSrc[154]; pDst[155] = pSrc[155]; + pDst[156] = pSrc[156]; pDst[157] = pSrc[157]; + pDst[158] = pSrc[158]; pDst[159] = pSrc[159]; + pDst[160] = pSrc[160]; pDst[161] = pSrc[161]; + pDst[162] = pSrc[162]; pDst[163] = pSrc[163]; + pDst[164] = pSrc[164]; pDst[165] = pSrc[165]; + pDst[166] = pSrc[166]; pDst[167] = pSrc[167]; + pDst[168] = pSrc[168]; pDst[169] = pSrc[169]; + pDst[170] = pSrc[170]; pDst[171] = pSrc[171]; + pDst[172] = pSrc[172]; pDst[173] = pSrc[173]; + pDst[174] = pSrc[174]; pDst[175] = pSrc[175]; + pDst[176] = pSrc[176]; pDst[177] = pSrc[177]; + pDst[178] = pSrc[178]; pDst[179] = pSrc[179]; + pDst[180] = pSrc[180]; pDst[181] = pSrc[181]; + pDst[182] = pSrc[182]; pDst[183] = pSrc[183]; + pDst[184] = pSrc[184]; pDst[185] = pSrc[185]; + pDst[186] = pSrc[186]; pDst[187] = pSrc[187]; + pDst[188] = pSrc[188]; pDst[189] = pSrc[189]; + pDst[190] = pSrc[190]; pDst[191] = pSrc[191]; + pDst[192] = pSrc[192]; pDst[193] = pSrc[193]; + pDst[194] = pSrc[194]; pDst[195] = pSrc[195]; + pDst[196] = pSrc[196]; pDst[197] = pSrc[197]; + pDst[198] = pSrc[198]; pDst[199] = pSrc[199]; + pDst[200] = pSrc[200]; pDst[201] = pSrc[201]; + pDst[202] = pSrc[202]; pDst[203] = pSrc[203]; + pDst[204] = pSrc[204]; pDst[205] = pSrc[205]; + pDst[206] = pSrc[206]; pDst[207] = pSrc[207]; + pDst[208] = pSrc[208]; pDst[209] = pSrc[209]; + pDst[210] = pSrc[210]; pDst[211] = pSrc[211]; + pDst[212] = pSrc[212]; pDst[213] = pSrc[213]; + pDst[214] = pSrc[214]; pDst[215] = pSrc[215]; + pDst[216] = pSrc[216]; pDst[217] = pSrc[217]; + pDst[218] = pSrc[218]; pDst[219] = pSrc[219]; + pDst[220] = pSrc[220]; pDst[221] = pSrc[221]; + pDst[222] = pSrc[222]; pDst[223] = pSrc[223]; + pDst[224] = pSrc[224]; pDst[225] = pSrc[225]; + pDst[226] = pSrc[226]; pDst[227] = pSrc[227]; + pDst[228] = pSrc[228]; pDst[229] = pSrc[229]; + pDst[230] = pSrc[230]; pDst[231] = pSrc[231]; + pDst[232] = pSrc[232]; pDst[233] = pSrc[233]; + pDst[234] = pSrc[234]; pDst[235] = pSrc[235]; + pDst[236] = pSrc[236]; pDst[237] = pSrc[237]; + pDst[238] = pSrc[238]; pDst[239] = pSrc[239]; + pDst[240] = pSrc[240]; pDst[241] = pSrc[241]; + pDst[242] = pSrc[242]; pDst[243] = pSrc[243]; + pDst[244] = pSrc[244]; pDst[245] = pSrc[245]; + pDst[246] = pSrc[246]; pDst[247] = pSrc[247]; + pDst[248] = pSrc[248]; pDst[249] = pSrc[249]; + pDst[250] = pSrc[250]; pDst[251] = pSrc[251]; + pDst[252] = pSrc[252]; pDst[253] = pSrc[253]; + pDst[254] = pSrc[254]; pDst[255] = pSrc[255]; + } + +#endif + +} + +/* + * ATIMach64HideCursor -- + * + * Turn off hardware cursor. + */ +static void +ATIMach64HideCursor +( + ScrnInfoPtr pScreenInfo +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + if (!(pATI->NewHW.gen_test_cntl & GEN_CUR_EN)) + return; + + pATI->NewHW.gen_test_cntl &= ~GEN_CUR_EN; + out8(GEN_TEST_CNTL, GetByte(pATI->NewHW.gen_test_cntl, 0)); +} + +/* + * ATIMach64ShowCursor -- + * + * Turn on hardware cursor. + */ +static void +ATIMach64ShowCursor +( + ScrnInfoPtr pScreenInfo +) +{ + ATIPtr pATI = ATIPTR(pScreenInfo); + + if (pATI->NewHW.gen_test_cntl & GEN_CUR_EN) + return; + + pATI->NewHW.gen_test_cntl |= GEN_CUR_EN; + out8(GEN_TEST_CNTL, GetByte(pATI->NewHW.gen_test_cntl, 0)); +} + +/* + * ATIMach64UseHWCursor -- + * + * Notify cursor layer whether a hardware cursor is configured. + */ +static Bool +ATIMach64UseHWCursor +( + ScreenPtr pScreen, + CursorPtr pCursor +) +{ + ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum]; + ATIPtr pATI = ATIPTR(pScreenInfo); + + if (!pATI->CursorBase) + return FALSE; + +#ifndef AVOID_CPIO + + /* + * For some reason, the hardware cursor isn't vertically scaled when a VGA + * doublescanned or multiscanned mode is in effect. + */ + if (pATI->NewHW.crtc == ATI_CRTC_MACH64) + return TRUE; + if ((pScreenInfo->currentMode->Flags & V_DBLSCAN) || + (pScreenInfo->currentMode->VScan > 1)) + return FALSE; + +#endif /* AVOID_CPIO */ + + return TRUE; +} + +/* + * ATIMach64CursorInit -- + * + * Initialise xf86CursorInfoRec fields with information specific to Mach64 + * variants. + */ +Bool +ATIMach64CursorInit +( + xf86CursorInfoPtr pCursorInfo +) +{ + /* + * For Mach64 variants, toggling hardware cursors off and on causes display + * artifacts. Ask the cursor support layers to always paint the cursor + * (whether or not it is entirely transparent) and to not hide the cursor + * when reloading its image. The two remaining reasons for turning off the + * hardware cursor are when it moves to a different screen or on a switch + * to a different virtual console. + */ + pCursorInfo->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_INVERT_MASK | + HARDWARE_CURSOR_SHOW_TRANSPARENT | + HARDWARE_CURSOR_UPDATE_UNHIDDEN | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + +#if X_BYTE_ORDER != X_LITTLE_ENDIAN + + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + +#endif /* X_BYTE_ORDER */ + + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1; + pCursorInfo->MaxWidth = pCursorInfo->MaxHeight = 64; + + pCursorInfo->SetCursorColors = ATIMach64SetCursorColours; + pCursorInfo->SetCursorPosition = ATIMach64SetCursorPosition; + pCursorInfo->LoadCursorImage = ATIMach64LoadCursorImage; + pCursorInfo->HideCursor = ATIMach64HideCursor; + pCursorInfo->ShowCursor = ATIMach64ShowCursor; + pCursorInfo->UseHWCursor = ATIMach64UseHWCursor; + + return TRUE; +} diff --git a/src/atimach64cursor.h b/src/atimach64cursor.h new file mode 100644 index 00000000..6439f131 --- /dev/null +++ b/src/atimach64cursor.h @@ -0,0 +1,33 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64cursor.h,v 1.1 2003/04/23 21:51:29 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#ifndef ___ATIMACH64CURSOR_H___ +#define ___ATIMACH64CURSOR_H___ 1 + +#include "atiproto.h" + +#include "xf86Cursor.h" + +extern Bool ATIMach64CursorInit FunctionPrototype((xf86CursorInfoPtr)); + +#endif /* ___ATIMACH64CURSOR_H___ */ diff --git a/src/atimach64i2c.c b/src/atimach64i2c.c new file mode 100644 index 00000000..4cb565f6 --- /dev/null +++ b/src/atimach64i2c.c @@ -0,0 +1,466 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64i2c.c,v 1.1 2003/07/24 22:08:28 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#include "ati.h" +#include "atichip.h" +#include "atii2c.h" +#include "atimach64i2c.h" +#include "atimach64io.h" +#include "atituner.h" + +/* MPP_CONFIG register values */ +#define MPP_INIT pATI->NewHW.mpp_config + +#define MPP_WRITE (MPP_INIT ) +#define MPP_WRITEINC (MPP_INIT | (MPP_AUTO_INC_EN )) +#define MPP_READ (MPP_INIT | ( MPP_BUFFER_MODE_PREFETCH)) +#define MPP_READINC (MPP_INIT | (MPP_AUTO_INC_EN | MPP_BUFFER_MODE_PREFETCH)) + +/* + * ATIMach64MPPWaitForIdle -- + * + * Support function to wait for the Multimedia Peripheral Port to become idle. + * Currently, this function's return value indicates whether or not the port + * became idle within 512 polling iterations. For now, this value is ignored + * by the rest of the code, but might be used in the future. + */ +static Bool +ATIMach64MPPWaitForIdle +( + ATIPtr pATI +) +{ + CARD32 Count = 0x0200; + + while (in8(MPP_CONFIG + 3) & GetByte(MPP_BUSY, 3)) + { + if (!--Count) + return FALSE; + usleep(1); /* XXX Excessive? */ + } + + return TRUE; +} + +/* + * ATIMach64MPPSetAddress -- + * + * Sets a 16-bit ImpacTV address on the Multimedia Peripheral Port. + */ +static void +ATIMach64MPPSetAddress +( + ATIPtr pATI, + CARD16 Address +) +{ + ATIMach64MPPWaitForIdle(pATI); + outr(MPP_CONFIG, MPP_WRITEINC); + outr(MPP_ADDR, 0x00000008U); + out8(MPP_DATA, (CARD8)Address); + ATIMach64MPPWaitForIdle(pATI); + out8(MPP_DATA, (CARD8)(Address >> 8)); + ATIMach64MPPWaitForIdle(pATI); + outr(MPP_CONFIG, MPP_WRITE); + outr(MPP_ADDR, 0x00000018U); + ATIMach64MPPWaitForIdle(pATI); +} + +/* + * ATIMach64ImpacTVProbe -- + * + * This probes for an ImpacTV chip and returns its chip ID, or 0. + */ +static int +ATIMach64ImpacTVProbe +( + int iScreen, + ATIPtr pATI +) +{ + CARD8 ChipID = 0; + + /* Assume ATIModePreInit() has already been called */ + outr(MPP_STROBE_SEQ, pATI->NewHW.mpp_strobe_seq); + outr(TVO_CNTL, pATI->NewHW.tvo_cntl); + + outr(MPP_CONFIG, MPP_READ); + ATIMach64MPPWaitForIdle(pATI); + outr(MPP_ADDR, 0x0000000AU); + if (!(ChipID = in8(MPP_DATA))) + { + ATIMach64MPPWaitForIdle(pATI); + outr(MPP_ADDR, 0x00000023U); + if ((ChipID = in8(MPP_DATA)) != 0x54U) + { + ATIMach64MPPWaitForIdle(pATI); + outr(MPP_ADDR, 0x0000000BU); + ChipID = in8(MPP_DATA); + } + } + ATIMach64MPPWaitForIdle(pATI); + outr(MPP_CONFIG, MPP_WRITE); + + if (ChipID) + xf86DrvMsg(iScreen, X_PROBED, "ImpacTV chip ID 0x%02X detected.\n", + ChipID); + + return (int)(CARD16)ChipID; +} + +/* + * ATIMach64ImpacTVSetBits -- + * + * Controls I2C SDA and SCL lines through ImpacTV. + */ +static void +ATIMach64ImpacTVSetBits +( + ATII2CPtr pATII2C, + ATIPtr pATI, + CARD32 Bits +) +{ + pATII2C->I2CCur = Bits; + + ATIMach64MPPSetAddress(pATI, IT_I2C_CNTL); + + outr(MPP_CONFIG, MPP_WRITE); + + out8(MPP_DATA, (CARD8)Bits); + + ATIMach64MPPWaitForIdle(pATI); +} + +/* + * ATIMach64ImpacTVGetBits -- + * + * Returns the status of an ImpacTV's I2C control lines. + */ +static CARD32 +ATIMach64ImpacTVGetBits +( + ATIPtr pATI +) +{ + ATIMach64MPPSetAddress(pATI, IT_I2C_CNTL); + + outr(MPP_CONFIG, MPP_READ); + + ATIMach64MPPWaitForIdle(pATI); + + return in8(MPP_DATA); +} + +/* + * ATIMach64I2C_CNTLSetBits -- + * + * Controls SDA and SCL lines through a 3D Rage Pro's hardware assisted I2C. + */ +static void +ATIMach64I2C_CNTLSetBits +( + ATII2CPtr pATII2C, + ATIPtr pATI, + CARD32 Bits +) +{ + pATII2C->I2CCur = Bits; + + out8(I2C_CNTL_0 + 1, (CARD8)Bits); +} + +/* + * ATIMach64I2C_CNTLGetBits -- + * + * Returns the status of a 3D Rage Pro's hardware assisted I2C control lines. + */ +static CARD32 +ATIMach64I2C_CNTLGetBits +( + ATIPtr pATI +) +{ + return in8(I2C_CNTL_0 + 1); +} + +/* + * ATIMach64GP_IOSetBits -- + * + * Controls SDA and SCL control lines through a Mach64's GP_IO register. + */ +static void +ATIMach64GP_IOSetBits +( + ATII2CPtr pATII2C, + ATIPtr pATI, + CARD32 Bits +) +{ + pATII2C->I2CCur = Bits; + + outr(GP_IO, Bits); +} + +/* + * ATIMach64GP_IOGetBits -- + * + * Returns the status of I2C control lines through a Mach64's GP_IO register. + */ +static CARD32 +ATIMach64GP_IOGetBits +( + ATIPtr pATI +) +{ + return inr(GP_IO); +} + +#define GPIO1_MASK \ + (DAC_GIO_STATE_1 | DAC_GIO_DIR_1) +#define GPIO2_MASK \ + (GEN_GIO2_DATA_OUT | GEN_GIO2_DATA_IN | GEN_GIO2_WRITE) + +/* + * ATIMach64DAC_GENSetBits -- + * + * Controls SDA and SCL control lines through a Mach64's GEN_TEST_CNTL and + * DAC_CNTL registers. + */ +static void +ATIMach64DAC_GENSetBits +( + ATII2CPtr pATII2C, + ATIPtr pATI, + CARD32 Bits +) +{ + CARD32 tmp; + + pATII2C->I2CCur = Bits; + + tmp = inr(DAC_CNTL) & ~GPIO1_MASK; + outr(DAC_CNTL, tmp | (Bits & GPIO1_MASK)); + tmp = inr(GEN_TEST_CNTL) & ~GPIO2_MASK; + outr(GEN_TEST_CNTL, tmp | (Bits & GPIO2_MASK)); +} + +/* + * ATIMach64DAC_GENGetBits -- + * + * Returns the status of I2C control lines through a Mach64's GEN_TEST_CNTL and + * DAC_CNTL registers. + */ +static CARD32 +ATIMach64DAC_GENGetBits +( + ATIPtr pATI +) +{ + return (inr(DAC_CNTL) & GPIO1_MASK) | (inr(GEN_TEST_CNTL) & GPIO2_MASK); +} + +/* + * ATITVAddOnProbe -- + * + * Probe for an ATI-TV add-on card at specific addresses on an I2C bus. + */ +static Bool +ATITVAddOnProbe +( + ScrnInfoPtr pScreenInfo, + ATIPtr pATI, + I2CBusPtr pI2CBus +) +{ + I2CDevPtr pI2CDev = xnfcalloc(1, SizeOf(I2CDevRec)); + int Index; + I2CByte tmp; + + static const CARD8 ATITVAddOnAddresses[] = {0x70, 0x40, 0x78, 0x72, 0x42}; + + pI2CDev->DevName = "ATI-TV Add-on"; + pI2CDev->pI2CBus = pI2CBus; + pI2CDev->StartTimeout = pI2CBus->StartTimeout; + pI2CDev->BitTimeout = pI2CBus->BitTimeout; + pI2CDev->AcknTimeout = pI2CBus->AcknTimeout; + pI2CDev->ByteTimeout = pI2CBus->ByteTimeout; + + for (Index = 0; Index < NumberOf(ATITVAddOnAddresses); Index++) + { + pI2CDev->SlaveAddr = ATITVAddOnAddresses[Index]; + + if (xf86I2CFindDev(pI2CBus, pI2CDev->SlaveAddr)) + continue; + + tmp = 0xFFU; + + if (!(*pI2CBus->I2CWriteRead)(pI2CDev, &tmp, 1, NULL, 0) || + !(*pI2CBus->I2CWriteRead)(pI2CDev, NULL, 0, &tmp, 1) || + (tmp == 0xFFU) || ((tmp = tmp & 0x1FU) == /*ATI_TUNER_NONE*/0)) + continue; + + if (!xf86I2CDevInit(pI2CDev)) + { + xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, + "Failed to register I2C device for ATI-TV add-on.\n"); + break; + } + + if (pATI->Tuner != tmp) + { + if (pATI->Tuner != ATI_TUNER_NONE) + xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, + "Tuner type mismatch: BIOS 0x%x, ATI-TV 0x%x.\n", + pATI->Tuner, tmp); + + pATI->Tuner = tmp; + } + + xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, + "%s tuner detected on ATI-TV add-on adapter at I2C bus address" + " 0x%2x.\n", ATITuners[pATI->Tuner].name, pI2CDev->SlaveAddr); + + return TRUE; + } + + xfree(pI2CDev); + return FALSE; +} + +/* + * ATIMach64I2CPreInit -- + * + * This function potentially allocates an I2CBusRec and initialises it with + * ATI-specific and Mach64-specific information. + */ +void +ATIMach64I2CPreInit +( + ScrnInfoPtr pScreenInfo, + ATIPtr pATI +) +{ + I2CBusPtr pI2CBus; + ATII2CPtr pATII2C; + + if ((pATI->Chip < ATI_CHIP_264CT) || (pATI->Chip >= ATI_CHIP_Mach64)) + return; + + /* Create an I2CBusRec and generically prime it */ + if (!(pI2CBus = ATICreateI2CBusRec(pScreenInfo->scrnIndex, pATI, "Mach64"))) + return; + + pATII2C = pI2CBus->DriverPrivate.ptr; + + switch (pATI->Chip) + { + case ATI_CHIP_264GTPRO: + case ATI_CHIP_264LTPRO: + case ATI_CHIP_264XL: + case ATI_CHIP_MOBILITY: + /* + * These have I2C-specific registers. Assume older I2C access + * mechanisms are inoperative. + */ + pATII2C->I2CSetBits = ATIMach64I2C_CNTLSetBits; + pATII2C->I2CGetBits = ATIMach64I2C_CNTLGetBits; + pATII2C->SCLDir = pATII2C->SDADir = 0; + pATII2C->SCLGet = pATII2C->SCLSet = GetByte(I2C_CNTL_SCL, 1); + pATII2C->SDAGet = pATII2C->SDASet = GetByte(I2C_CNTL_SDA, 1); + + out8(I2C_CNTL_1 + 2, GetByte(I2C_SEL, 2)); + out8(I2C_CNTL_0 + 0, + GetByte(I2C_CNTL_STAT | I2C_CNTL_HPTR_RST, 0)); + break; + + case ATI_CHIP_264VTB: + case ATI_CHIP_264GTB: + case ATI_CHIP_264VT3: + case ATI_CHIP_264GTDVD: + case ATI_CHIP_264LT: + case ATI_CHIP_264VT4: + case ATI_CHIP_264GT2C: + /* If an ImpacTV chip is found, use it to provide I2C access */ + if (ATIMach64ImpacTVProbe(pScreenInfo->scrnIndex, pATI)) + { + pATII2C->I2CSetBits = ATIMach64ImpacTVSetBits; + pATII2C->I2CGetBits = ATIMach64ImpacTVGetBits; + pATII2C->SCLDir = IT_SCL_DIR; + pATII2C->SCLGet = IT_SCL_GET; + pATII2C->SCLSet = IT_SCL_SET; + pATII2C->SDADir = IT_SDA_DIR; + pATII2C->SDAGet = IT_SDA_GET; + pATII2C->SDASet = IT_SDA_SET; + + ATIMach64MPPSetAddress(pATI, IT_I2C_CNTL); + outr(MPP_CONFIG, MPP_WRITEINC); + out8(MPP_DATA, 0x00U); + out8(MPP_DATA, 0x55U); + out8(MPP_DATA, 0x00U); + out8(MPP_DATA, 0x00U); + ATIMach64MPPWaitForIdle(pATI); + break; + } + /* Otherwise, fall through to the older case */ + + case ATI_CHIP_264VT: + case ATI_CHIP_264GT: + /* First try GIO pins 11 (clock) and 4 (data) */ + pATII2C->I2CSetBits = ATIMach64GP_IOSetBits; + pATII2C->I2CGetBits = ATIMach64GP_IOGetBits; + pATII2C->SCLDir = GP_IO_DIR_B; + pATII2C->SCLGet = pATII2C->SCLSet = GP_IO_B; + pATII2C->SDADir = GP_IO_DIR_4; + pATII2C->SDAGet = pATII2C->SDASet = GP_IO_4; + + if (ATITVAddOnProbe(pScreenInfo, pATI, pI2CBus)) + break; + + /* Next, try pins 10 (clock) and 12 (data) */ + pATII2C->SCLDir = GP_IO_DIR_A; + pATII2C->SCLGet = pATII2C->SCLSet = GP_IO_A; + pATII2C->SDADir = GP_IO_DIR_C; + pATII2C->SDAGet = pATII2C->SDASet = GP_IO_C; + + if (ATITVAddOnProbe(pScreenInfo, pATI, pI2CBus)) + break; + /* Otherwise, fall back to ATI's first I2C implementation */ + + default: + /* + * First generation integrated controllers access GIO pin 1 (clock) + * though DAC_CNTL, and pin 2 (data) through GEN_TEST_CNTL. + */ + pATII2C->I2CSetBits = ATIMach64DAC_GENSetBits; + pATII2C->I2CGetBits = ATIMach64DAC_GENGetBits; + pATII2C->SCLDir = DAC_GIO_DIR_1; + pATII2C->SCLGet = pATII2C->SCLSet = DAC_GIO_STATE_1; + pATII2C->SDADir = GEN_GIO2_WRITE; + pATII2C->SDAGet = GEN_GIO2_DATA_IN; + pATII2C->SDASet = GEN_GIO2_DATA_OUT; + + (void)ATITVAddOnProbe(pScreenInfo, pATI, pI2CBus); + break; + } +} diff --git a/src/atimach64i2c.h b/src/atimach64i2c.h new file mode 100644 index 00000000..99309523 --- /dev/null +++ b/src/atimach64i2c.h @@ -0,0 +1,34 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64i2c.h,v 1.1 2003/07/24 22:08:28 tsi Exp $ */ +/* + * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#ifndef ___ATIMACH64I2C_H___ +#define ___ATIMACH64I2C_H___ 1 + +#include "atipriv.h" +#include "atiproto.h" + +#include "xf86str.h" + +extern void ATIMach64I2CPreInit FunctionPrototype((ScrnInfoPtr, ATIPtr)); + +#endif /* ___ATIMACH64I2C_H___ */ diff --git a/src/atimach64io.c b/src/atimach64io.c index 3197f3ca..b4fafd97 100644 --- a/src/atimach64io.c +++ b/src/atimach64io.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64io.c,v 1.5 2003/01/01 19:16:32 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64io.c,v 1.6 2003/04/23 21:51:29 tsi Exp $ */ /* * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -26,13 +26,13 @@ #include "atimach64io.h" /* - * ATIAccessMach64PLLReg -- + * ATIMach64AccessPLLReg -- * * This function sets up the addressing required to access, for read or write, * a 264xT's PLL registers. */ void -ATIAccessMach64PLLReg +ATIMach64AccessPLLReg ( ATIPtr pATI, const CARD8 Index, diff --git a/src/atimach64io.h b/src/atimach64io.h index b91a882b..e4db52a3 100644 --- a/src/atimach64io.h +++ b/src/atimach64io.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64io.h,v 1.14 2003/01/01 19:16:32 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64io.h,v 1.15 2003/04/23 21:51:29 tsi Exp $ */ /* * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -192,47 +192,82 @@ extern void ATIMach64PollEngineStatus FunctionPrototype((ATIPtr)); * This is no longer as critical, especially for _n == 1. However, * there is still a need to ensure _n <= pATI->nFIFOEntries. */ -#define ATIMach64WaitForFIFO(_pATI, _n) \ - while (pATI->nAvailableFIFOEntries < (_n)) \ - ATIMach64PollEngineStatus(pATI) +#define ATIMach64WaitForFIFO(_pATI, _n) \ + while ((_pATI)->nAvailableFIFOEntries < (_n)) \ + ATIMach64PollEngineStatus(_pATI) -#define ATIMach64WaitForIdle(_pATI) \ - while (pATI->EngineIsBusy) \ - ATIMach64PollEngineStatus(pATI) +#define ATIMach64WaitForIdle(_pATI) \ + while ((_pATI)->EngineIsBusy) \ + ATIMach64PollEngineStatus(_pATI) -extern void ATIAccessMach64PLLReg FunctionPrototype((ATIPtr, const CARD8, +/* + * An outf() variant to write two registers such that the second register is + * is always written whenever either is to be changed. + */ +#define outq(_Register1, _Register2, _Value1, _Value2) \ + do \ + { \ + CARD32 _IOValue1 = (_Value1), \ + _IOValue2 = (_Value2); \ + \ + if (!RegisterIsCached(_Register1) || \ + (_IOValue1 != CacheSlot(_Register1))) \ + { \ + ATIMach64WaitForFIFO(pATI, 2); \ + pATI->nAvailableFIFOEntries -= 2; \ + MMIO_OUT32(pATI->pBlock[GetBits(_Register1, BLOCK_SELECT)], \ + (_Register1) & MM_IO_SELECT, _IOValue1); \ + MMIO_OUT32(pATI->pBlock[GetBits(_Register2, BLOCK_SELECT)], \ + (_Register2) & MM_IO_SELECT, _IOValue2); \ + CacheSlot(_Register1) = _IOValue1; \ + CacheSlot(_Register2) = _IOValue2; \ + pATI->EngineIsBusy = TRUE; \ + } \ + else if (!RegisterIsCached(_Register2) || \ + (_IOValue2 != CacheSlot(_Register2))) \ + { \ + while (!pATI->nAvailableFIFOEntries--) \ + ATIMach64PollEngineStatus(pATI); \ + MMIO_OUT32(pATI->pBlock[GetBits(_Register2, BLOCK_SELECT)], \ + (_Register2) & MM_IO_SELECT, _IOValue2); \ + CacheSlot(_Register2) = _IOValue2; \ + pATI->EngineIsBusy = TRUE; \ + } \ + } while (0) + +extern void ATIMach64AccessPLLReg FunctionPrototype((ATIPtr, const CARD8, const Bool)); -#define ATIGetMach64PLLReg(_Index) \ +#define ATIMach64GetPLLReg(_Index) \ ( \ - ATIAccessMach64PLLReg(pATI, _Index, FALSE), \ + ATIMach64AccessPLLReg(pATI, _Index, FALSE), \ in8(CLOCK_CNTL + 2) \ ) -#define ATIPutMach64PLLReg(_Index, _Value) \ +#define ATIMach64PutPLLReg(_Index, _Value) \ do \ { \ - ATIAccessMach64PLLReg(pATI, _Index, TRUE); \ + ATIMach64AccessPLLReg(pATI, _Index, TRUE); \ out8(CLOCK_CNTL + 2, _Value); \ } while (0) -#define ATIGetMach64LCDReg(_Index) \ +#define ATIMach64GetLCDReg(_Index) \ ( \ out8(LCD_INDEX, SetBits(_Index, LCD_REG_INDEX)), \ inr(LCD_DATA) \ ) -#define ATIPutMach64LCDReg(_Index, _Value) \ +#define ATIMach64PutLCDReg(_Index, _Value) \ do \ { \ out8(LCD_INDEX, SetBits(_Index, LCD_REG_INDEX)); \ outr(LCD_DATA, _Value); \ } while (0) -#define ATIGetMach64TVReg(_Index) \ +#define ATIMach64GetTVReg(_Index) \ ( \ out8(TV_OUT_INDEX, SetBits(_Index, TV_REG_INDEX)), \ inr(TV_OUT_DATA) \ ) -#define ATIPutMach64TVReg(_Index, _Value) \ +#define ATIMach64PutTVReg(_Index, _Value) \ do \ { \ out8(TV_OUT_INDEX, SetBits(_Index, TV_REG_INDEX)); \ diff --git a/src/atimach64xv.c b/src/atimach64xv.c new file mode 100644 index 00000000..92fe7ecc --- /dev/null +++ b/src/atimach64xv.c @@ -0,0 +1,1493 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64xv.c,v 1.7 2003/11/10 18:22:18 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#include "ati.h" +#include "atiaccel.h" +#include "atichip.h" +#include "atimach64accel.h" +#include "atimach64io.h" +#include "atimach64xv.h" + +#include "Xv.h" +#include "fourcc.h" + +#define MAKE_ATOM(string) MakeAtom(string, strlen(string), TRUE) +#define MaxScale (CARD32)(CARD16)(-1) + +static unsigned long ATIMach64XVAtomGeneration = (unsigned long)(-1); + +static XF86VideoEncodingRec ATIMach64VideoEncoding_A[] = +{ + { 0, "XV_IMAGE", 384, 2048, {1, 1} } +}; +#define nATIMach64VideoEncoding_A NumberOf(ATIMach64VideoEncoding_A) + +static XF86VideoEncodingRec ATIMach64VideoEncoding_B[] = +{ + { 0, "XV_IMAGE", 720, 2048, {1, 1} } +}; +#define nATIMach64VideoEncoding_B NumberOf(ATIMach64VideoEncoding_B) + +/* nATIMach64VideoEncoding_[AB] should be equal */ +#define nATIMach64VideoEncoding nATIMach64VideoEncoding_A + +static XF86VideoFormatRec ATIMach64VideoFormat[] = +{ + { 8, TrueColor}, + { 8, DirectColor}, + { 8, PseudoColor}, + { 8, GrayScale}, + { 8, StaticGray}, + { 8, StaticColor}, + {15, TrueColor}, + {16, TrueColor}, + {24, TrueColor}, + {15, DirectColor}, + {16, DirectColor}, + {24, DirectColor} +}; +#define nATIMach64VideoFormat NumberOf(ATIMach64VideoFormat) + +static XF86AttributeRec ATIMach64Attribute[] = +{ + /* These are only supported on the Rage Pro and later ... */ + { + XvSettable | XvGettable, + -1000, 1000, + "XV_SATURATION" + }, + { + XvSettable | XvGettable, + -1000, 1000, + "XV_BRIGHTNESS" + }, + { + XvSettable | XvGettable, + -1000, 1000, + "XV_COLOUR" + }, + { + XvSettable | XvGettable, + -1000, 1000, + "XV_COLOR" + }, + + /* Local attributes, odds and ends for compatibility, etc... */ + { + XvSettable | XvGettable, + 0, 1, + "XV_AUTOPAINT_COLOURKEY" + }, + { + XvSettable | XvGettable, + 0, 1, + "XV_AUTOPAINT_COLORKEY" + }, + { + XvSettable | XvGettable, + 0, (1 << 24) - 1, + "XV_COLOURKEY" + }, + { + XvSettable | XvGettable, + 0, (1 << 24) - 1, + "XV_COLORKEY" + }, + { + XvSettable | XvGettable, + 0, (1 << 24) - 1, + "XV_COLOURKEY_MASK" + }, + { + XvSettable | XvGettable, + 0, (1 << 24) - 1, + "XV_COLORKEY_MASK" + }, + { + XvSettable, + 0, 0, + "XV_SET_DEFAULTS" + }, + { /* Keep last */ + XvSettable | XvGettable, + 0, 1, + "XV_DOUBLE_BUFFER" + } +}; +#define nATIMach64Attribute NumberOf(ATIMach64Attribute) + +static XF86ImageRec ATIMach64Image[] = +{ + XVIMAGE_YUY2, + XVIMAGE_UYVY, + XVIMAGE_YV12, + XVIMAGE_I420 +}; +#define nATIMach64Image NumberOf(ATIMach64Image) + +/* A local XVideo adaptor attribute record */ +typedef struct _ATIMach64Attribute +{ + Atom AttributeID; + INT32 MaxValue; /* ... for the hardware */ + void (*SetAttribute) NestedPrototype((ATIPtr, INT32)); + INT32 (*GetAttribute) NestedPrototype((ATIPtr)); +} ATIMach64AttributeRec, *ATIMach64AttributePtr; + +/* Functions to get/set XVideo adaptor attributes */ + +static void +ATIMach64SetSaturationAttribute +( + ATIPtr pATI, + INT32 Value +) +{ + /* Set the register */ + pATI->NewHW.scaler_colour_cntl &= + ~(SCALE_SATURATION_U | SCALE_SATURATION_V); + pATI->NewHW.scaler_colour_cntl |= SetBits(Value, SCALE_SATURATION_U) | + SetBits(Value, SCALE_SATURATION_V); + outf(SCALER_COLOUR_CNTL, pATI->NewHW.scaler_colour_cntl); +} + +static INT32 +ATIMach64GetSaturationAttribute +( + ATIPtr pATI +) +{ + return (INT32)GetBits(pATI->NewHW.scaler_colour_cntl, SCALE_SATURATION_U); +} + +static void +ATIMach64SetBrightnessAttribute +( + ATIPtr pATI, + INT32 Value +) +{ + /* Set the register */ + pATI->NewHW.scaler_colour_cntl &= ~SCALE_BRIGHTNESS; + pATI->NewHW.scaler_colour_cntl |= SetBits(Value, SCALE_BRIGHTNESS); + outf(SCALER_COLOUR_CNTL, pATI->NewHW.scaler_colour_cntl); +} + +static INT32 +ATIMach64GetBrightnessAttribute +( + ATIPtr pATI +) +{ + return (INT32)GetBits(pATI->NewHW.scaler_colour_cntl, SCALE_BRIGHTNESS); +} + +static void +ATIMach64SetDoubleBufferAttribute +( + ATIPtr pATI, + INT32 Value +) +{ + pATI->DoubleBuffer = Value; +} + +static INT32 +ATIMach64GetDoubleBufferAttribute +( + ATIPtr pATI +) +{ + return (int)pATI->DoubleBuffer; +} + +static void +ATIMach64SetAutoPaintAttribute +( + ATIPtr pATI, + INT32 Value +) +{ + pATI->AutoPaint = Value; +} + +static INT32 +ATIMach64GetAutoPaintAttribute +( + ATIPtr pATI +) +{ + return (int)pATI->AutoPaint; +} + +static void +ATIMach64SetColourKeyAttribute +( + ATIPtr pATI, + INT32 Value +) +{ + pATI->NewHW.overlay_graphics_key_clr = + (CARD32)(Value & ((1 << pATI->depth) - 1)); + outf(OVERLAY_GRAPHICS_KEY_CLR, pATI->NewHW.overlay_graphics_key_clr); +} + +static INT32 +ATIMach64GetColourKeyAttribute +( + ATIPtr pATI +) +{ + return (INT32)pATI->NewHW.overlay_graphics_key_clr; +} + +static void +ATIMach64SetColourKeyMaskAttribute +( + ATIPtr pATI, + INT32 Value +) +{ + pATI->NewHW.overlay_graphics_key_msk = + (CARD32)(Value & ((1 << pATI->depth) - 1)); + outf(OVERLAY_GRAPHICS_KEY_MSK, pATI->NewHW.overlay_graphics_key_msk); +} + +static INT32 +ATIMach64GetColourKeyMaskAttribute +( + ATIPtr pATI +) +{ + return (INT32)pATI->NewHW.overlay_graphics_key_msk; +} + +/* + * ATIMach64SetDefaultAttributes -- + * + * This function calls other functions to set default values for the various + * attributes of an XVideo port. + */ +static void +ATIMach64SetDefaultAttributes +( + ATIPtr pATI, + INT32 Value +) +{ + ATIMach64SetAutoPaintAttribute(pATI, TRUE); + ATIMach64SetDoubleBufferAttribute(pATI, FALSE); + ATIMach64SetColourKeyMaskAttribute(pATI, (1 << pATI->depth) - 1); + ATIMach64SetColourKeyAttribute(pATI, (3 << ((2 * pATI->depth) / 3)) | + (2 << ((1 * pATI->depth) / 3)) | + (1 << ((0 * pATI->depth) / 3))); + + if (pATI->Chip < ATI_CHIP_264GTPRO) + return; + + ATIMach64SetBrightnessAttribute(pATI, 32); + ATIMach64SetSaturationAttribute(pATI, 16); +} + +/* + * There is a one-to-one correspondance between elements of the following array + * and those of ATIMach64Attribute. + */ +static ATIMach64AttributeRec ATIMach64AttributeInfo[nATIMach64Attribute] = +{ + { /* SATURATION */ + 0, 23, + ATIMach64SetSaturationAttribute, + ATIMach64GetSaturationAttribute + }, + { /* BRIGHTNESS */ + 0, 63, + ATIMach64SetBrightnessAttribute, + ATIMach64GetBrightnessAttribute + }, + { /* COLOUR */ + 0, 23, + ATIMach64SetSaturationAttribute, + ATIMach64GetSaturationAttribute + }, + { /* COLOR */ + 0, 23, + ATIMach64SetSaturationAttribute, + ATIMach64GetSaturationAttribute + }, + { /* AUTOPAINT_COLOURKEY */ + 0, 1, + ATIMach64SetAutoPaintAttribute, + ATIMach64GetAutoPaintAttribute + }, + { /* AUTOPAINT_COLORKEY */ + 0, 1, + ATIMach64SetAutoPaintAttribute, + ATIMach64GetAutoPaintAttribute + }, + { /* COLOURKEY */ + 0, (1 << 24) - 1, + ATIMach64SetColourKeyAttribute, + ATIMach64GetColourKeyAttribute + }, + { /* COLORKEY */ + 0, (1 << 24) - 1, + ATIMach64SetColourKeyAttribute, + ATIMach64GetColourKeyAttribute + }, + { /* COLOURKEY_MASK */ + 0, (1 << 24) - 1, + ATIMach64SetColourKeyMaskAttribute, + ATIMach64GetColourKeyMaskAttribute + }, + { /* COLORKEY_MASK */ + 0, (1 << 24) - 1, + ATIMach64SetColourKeyMaskAttribute, + ATIMach64GetColourKeyMaskAttribute + }, + { /* SET_DEFAULTS */ + 0, 0, + ATIMach64SetDefaultAttributes, + NULL + }, + { /* DOUBLE_BUFFER */ + 0, 1, + ATIMach64SetDoubleBufferAttribute, + ATIMach64GetDoubleBufferAttribute + } +}; + +/* + * ATIMach64FindAttribute -- + * + * This function is called to locate an Xv attribute's table entry. + */ +static int +ATIMach64FindPortAttribute +( + ATIPtr pATI, + Atom AttributeID +) +{ + int iAttribute; + + if (pATI->Chip < ATI_CHIP_264GTPRO) + iAttribute = 4; + else + iAttribute = 0; + + for (; iAttribute < nATIMach64Attribute; iAttribute++) + if (AttributeID == ATIMach64AttributeInfo[iAttribute].AttributeID) + return iAttribute; + + return -1; +} + +/* + * ATIMach64SetPortAttribute -- + * + * This function sets the value of a particular port's attribute. + */ +static int +ATIMach64SetPortAttribute +( + ScrnInfoPtr pScreenInfo, + Atom AttributeID, + INT32 Value, + pointer pATI +) +{ + INT32 Range; + int iAttribute; + + if (((iAttribute = ATIMach64FindPortAttribute(pATI, AttributeID)) < 0) || + !ATIMach64AttributeInfo[iAttribute].SetAttribute) + return BadMatch; + + Range = ATIMach64Attribute[iAttribute].max_value - + ATIMach64Attribute[iAttribute].min_value; + + if (Range >= 0) + { + /* Limit and scale the value */ + Value -= ATIMach64Attribute[iAttribute].min_value; + + if (Value < 0) + Value = 0; + else if (Value > Range) + Value = Range; + + if (Range != ATIMach64AttributeInfo[iAttribute].MaxValue) + { + if (ATIMach64AttributeInfo[iAttribute].MaxValue > 0) + Value *= ATIMach64AttributeInfo[iAttribute].MaxValue; + if (Range > 0) + Value /= Range; + } + } + + (*ATIMach64AttributeInfo[iAttribute].SetAttribute)(pATI, Value); + + return Success; +} + +/* + * ATIMach64SetPortAttribute -- + * + * This function retrieves the value of a particular port's attribute. + */ +static int +ATIMach64GetPortAttribute +( + ScrnInfoPtr pScreenInfo, + Atom AttributeID, + INT32 *Value, + pointer pATI +) +{ + INT32 Range; + int iAttribute; + + if (!Value || + ((iAttribute = ATIMach64FindPortAttribute(pATI, AttributeID)) < 0) || + !ATIMach64AttributeInfo[iAttribute].GetAttribute) + return BadMatch; + + *Value = (*ATIMach64AttributeInfo[iAttribute].GetAttribute)(pATI); + + Range = ATIMach64Attribute[iAttribute].max_value - + ATIMach64Attribute[iAttribute].min_value; + + if (Range >= 0) + { + if (Range != ATIMach64AttributeInfo[iAttribute].MaxValue) + { + /* (Un-)scale the value */ + if (Range > 0) + *Value *= Range; + if (ATIMach64AttributeInfo[iAttribute].MaxValue > 0) + *Value /= ATIMach64AttributeInfo[iAttribute].MaxValue; + } + + *Value += ATIMach64Attribute[iAttribute].min_value; + } + + return Success; +} + +/* + * ATIMach64RemoveLinearCallback -- + * + * This is called by the framebuffer manager to release the offscreen XVideo + * buffer after the video has been temporarily disabled due to its window being + * iconified or completely occluded. + */ +static void +ATIMach64RemoveLinearCallback +( + FBLinearPtr pLinear +) +{ + ATIPtr pATI = ATIPTR(xf86Screens[pLinear->pScreen->myNum]); + + pATI->pXVBuffer = NULL; + outf(OVERLAY_SCALE_CNTL, SCALE_EN); +} + +/* + * ATIMach64StopVideo -- + * + * This is called to stop displaying a video. Note that, to prevent jittering + * this doesn't actually turn off the overlay unless 'Cleanup' is TRUE, i.e. + * when the video is to be actually stopped rather than temporarily disabled. + */ +static void +ATIMach64StopVideo +( + ScrnInfoPtr pScreenInfo, + pointer Data, + Bool Cleanup +) +{ + ScreenPtr pScreen = pScreenInfo->pScreen; + ATIPtr pATI = Data; + + if (pATI->ActiveSurface) + return; + + REGION_EMPTY(pScreen, &pATI->VideoClip); + + if (!Cleanup) + { + /* + * Free offscreen buffer if/when its allocation is needed by XAA's + * pixmap cache. + */ + if (pATI->pXVBuffer) + pATI->pXVBuffer->RemoveLinearCallback = + ATIMach64RemoveLinearCallback; + return; + } + + pATI->pXVBuffer = ATIResizeOffscreenLinear(pScreen, pATI->pXVBuffer, 0); + outf(OVERLAY_SCALE_CNTL, SCALE_EN); +} + +/* + * ATIMach64QueryBestSize -- + * + * Quoting XVideo docs: + * + * This function provides the client with a way to query what the destination + * dimensions would end up being if they were to request that an area + * VideoWidth by VideoHeight from the video stream be scaled to rectangle of + * DrawableWidth by DrawableHeight on the screen. Since it is not expected + * that all hardware will be able to get the target dimensions exactly, it is + * important that the driver provide this function. + */ +static void +ATIMach64QueryBestSize +( + ScrnInfoPtr pScreenInfo, + Bool Motion, + short VideoWidth, + short VideoHeight, + short DrawableWidth, + short DrawableHeight, + unsigned int *Width, + unsigned int *Height, + pointer pATI +) +{ + *Width = DrawableWidth; + *Height = DrawableHeight; +} + +/* + * ATIMach64QueryImageAttributes -- + * + * Quoting XVideo docs: + * + * This function is called to let the driver specify how data for a particular + * image of size Width by Height should be stored. Sometimes only the size and + * corrected width and height are needed. In that case pitches and offsets are + * NULL. The size of the memory required for the image is returned by this + * function. The width and height of the requested image can be altered by the + * driver to reflect format limitations (such as component sampling periods + * that are larger than one). If pPitch and pOffset are not NULL, these will + * be arrays with as many elements in them as there are planes in the image + * format. The driver should specify the pitch (in bytes) of each scanline in + * the particular plane as well as the offset to that plane (in bytes) from the + * beginning of the image. + */ +static int +ATIMach64QueryImageAttributes +( + ScrnInfoPtr pScreenInfo, + int ImageID, + unsigned short *Width, + unsigned short *Height, + int *pPitch, + int *pOffset +) +{ + int Size, tmp; + + if (!Width || !Height) + return 0; + + if (*Width > 2048) + *Width = 2048; + else + *Width = (*Width + 1) & ~1; + + if (*Height > 2048) + *Height = 2048; + + if (pOffset) + pOffset[0] = 0; + + switch (ImageID) + { + case FOURCC_YV12: + case FOURCC_I420: + *Height = (*Height + 1) & ~1; + Size = (*Width + 3) & ~3; + if (pPitch) + pPitch[0] = Size; + Size *= *Height; + if (pOffset) + pOffset[1] = Size; + tmp = ((*Width >> 1) + 3) & ~3; + if (pPitch) + pPitch[1] = pPitch[2] = tmp; + tmp *= (*Height >> 1); + Size += tmp; + if (pOffset) + pOffset[2] = Size; + Size += tmp; + break; + + case FOURCC_UYVY: + case FOURCC_YUY2: + Size = *Width << 1; + if (pPitch) + pPitch[0] = Size; + Size *= *Height; + break; + + default: + Size = 0; + break; + } + + return Size; +} + +/* + * ATIMach64ScaleVideo -- + * + * This function is called to calculate overlay scaling factors. + */ +static void +ATIMach64ScaleVideo +( + ATIPtr pATI, + DisplayModePtr pMode, + int SrcW, + int SrcH, + int DstW, + int DstH, + CARD32 *pHScale, + CARD32 *pVScale +) +{ + int Shift; + + *pHScale = ATIDivide(SrcW, DstW, + GetBits(pATI->NewHW.pll_vclk_cntl, PLL_ECP_DIV) + 12, 0); + + Shift = 12; + if (pMode->Flags & V_INTERLACE) + Shift++; + + if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0)) + { + if (pMode->VDisplay < pATI->LCDVertical) + { + SrcH *= pMode->VDisplay; + DstH *= pATI->LCDVertical; + } + } + else + { + if (pMode->Flags & V_DBLSCAN) + Shift--; + if (pMode->VScan > 1) + DstH *= pMode->VScan; + } + + *pVScale = ATIDivide(SrcH, DstH, Shift, 0); +} + +/* + * ATIMach64ClipVideo -- + * + * Clip the video (both source and destination) and make various other + * adjustments. + */ +static Bool +ATIMach64ClipVideo +( + ScrnInfoPtr pScreenInfo, + ATIPtr pATI, + int ImageID, + short SrcX, + short SrcY, + short SrcW, + short SrcH, + short DstX, + short DstY, + short *DstW, + short *DstH, + short Width, + short Height, + RegionPtr pClip, + BoxPtr pDstBox, + INT32 *SrcX1, + INT32 *SrcX2, + INT32 *SrcY1, + INT32 *SrcY2, + int *SrcLeft, + int *SrcTop +) +{ + CARD32 HScale, VScale; + + /* Check hardware limits */ + if ((Height <= 0) || (Height > 2048) || (Width <= 0) || (Width > 720) || + ((Width > 384) && (pATI->Chip < ATI_CHIP_264VTB))) + return FALSE; + + ATIMach64ScaleVideo(pATI, pScreenInfo->currentMode, + SrcW, SrcH, *DstW, *DstH, &HScale, &VScale); + if (!HScale || !VScale) + return FALSE; + if (HScale > MaxScale) + *DstW = (*DstW * HScale) / MaxScale; + if (VScale > MaxScale) + *DstH = (*DstH * HScale) / MaxScale; + + /* Clip both the source and the destination */ + *SrcX1 = SrcX; + *SrcX2 = SrcX + SrcW; + *SrcY1 = SrcY; + *SrcY2 = SrcY + SrcH; + + pDstBox->x1 = DstX; + pDstBox->x2 = DstX + *DstW; + pDstBox->y1 = DstY; + pDstBox->y2 = DstY + *DstH; + + if (!xf86XVClipVideoHelper(pDstBox, SrcX1, SrcX2, SrcY1, SrcY2, + pClip, Width, Height)) + return FALSE; + + /* + * Reset overlay scaler origin. This prevents jittering during + * viewport panning or while the video is being moved or gradually + * obscured/unobscured. + */ + pDstBox->x1 = DstX; + pDstBox->y1 = DstY; + + /* Translate to the current viewport */ + pDstBox->x1 -= pScreenInfo->frameX0; + pDstBox->x2 -= pScreenInfo->frameX0; + pDstBox->y1 -= pScreenInfo->frameY0; + pDstBox->y2 -= pScreenInfo->frameY0; + + *SrcLeft = *SrcTop = 0; + + /* + * If the overlay scaler origin ends up outside the current viewport, move + * it to the viewport's top left corner. This unavoidably causes a slight + * jittering in the image (even with double-buffering). + */ + if (pDstBox->x1 < 0) + { + *SrcLeft = ((-pDstBox->x1 * SrcW) / *DstW) & ~1; + pDstBox->x1 = 0; + } + + if (pDstBox->y1 < 0) + { + *SrcTop = (-pDstBox->y1 * SrcH) / *DstH; + pDstBox->y1 = 0; + + switch (ImageID) + { + case FOURCC_YV12: + case FOURCC_I420: + *SrcTop = (*SrcTop + 1) & ~1; + break; + + default: + break; + } + } + + return TRUE; +} + +#ifdef ATIMove32 + +/* A faster intercept */ +#undef xf86XVCopyPacked +#define xf86XVCopyPacked ATIMach64XVCopyPacked + +static void +ATIMach64XVCopyPacked +( + const CARD8 *pSrc, + CARD8 *pDst, + int SrcPitch, + int DstPitch, + int Height, + int Width +) +{ + Width >>= 1; + while (--Height >= 0) + { + ATIMove32(pDst, pSrc, Width); + pSrc += SrcPitch; + pDst += DstPitch; + } +} + +#endif + +/* + * ATIMach64DisplayVideo -- + * + * This function programmes Mach64 registers needed to display a video. + */ +static void +ATIMach64DisplayVideo +( + ScrnInfoPtr pScreenInfo, + ATIPtr pATI, + BoxPtr pDstBox, + int ImageID, + int Offset, + int Pitch, + short SrcW, + short SrcH, + short DstW, + short DstH, + short Width, + short Height +) +{ + DisplayModePtr pMode = pScreenInfo->currentMode; + CARD32 HScale, VScale; + + if (pMode->VScan > 1) + { + pDstBox->y1 *= pMode->VScan; + pDstBox->y2 *= pMode->VScan; + } + if (pMode->Flags & V_DBLSCAN) + { + pDstBox->y1 <<= 1; + pDstBox->y2 <<= 1; + } + + /* Recalculate overlay scale factors */ + ATIMach64ScaleVideo(pATI, pMode, SrcW, SrcH, DstW, DstH, &HScale, &VScale); + + pATI->NewHW.video_format &= ~SCALER_IN; + if (ImageID == FOURCC_UYVY) + pATI->NewHW.video_format |= SCALER_IN_YVYU422; + else + pATI->NewHW.video_format |= SCALER_IN_VYUY422; + + ATIMach64WaitForFIFO(pATI, 8); + outq(OVERLAY_Y_X_START, OVERLAY_Y_X_END, OVERLAY_LOCK_START | + SetWord(pDstBox->x1, 1) | SetWord(pDstBox->y1, 0), + SetWord(pDstBox->x2 - 1, 1) | SetWord(pDstBox->y2 - 1, 0)); + outf(OVERLAY_SCALE_INC, SetWord(HScale, 1) | SetWord(VScale, 0)); + outf(SCALER_HEIGHT_WIDTH, SetWord(Width, 1) | SetWord(Height, 0)); + outf(VIDEO_FORMAT, pATI->NewHW.video_format); + + if (pATI->Chip < ATI_CHIP_264VTB) + { + outf(BUF0_OFFSET, Offset); + outf(BUF0_PITCH, Pitch); + } + else + { + outf(SCALER_BUF0_OFFSET, Offset); + outf(SCALER_BUF_PITCH, Pitch); + } + + outf(OVERLAY_SCALE_CNTL, SCALE_PIX_EXPAND | OVERLAY_EN | SCALE_EN); +} + +/* + * ATIMach64PutImage -- + * + * This function is called to put a video image on the screen. + */ +static int +ATIMach64PutImage +( + ScrnInfoPtr pScreenInfo, + short SrcX, + short SrcY, + short DstX, + short DstY, + short SrcW, + short SrcH, + short DstW, + short DstH, + int ImageID, + unsigned char *Buffer, + short Width, + short Height, + Bool Synchronise, + RegionPtr pClip, + pointer Data +) +{ + ATIPtr pATI = Data; + ScreenPtr pScreen; + INT32 SrcX1, SrcX2, SrcY1, SrcY2; + BoxRec DstBox; + int SrcPitch, SrcPitchUV, DstPitch, DstSize; + int SrcTop, SrcLeft, DstWidth, DstHeight; + int Top, Bottom, Left, Right, nLine, nPixel, Offset; + int OffsetV, OffsetU; + int tmp; + CARD8 *pDst; + + if (pATI->ActiveSurface) + return Success; + + if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID, + SrcX, SrcY, SrcW, SrcH, + DstX, DstY, &DstW, &DstH, + Width, Height, pClip, &DstBox, + &SrcX1, &SrcX2, &SrcY1, &SrcY2, + &SrcLeft, &SrcTop)) + return Success; + + pScreen = pScreenInfo->pScreen; + + DstWidth = Width - SrcLeft; + DstHeight = Height - SrcTop; + + /* + * Allocate an offscreen buffer for the entire source, even though only a + * subset of the source will be copied into it. + */ + DstPitch = /* bytes */ + (DstWidth + DstWidth + 15) & ~15; + DstSize = /* pixels */ + ((DstPitch * DstHeight) + pATI->AdjustDepth - 1) / pATI->AdjustDepth; + + pATI->pXVBuffer = ATIResizeOffscreenLinear(pScreen, pATI->pXVBuffer, + (pATI->DoubleBuffer + 1) * DstSize); + + if (!pATI->pXVBuffer) + { + if (!pATI->DoubleBuffer) + return BadAlloc; + + pATI->pXVBuffer = + ATIResizeOffscreenLinear(pScreen, pATI->pXVBuffer, DstSize); + + if (!pATI->pXVBuffer) + return BadAlloc; + + xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, + "Video image double-buffering downgraded to single-buffering\n due" + " to insufficient video memory.\n"); + pATI->DoubleBuffer = pATI->CurrentBuffer = 0; + } + else + { + /* Possibly switch buffers */ + pATI->CurrentBuffer = pATI->DoubleBuffer - pATI->CurrentBuffer; + } + + /* Synchronise video memory accesses */ + ATIMach64Sync(pScreenInfo); + + Offset = (pATI->pXVBuffer->offset * pATI->AdjustDepth) + + (pATI->CurrentBuffer * DstSize * pATI->AdjustDepth); + pDst = pATI->pMemoryLE; + pDst += Offset; + + switch (ImageID) + { + case FOURCC_YV12: + case FOURCC_I420: + Left = (SrcX1 >> 16) & ~1; + Right = ((SrcX2 + 0x1FFFF) >> 16) & ~1; + Top = (SrcY1 >> 16) & ~1; + Bottom = ((SrcY2 + 0x1FFFF) >> 16) & ~1; + + if ((Right < Width) && ((SrcX1 & 0x1FFFF) <= (SrcX2 & 0x1FFFF))) + Right += 2; + if ((Bottom < Height) && ((SrcY1 & 0x1FFFF) <= (SrcY2 & 0x1FFFF))) + Bottom += 2; + + nPixel = Right - Left; + nLine = Bottom - Top; + + SrcPitch = (Width + 3) & ~3; + OffsetV = SrcPitch * Height; + SrcPitchUV = ((Width >> 1) + 3) & ~3; + OffsetU = ((Height >> 1) * SrcPitchUV) + OffsetV; + + tmp = ((Top >> 1) * SrcPitchUV) + (Left >> 1); + OffsetV += tmp; + OffsetU += tmp; + + if (ImageID == FOURCC_I420) + { + tmp = OffsetV; + OffsetV = OffsetU; + OffsetU = tmp; + } + + pDst += ((Top - SrcTop) * DstPitch) + ((Left - SrcLeft) << 1); + + xf86XVCopyYUV12ToPacked(Buffer + (Top * SrcPitch) + Left, + Buffer + OffsetV, Buffer + OffsetU, pDst, SrcPitch, SrcPitchUV, + DstPitch, nLine, nPixel); + break; + + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + Left = (SrcX1 >> 16) & ~1; + Right = ((SrcX2 + 0x1FFFF) >> 16) & ~1; + Top = SrcY1 >> 16; + Bottom = (SrcY2 + 0x0FFFF) >> 16; + + if ((Right < Width) && ((SrcX1 & 0x1FFFF) <= (SrcX2 & 0x1FFFF))) + Right += 2; + if ((Bottom < Height) && ((SrcY1 & 0x0FFFF) <= (SrcY2 & 0x0FFFF))) + Bottom++; + + nPixel = Right - Left; + nLine = Bottom - Top; + + SrcPitch = Width << 1; + Buffer += (Top * SrcPitch) + (Left << 1); + pDst += ((Top - SrcTop) * DstPitch) + ((Left - SrcLeft) << 1); + + xf86XVCopyPacked(Buffer, pDst, SrcPitch, DstPitch, nLine, nPixel); + break; + } + + if (!REGION_EQUAL(pScreen, &pATI->VideoClip, pClip)) + { + REGION_COPY(pScreen, &pATI->VideoClip, pClip); + if (pATI->AutoPaint) + xf86XVFillKeyHelper(pScreen, pATI->NewHW.overlay_graphics_key_clr, + pClip); + } + + ATIMach64DisplayVideo(pScreenInfo, pATI, &DstBox, ImageID, + Offset, DstPitch / 2, SrcW, SrcH, DstW, DstH, DstWidth, DstHeight); + + return Success; +} + +/* + * ATIMach64AllocateSurface -- + * + * This function allocates an offscreen buffer (called a "surface") for use by + * an external driver such as 'v4l'. + */ +static int +ATIMach64AllocateSurface +( + ScrnInfoPtr pScreenInfo, + int ImageID, + unsigned short Width, + unsigned short Height, + XF86SurfacePtr pSurface +) +{ + ScreenPtr pScreen; + ATIPtr pATI = ATIPTR(pScreenInfo); + + if (pATI->ActiveSurface) + return BadAlloc; + + if ((Height <= 0) || (Height > 2048) || (Width <= 0) || (Width > 720) || + ((Width > 384) && (pATI->Chip < ATI_CHIP_264VTB))) + return BadValue; + + Width = (Width + 1) & ~1; + pATI->SurfacePitch = ((Width << 1) + 15) & ~15; + + pScreen = pScreenInfo->pScreen; + + pATI->pXVBuffer = ATIResizeOffscreenLinear(pScreen, pATI->pXVBuffer, + ((Height * pATI->SurfacePitch) + pATI->AdjustDepth - 1) / + pATI->AdjustDepth); + if (!pATI->pXVBuffer) + return BadAlloc; + + pATI->SurfaceOffset = pATI->pXVBuffer->offset * pATI->AdjustDepth; + + pSurface->pScrn = pScreenInfo; + pSurface->id = ImageID; + pSurface->width = Width; + pSurface->height = Height; + pSurface->pitches = &pATI->SurfacePitch; + pSurface->offsets = &pATI->SurfaceOffset; + pSurface->devPrivate.ptr = pATI; + + /* Stop the video */ + outf(OVERLAY_SCALE_CNTL, SCALE_EN); + REGION_EMPTY(pScreen, &pATI->VideoClip); + pATI->ActiveSurface = TRUE; + + return Success; +} + +/* + * ATIMach64FreeSurface -- + * + * This function called to free a surface's offscreen buffer. + */ +static int +ATIMach64FreeSurface +( + XF86SurfacePtr pSurface +) +{ + ATIPtr pATI = pSurface->devPrivate.ptr; + + if (!pATI->ActiveSurface) + return Success; + + outf(OVERLAY_SCALE_CNTL, SCALE_EN); + pATI->pXVBuffer = ATIResizeOffscreenLinear(pSurface->pScrn->pScreen, + pATI->pXVBuffer, 0); + pATI->ActiveSurface = FALSE; + + return Success; +} + +/* + * ATIMach64DisplaySurface -- + * + * This function is called to display a video surface. + */ +static int +ATIMach64DisplaySurface +( + XF86SurfacePtr pSurface, + short SrcX, + short SrcY, + short DstX, + short DstY, + short SrcW, + short SrcH, + short DstW, + short DstH, + RegionPtr pClip +) +{ + ATIPtr pATI = pSurface->devPrivate.ptr; + ScrnInfoPtr pScreenInfo; + int ImageID; + short Width, Height; + BoxRec DstBox; + INT32 SrcX1, SrcX2, SrcY1, SrcY2; + int SrcLeft, SrcTop, SrcPitch, Offset; + + if (!pATI->ActiveSurface) + return Success; + + pScreenInfo = pSurface->pScrn; + ImageID = pSurface->id; + Width = pSurface->width; + Height = pSurface->height; + + if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID, + SrcX, SrcY, SrcW, SrcH, + DstX, DstY, &DstW, &DstH, + Width, Height, pClip, &DstBox, + &SrcX1, &SrcX2, &SrcY1, &SrcY2, + &SrcLeft, &SrcTop)) + return Success; + + xf86XVFillKeyHelper(pScreenInfo->pScreen, + pATI->NewHW.overlay_graphics_key_clr, pClip); + + SrcPitch = pSurface->pitches[0]; + Offset = pSurface->offsets[0] + (SrcTop * SrcPitch) + (SrcLeft << 1); + ATIMach64DisplayVideo(pScreenInfo, pATI, &DstBox, ImageID, + Offset, SrcPitch, SrcW, SrcH, DstW, DstH, Width, Height); + + return Success; +} + +/* + * ATIMach64StopSurface -- + * + * This function is called to stop the overlaid display of a video surface. + */ +static int +ATIMach64StopSurface +( + XF86SurfacePtr pSurface +) +{ + ATIPtr pATI = pSurface->devPrivate.ptr; + + if (pATI->ActiveSurface) + outf(OVERLAY_SCALE_CNTL, SCALE_EN); + + return Success; +} + +/* + * ATIMach64GetSurfaceAttribute -- + * + * Retrieve the value of an XVideo attribute. + */ +static int +ATIMach64GetSurfaceAttribute +( + ScrnInfoPtr pScreenInfo, + Atom AttributeID, + INT32 *Value +) +{ + return ATIMach64GetPortAttribute(pScreenInfo, AttributeID, Value, + ATIPTR(pScreenInfo)); +} + +/* + * ATIMach64SetSurfaceAttribute + * + * Set the value of an XVideo attribute. + */ +static int +ATIMach64SetSurfaceAttribute +( + ScrnInfoPtr pScreenInfo, + Atom AttributeID, + INT32 Value +) +{ + return ATIMach64SetPortAttribute(pScreenInfo, AttributeID, Value, + ATIPTR(pScreenInfo)); +} + +/* XVideo surface registration data */ +static XF86OffscreenImageRec ATIMach64Surface_A[] = +{ + { + &ATIMach64Image[0], /* YUY2 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + ATIMach64AllocateSurface, + ATIMach64FreeSurface, + ATIMach64DisplaySurface, + ATIMach64StopSurface, + ATIMach64GetSurfaceAttribute, + ATIMach64SetSurfaceAttribute, + 384, 2048, + nATIMach64Attribute - 5, /* No double-buffering */ + ATIMach64Attribute + 4 /* No saturation nor brightness */ + }, + { + &ATIMach64Image[1], /* UYVY */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + ATIMach64AllocateSurface, + ATIMach64FreeSurface, + ATIMach64DisplaySurface, + ATIMach64StopSurface, + ATIMach64GetSurfaceAttribute, + ATIMach64SetSurfaceAttribute, + 384, 2048, + nATIMach64Attribute - 5, /* No double-buffering */ + ATIMach64Attribute + 4 /* No saturation nor brightness */ + } +}; +#define nATIMach64Surface_A NumberOf(ATIMach64Surface_A) + +static XF86OffscreenImageRec ATIMach64Surface_B[] = +{ + { + &ATIMach64Image[0], /* YUY2 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + ATIMach64AllocateSurface, + ATIMach64FreeSurface, + ATIMach64DisplaySurface, + ATIMach64StopSurface, + ATIMach64GetSurfaceAttribute, + ATIMach64SetSurfaceAttribute, + 720, 2048, + nATIMach64Attribute - 5, /* No double-buffering */ + ATIMach64Attribute + 4 /* No saturation nor brightness */ + }, + { + &ATIMach64Image[1], /* UYVY */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + ATIMach64AllocateSurface, + ATIMach64FreeSurface, + ATIMach64DisplaySurface, + ATIMach64StopSurface, + ATIMach64GetSurfaceAttribute, + ATIMach64SetSurfaceAttribute, + 720, 2048, + nATIMach64Attribute - 5, /* No double-buffering */ + ATIMach64Attribute + 4 /* No saturation nor brightness */ + } +}; +#define nATIMach64Surface_B NumberOf(ATIMach64Surface_B) + +static XF86OffscreenImageRec ATIMach64Surface_C[] = +{ + { + &ATIMach64Image[0], /* YUY2 */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + ATIMach64AllocateSurface, + ATIMach64FreeSurface, + ATIMach64DisplaySurface, + ATIMach64StopSurface, + ATIMach64GetSurfaceAttribute, + ATIMach64SetSurfaceAttribute, + 720, 2048, + nATIMach64Attribute - 1, /* No double-buffering */ + ATIMach64Attribute + }, + { + &ATIMach64Image[1], /* UYVY */ + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT, + ATIMach64AllocateSurface, + ATIMach64FreeSurface, + ATIMach64DisplaySurface, + ATIMach64StopSurface, + ATIMach64GetSurfaceAttribute, + ATIMach64SetSurfaceAttribute, + 720, 2048, + nATIMach64Attribute - 1, /* No double-buffering */ + ATIMach64Attribute + } +}; +#define nATIMach64Surface_C NumberOf(ATIMach64Surface_C) + +/* + * ATIMach64XVInitialiseAdaptor -- + * + * This function is called to make a Mach64's hardware overlay support + * available as an XVideo adaptor. + */ +int +ATIMach64XVInitialiseAdaptor +( + ScreenPtr pScreen, + ScrnInfoPtr pScreenInfo, + ATIPtr pATI, + XF86VideoAdaptorPtr **pppAdaptor +) +{ + XF86VideoAdaptorPtr pAdaptor; + int Index; + + if (!pATI->Block1Base) + return 0; + + if (!(pAdaptor = xf86XVAllocateVideoAdaptorRec(pScreenInfo))) + return 0; + + *pppAdaptor = xnfalloc(sizeof(pAdaptor)); + **pppAdaptor = pAdaptor; + + pAdaptor->nPorts = 1; + pAdaptor->pPortPrivates = pATI->XVPortPrivate; + pATI->XVPortPrivate[0].ptr = pATI; + + pAdaptor->type = XvInputMask | XvImageMask | XvWindowMask; + pAdaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + pAdaptor->name = "ATI Mach64 Back-end Overlay Scaler"; + + if (pATI->Chip < ATI_CHIP_264VTB) + { + pAdaptor->nEncodings = nATIMach64VideoEncoding_A; + pAdaptor->pEncodings = ATIMach64VideoEncoding_A; + } + else + { + pAdaptor->nEncodings = nATIMach64VideoEncoding_B; + pAdaptor->pEncodings = ATIMach64VideoEncoding_B; + } + + pAdaptor->nFormats = nATIMach64VideoFormat; + pAdaptor->pFormats = ATIMach64VideoFormat; + + pAdaptor->nAttributes = nATIMach64Attribute; + pAdaptor->pAttributes = ATIMach64Attribute; + + if (pATI->Chip < ATI_CHIP_264GTPRO) + { + /* Older controllers don't have brightness or saturation controls */ + pAdaptor->nAttributes -= 4; + pAdaptor->pAttributes += 4; + } + + pAdaptor->nImages = nATIMach64Image; + pAdaptor->pImages = ATIMach64Image; + + pAdaptor->StopVideo = ATIMach64StopVideo; + pAdaptor->SetPortAttribute = ATIMach64SetPortAttribute; + pAdaptor->GetPortAttribute = ATIMach64GetPortAttribute; + pAdaptor->QueryBestSize = ATIMach64QueryBestSize; + pAdaptor->PutImage = ATIMach64PutImage; + pAdaptor->QueryImageAttributes = ATIMach64QueryImageAttributes; + + REGION_NULL(pScreen, &pATI->VideoClip); + pATI->ActiveSurface = FALSE; + + if (ATIMach64XVAtomGeneration != serverGeneration) + { + /* Refresh static data */ + ATIMach64XVAtomGeneration = serverGeneration; + + Index = nATIMach64Attribute - pAdaptor->nAttributes; + for (; Index < nATIMach64Attribute; Index++) + ATIMach64AttributeInfo[Index].AttributeID = + MAKE_ATOM(ATIMach64Attribute[Index].name); + } + + ATIMach64SetDefaultAttributes(pATI, 0); + + if (pATI->Chip < ATI_CHIP_264VTB) + { + xf86XVRegisterOffscreenImages(pScreen, + ATIMach64Surface_A, nATIMach64Surface_A); + } + else if (pATI->Chip < ATI_CHIP_264GTPRO) + { + xf86XVRegisterOffscreenImages(pScreen, + ATIMach64Surface_B, nATIMach64Surface_B); + } + else + { + xf86XVRegisterOffscreenImages(pScreen, + ATIMach64Surface_C, nATIMach64Surface_C); + } + + return 1; +} + +/* + * ATIMach64CloseXVideo -- + * + * This function is called during screen termination to clean up after + * initialisation of Mach64 XVideo support. + */ +void +ATIMach64CloseXVideo +( + ScreenPtr pScreen, + ScrnInfoPtr pScreenInfo, + ATIPtr pATI +) +{ + ATIMach64StopVideo(pScreenInfo, pATI, TRUE); + + REGION_UNINIT(pScreen, &pATI->VideoClip); +} diff --git a/src/atimach64xv.h b/src/atimach64xv.h new file mode 100644 index 00000000..8d5c07c9 --- /dev/null +++ b/src/atimach64xv.h @@ -0,0 +1,40 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64xv.h,v 1.1 2003/04/23 21:51:29 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#ifndef ___ATIMACH64XV_H___ +#define ___ATIMACH64XV_H___ 1 + +#include "atipriv.h" +#include "atiproto.h" + +#include "xf86str.h" +#include "xf86xv.h" + +extern int ATIMach64XVInitialiseAdaptor + FunctionPrototype((ScreenPtr, ScrnInfoPtr, ATIPtr, + XF86VideoAdaptorPtr **)); + +extern void ATIMach64CloseXVideo + FunctionPrototype((ScreenPtr, ScrnInfoPtr, ATIPtr)); + +#endif /* ___ATIMACH64XV_H___ */ diff --git a/src/atimisc.c b/src/atimisc.c index f84240e4..a84eac49 100644 --- a/src/atimisc.c +++ b/src/atimisc.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimisc.c,v 1.6 2003/01/01 19:16:32 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimisc.c,v 1.7 2003/07/24 22:08:28 tsi Exp $ */ /* * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -85,6 +85,7 @@ ATISetup ATIshadowfbSymbols, ATIxaaSymbols, ATIramdacSymbols, + ATIi2cSymbols, NULL); Inited = TRUE; diff --git a/src/atimode.c b/src/atimode.c index d470ae49..02cf3193 100644 --- a/src/atimode.c +++ b/src/atimode.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimode.c,v 1.16 2003/01/01 19:16:32 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimode.c,v 1.17 2003/04/23 21:51:29 tsi Exp $ */ /* * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -257,32 +257,32 @@ ATIModePreInit ATIVGAWonderPreInit(pATI, pATIHW); } - /* Fill in Mach64 data */ if (pATI->Chip >= ATI_CHIP_88800GXC) #endif /* AVOID_CPIO */ { + /* Fill in Mach64 data */ ATIMach64PreInit(pScreenInfo, pATI, pATIHW); if (pATI->Chip >= ATI_CHIP_264CT) { /* Ensure proper VCLK source */ - pATIHW->pll_vclk_cntl = ATIGetMach64PLLReg(PLL_VCLK_CNTL) | + pATIHW->pll_vclk_cntl = ATIMach64GetPLLReg(PLL_VCLK_CNTL) | (PLL_VCLK_SRC_SEL | PLL_VCLK_RESET); /* Set provisional values for other PLL registers */ - pATIHW->pll_vclk_post_div = ATIGetMach64PLLReg(PLL_VCLK_POST_DIV); - pATIHW->pll_vclk0_fb_div = ATIGetMach64PLLReg(PLL_VCLK0_FB_DIV); - pATIHW->pll_vclk1_fb_div = ATIGetMach64PLLReg(PLL_VCLK1_FB_DIV); - pATIHW->pll_vclk2_fb_div = ATIGetMach64PLLReg(PLL_VCLK2_FB_DIV); - pATIHW->pll_vclk3_fb_div = ATIGetMach64PLLReg(PLL_VCLK3_FB_DIV); - pATIHW->pll_xclk_cntl = ATIGetMach64PLLReg(PLL_XCLK_CNTL); + pATIHW->pll_vclk_post_div = ATIMach64GetPLLReg(PLL_VCLK_POST_DIV); + pATIHW->pll_vclk0_fb_div = ATIMach64GetPLLReg(PLL_VCLK0_FB_DIV); + pATIHW->pll_vclk1_fb_div = ATIMach64GetPLLReg(PLL_VCLK1_FB_DIV); + pATIHW->pll_vclk2_fb_div = ATIMach64GetPLLReg(PLL_VCLK2_FB_DIV); + pATIHW->pll_vclk3_fb_div = ATIMach64GetPLLReg(PLL_VCLK3_FB_DIV); + pATIHW->pll_xclk_cntl = ATIMach64GetPLLReg(PLL_XCLK_CNTL); /* For now disable extended reference and feedback dividers */ if (pATI->Chip >= ATI_CHIP_264LT) pATIHW->pll_ext_vpll_cntl = - ATIGetMach64PLLReg(PLL_EXT_VPLL_CNTL) & + ATIMach64GetPLLReg(PLL_EXT_VPLL_CNTL) & ~(PLL_EXT_VPLL_EN | PLL_EXT_VPLL_VGA_EN | PLL_EXT_VPLL_INSYNC); @@ -304,10 +304,10 @@ ATIModePreInit if (pATI->Chip != ATI_CHIP_264XL) pATIHW->lcd_index |= LCD_CRTC2_DISPLAY_DIS; pATIHW->config_panel = - ATIGetMach64LCDReg(LCD_CONFIG_PANEL) | + ATIMach64GetLCDReg(LCD_CONFIG_PANEL) | DONT_SHADOW_HEND; pATIHW->lcd_gen_ctrl = - ATIGetMach64LCDReg(LCD_GEN_CNTL) & ~CRTC_RW_SELECT; + ATIMach64GetLCDReg(LCD_GEN_CNTL) & ~CRTC_RW_SELECT; outr(LCD_INDEX, lcd_index); } @@ -338,7 +338,9 @@ ATIModePreInit } } else if (pATI->DAC == ATI_DAC_IBMRGB514) + { ATIRGB514PreInit(pATI, pATIHW); + } } /* Set RAMDAC data */ @@ -373,16 +375,16 @@ ATIModeSave if (pATI->Chip >= ATI_CHIP_264CT) { - pATIHW->pll_vclk_cntl = ATIGetMach64PLLReg(PLL_VCLK_CNTL) | + pATIHW->pll_vclk_cntl = ATIMach64GetPLLReg(PLL_VCLK_CNTL) | PLL_VCLK_RESET; - pATIHW->pll_vclk_post_div = ATIGetMach64PLLReg(PLL_VCLK_POST_DIV); - pATIHW->pll_vclk0_fb_div = ATIGetMach64PLLReg(PLL_VCLK0_FB_DIV); - pATIHW->pll_vclk1_fb_div = ATIGetMach64PLLReg(PLL_VCLK1_FB_DIV); - pATIHW->pll_vclk2_fb_div = ATIGetMach64PLLReg(PLL_VCLK2_FB_DIV); - pATIHW->pll_vclk3_fb_div = ATIGetMach64PLLReg(PLL_VCLK3_FB_DIV); - pATIHW->pll_xclk_cntl = ATIGetMach64PLLReg(PLL_XCLK_CNTL); + pATIHW->pll_vclk_post_div = ATIMach64GetPLLReg(PLL_VCLK_POST_DIV); + pATIHW->pll_vclk0_fb_div = ATIMach64GetPLLReg(PLL_VCLK0_FB_DIV); + pATIHW->pll_vclk1_fb_div = ATIMach64GetPLLReg(PLL_VCLK1_FB_DIV); + pATIHW->pll_vclk2_fb_div = ATIMach64GetPLLReg(PLL_VCLK2_FB_DIV); + pATIHW->pll_vclk3_fb_div = ATIMach64GetPLLReg(PLL_VCLK3_FB_DIV); + pATIHW->pll_xclk_cntl = ATIMach64GetPLLReg(PLL_XCLK_CNTL); if (pATI->Chip >= ATI_CHIP_264LT) - pATIHW->pll_ext_vpll_cntl = ATIGetMach64PLLReg(PLL_EXT_VPLL_CNTL); + pATIHW->pll_ext_vpll_cntl = ATIMach64GetPLLReg(PLL_EXT_VPLL_CNTL); /* Save LCD registers */ if (pATI->LCDPanelID >= 0) @@ -394,26 +396,25 @@ ATIModeSave pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL); /* Set up to save non-shadow registers */ - outr(LCD_GEN_CTRL, - pATIHW->lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN)); + outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN); } else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ { pATIHW->lcd_index = inr(LCD_INDEX); - pATIHW->config_panel = ATIGetMach64LCDReg(LCD_CONFIG_PANEL); - pATIHW->lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL); + pATIHW->config_panel = ATIMach64GetLCDReg(LCD_CONFIG_PANEL); + pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); pATIHW->horz_stretching = - ATIGetMach64LCDReg(LCD_HORZ_STRETCHING); + ATIMach64GetLCDReg(LCD_HORZ_STRETCHING); pATIHW->vert_stretching = - ATIGetMach64LCDReg(LCD_VERT_STRETCHING); + ATIMach64GetLCDReg(LCD_VERT_STRETCHING); pATIHW->ext_vert_stretch = - ATIGetMach64LCDReg(LCD_EXT_VERT_STRETCH); + ATIMach64GetLCDReg(LCD_EXT_VERT_STRETCH); /* Set up to save non-shadow registers */ - ATIPutMach64LCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl & - ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN)); + ATIMach64PutLCDReg(LCD_GEN_CNTL, + pATIHW->lcd_gen_ctrl & ~(CRTC_RW_SELECT | SHADOW_RW_EN)); } } } @@ -430,12 +431,12 @@ ATIModeSave ATIVGAWonderSave(pATI, pATIHW); } - /* Save Mach64 data */ if (pATI->Chip >= ATI_CHIP_88800GXC) #endif /* AVOID_CPIO */ { + /* Save Mach64 data */ ATIMach64Save(pATI, pATIHW); if (pATI->Chip >= ATI_CHIP_264VTB) @@ -447,14 +448,13 @@ ATIModeSave { /* Switch to shadow registers */ if (pATI->Chip == ATI_CHIP_264LT) - outr(LCD_GEN_CTRL, - pATIHW->lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN)); + outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ - ATIPutMach64LCDReg(LCD_GEN_CNTL, + ATIMach64PutLCDReg(LCD_GEN_CNTL, (pATIHW->lcd_gen_ctrl & ~CRTC_RW_SELECT) | - (SHADOW_EN | SHADOW_RW_EN)); + SHADOW_RW_EN); #ifndef AVOID_CPIO @@ -475,12 +475,14 @@ ATIModeSave /* Restore CRTC selection and shadow state */ if (pATI->Chip == ATI_CHIP_264LT) + { outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl); + } else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ { - ATIPutMach64LCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl); + ATIMach64PutLCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl); outr(LCD_INDEX, pATIHW->lcd_index); } } @@ -556,9 +558,9 @@ ATIModeCalculate int Index, ECPClock, MaxScalerClock; /* Clobber mode timings */ - if ((pATI->LCDPanelID >= 0) && pATI->OptionPanelDisplay && + if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0) && !pMode->CrtcHAdjusted && !pMode->CrtcVAdjusted && - (!pATI->OptionSync || (pMode->type & M_T_BUILTIN))) + (!pATI->OptionLCDSync || (pMode->type & M_T_BUILTIN))) { int VScan; @@ -654,12 +656,60 @@ ATIModeCalculate ~(CRTC_DBL_SCAN_EN | CRTC_INTERLACE_EN | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_CSYNC_EN | CRTC_PIX_BY_2_EN | CRTC_DISPLAY_DIS | - CRTC_VGA_XOVERSCAN | CRTC_VGA_128KAP_PAGING | + CRTC_VGA_XOVERSCAN | CRTC_PIX_WIDTH | + CRTC_BYTE_PIX_ORDER | CRTC_VGA_128KAP_PAGING | CRTC_VFC_SYNC_TRISTATE | CRTC_LOCK_REGS | /* Already off, but ... */ CRTC_SYNC_TRISTATE | CRTC_EXT_DISP_EN | CRTC_DISP_REQ_EN | CRTC_VGA_LINEAR | CRTC_VGA_TEXT_132 | CRTC_CUR_B_TEST); + /* Some of these are not relevent, but that doesn't matter */ + switch (pATI->depth) + { + case 1: + pATIHW->crtc_gen_cntl |= + SetBits(PIX_WIDTH_1BPP, CRTC_PIX_WIDTH); + break; + + case 4: + pATIHW->crtc_gen_cntl |= + SetBits(PIX_WIDTH_4BPP, CRTC_PIX_WIDTH); + break; + + case 8: + pATIHW->crtc_gen_cntl |= + SetBits(PIX_WIDTH_8BPP, CRTC_PIX_WIDTH); + break; + + case 15: + pATIHW->crtc_gen_cntl |= + SetBits(PIX_WIDTH_15BPP, CRTC_PIX_WIDTH); + break; + + case 16: + pATIHW->crtc_gen_cntl |= + SetBits(PIX_WIDTH_16BPP, CRTC_PIX_WIDTH); + break; + + case 24: + if (pATI->bitsPerPixel == 24) + { + pATIHW->crtc_gen_cntl |= + SetBits(PIX_WIDTH_24BPP, CRTC_PIX_WIDTH); + break; + } + if (pATI->bitsPerPixel != 32) + break; + /* Fall through */ + + case 32: + pATIHW->crtc_gen_cntl |= + SetBits(PIX_WIDTH_32BPP, CRTC_PIX_WIDTH); + break; + + default: + break; + } #if 0 /* This isn't needed, but is kept for reference */ if (pMode->Flags & V_DBLSCAN) pATIHW->crtc_gen_cntl |= CRTC_DBL_SCAN_EN; @@ -703,15 +753,17 @@ ATIModeCalculate pATIHW->crtc_gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH); if (pATI->Chip == ATI_CHIP_264LT) + { pATIHW->horz_stretching = inr(HORZ_STRETCHING); + } else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ { lcd_index = inr(LCD_INDEX); - pATIHW->horz_stretching = ATIGetMach64LCDReg(LCD_HORZ_STRETCHING); + pATIHW->horz_stretching = ATIMach64GetLCDReg(LCD_HORZ_STRETCHING); pATIHW->ext_vert_stretch = - ATIGetMach64LCDReg(LCD_EXT_VERT_STRETCH) & + ATIMach64GetLCDReg(LCD_EXT_VERT_STRETCH) & ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3); /* @@ -814,7 +866,9 @@ ATIModeCalculate } while (0); if (!pATI->OptionPanelDisplay || (VDisplay >= pATI->LCDVertical)) + { pATIHW->vert_stretching = 0; + } else { pATIHW->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN) | @@ -861,7 +915,9 @@ ATIModeCalculate pATIHW->pll_vclk_cntl |= SetBits(Index, PLL_ECP_DIV); } else if (pATI->DAC == ATI_DAC_IBMRGB514) + { ATIRGB514Calculate(pATI, pATIHW, pMode); + } return TRUE; } @@ -890,57 +946,60 @@ ATIModeSet #endif /* AVOID_CPIO */ - if (pATI->Chip >= ATI_CHIP_264CT) + if (pATI->Chip >= ATI_CHIP_88800GXC) { - ATIPutMach64PLLReg(PLL_VCLK_CNTL, pATIHW->pll_vclk_cntl); - ATIPutMach64PLLReg(PLL_VCLK_POST_DIV, pATIHW->pll_vclk_post_div); - ATIPutMach64PLLReg(PLL_VCLK0_FB_DIV, pATIHW->pll_vclk0_fb_div); - ATIPutMach64PLLReg(PLL_VCLK1_FB_DIV, pATIHW->pll_vclk1_fb_div); - ATIPutMach64PLLReg(PLL_VCLK2_FB_DIV, pATIHW->pll_vclk2_fb_div); - ATIPutMach64PLLReg(PLL_VCLK3_FB_DIV, pATIHW->pll_vclk3_fb_div); - ATIPutMach64PLLReg(PLL_XCLK_CNTL, pATIHW->pll_xclk_cntl); - if (pATI->Chip >= ATI_CHIP_264LT) - ATIPutMach64PLLReg(PLL_EXT_VPLL_CNTL, pATIHW->pll_ext_vpll_cntl); - ATIPutMach64PLLReg(PLL_VCLK_CNTL, - pATIHW->pll_vclk_cntl & ~PLL_VCLK_RESET); + /* Stop CRTC */ + outr(CRTC_GEN_CNTL, + pATIHW->crtc_gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN)); - /* Load LCD registers */ - if (pATI->LCDPanelID >= 0) + if (pATI->Chip >= ATI_CHIP_264CT) { - /* Stop CRTC */ - outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl & - ~(CRTC_EXT_DISP_EN | CRTC_EN)); + ATIMach64PutPLLReg(PLL_VCLK_CNTL, pATIHW->pll_vclk_cntl); + ATIMach64PutPLLReg(PLL_VCLK_POST_DIV, pATIHW->pll_vclk_post_div); + ATIMach64PutPLLReg(PLL_VCLK0_FB_DIV, pATIHW->pll_vclk0_fb_div); + ATIMach64PutPLLReg(PLL_VCLK1_FB_DIV, pATIHW->pll_vclk1_fb_div); + ATIMach64PutPLLReg(PLL_VCLK2_FB_DIV, pATIHW->pll_vclk2_fb_div); + ATIMach64PutPLLReg(PLL_VCLK3_FB_DIV, pATIHW->pll_vclk3_fb_div); + ATIMach64PutPLLReg(PLL_XCLK_CNTL, pATIHW->pll_xclk_cntl); + if (pATI->Chip >= ATI_CHIP_264LT) + ATIMach64PutPLLReg(PLL_EXT_VPLL_CNTL, + pATIHW->pll_ext_vpll_cntl); + ATIMach64PutPLLReg(PLL_VCLK_CNTL, + pATIHW->pll_vclk_cntl & ~PLL_VCLK_RESET); - if (pATI->Chip == ATI_CHIP_264LT) - { - /* Update non-shadow registers first */ - outr(LCD_GEN_CTRL, - pATIHW->lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN)); - - /* Temporarily disable stretching */ - outr(HORZ_STRETCHING, pATIHW->horz_stretching & - ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN)); - outr(VERT_STRETCHING, pATIHW->vert_stretching & - ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 | - VERT_STRETCH_USE0 | VERT_STRETCH_EN)); - } - else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || - (pATI->Chip == ATI_CHIP_264XL) || - (pATI->Chip == ATI_CHIP_MOBILITY)) */ + /* Load LCD registers */ + if (pATI->LCDPanelID >= 0) { - /* Update non-shadow registers first */ - ATIPutMach64LCDReg(LCD_CONFIG_PANEL, pATIHW->config_panel); - ATIPutMach64LCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl & - ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN)); - - /* Temporarily disable stretching */ - ATIPutMach64LCDReg(LCD_HORZ_STRETCHING, - pATIHW->horz_stretching & - ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN)); - ATIPutMach64LCDReg(LCD_VERT_STRETCHING, - pATIHW->vert_stretching & - ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 | - VERT_STRETCH_USE0 | VERT_STRETCH_EN)); + if (pATI->Chip == ATI_CHIP_264LT) + { + /* Update non-shadow registers first */ + outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN); + + /* Temporarily disable stretching */ + outr(HORZ_STRETCHING, pATIHW->horz_stretching & + ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN)); + outr(VERT_STRETCHING, pATIHW->vert_stretching & + ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 | + VERT_STRETCH_USE0 | VERT_STRETCH_EN)); + } + else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || + (pATI->Chip == ATI_CHIP_264XL) || + (pATI->Chip == ATI_CHIP_MOBILITY)) */ + { + /* Update non-shadow registers first */ + ATIMach64PutLCDReg(LCD_CONFIG_PANEL, pATIHW->config_panel); + ATIMach64PutLCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl & + ~(CRTC_RW_SELECT | SHADOW_RW_EN)); + + /* Temporarily disable stretching */ + ATIMach64PutLCDReg(LCD_HORZ_STRETCHING, + pATIHW->horz_stretching & + ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN)); + ATIMach64PutLCDReg(LCD_VERT_STRETCHING, + pATIHW->vert_stretching & + ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 | + VERT_STRETCH_USE0 | VERT_STRETCH_EN)); + } } } } @@ -951,10 +1010,6 @@ ATIModeSet #ifndef AVOID_CPIO case ATI_CRTC_VGA: - /* Stop CRTC */ - if (pATI->Chip >= ATI_CHIP_88800GXC) - outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl & ~CRTC_EN); - /* Start sequencer reset */ PutReg(SEQX, 0x00U, 0x00U); @@ -977,14 +1032,20 @@ ATIModeSet /* Load Mach64 registers */ if (pATI->Chip >= ATI_CHIP_88800GXC) { + /* Load MMIO registers */ + if (pATI->Block0Base) + ATIMach64Set(pATI, pATIHW); + outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl); outr(CUR_CLR0, pATIHW->cur_clr0); outr(CUR_CLR1, pATIHW->cur_clr1); outr(CUR_OFFSET, pATIHW->cur_offset); outr(CUR_HORZ_VERT_POSN, pATIHW->cur_horz_vert_posn); outr(CUR_HORZ_VERT_OFF, pATIHW->cur_horz_vert_off); + outr(BUS_CNTL, pATIHW->bus_cntl); outr(MEM_VGA_WP_SEL, pATIHW->mem_vga_wp_sel); outr(MEM_VGA_RP_SEL, pATIHW->mem_vga_rp_sel); + outr(DAC_CNTL, pATIHW->dac_cntl); outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN); outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl); outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN); @@ -996,8 +1057,6 @@ ATIModeSet outr(CRTC_V_TOTAL_DISP, pATIHW->crtc_v_total_disp); outr(CRTC_V_SYNC_STRT_WID, pATIHW->crtc_v_sync_strt_wid); outr(CRTC_OFF_PITCH, pATIHW->crtc_off_pitch); - outr(BUS_CNTL, pATIHW->bus_cntl); - outr(DAC_CNTL, pATIHW->dac_cntl); if (pATI->Chip >= ATI_CHIP_264VTB) { outr(MEM_CNTL, pATIHW->mem_cntl); @@ -1040,14 +1099,12 @@ ATIModeSet { /* Switch to shadow registers */ if (pATI->Chip == ATI_CHIP_264LT) - outr(LCD_GEN_CTRL, - pATIHW->lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN)); + outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ - ATIPutMach64LCDReg(LCD_GEN_CNTL, - (pATIHW->lcd_gen_ctrl & ~CRTC_RW_SELECT) | - (SHADOW_EN | SHADOW_RW_EN)); + ATIMach64PutLCDReg(LCD_GEN_CNTL, + (pATIHW->lcd_gen_ctrl & ~CRTC_RW_SELECT) | SHADOW_RW_EN); /* Restore shadow registers */ switch (pATIHW->crtc) @@ -1087,10 +1144,10 @@ ATIModeSet (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) */ { - ATIPutMach64LCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl); - ATIPutMach64LCDReg(LCD_HORZ_STRETCHING, pATIHW->horz_stretching); - ATIPutMach64LCDReg(LCD_VERT_STRETCHING, pATIHW->vert_stretching); - ATIPutMach64LCDReg(LCD_EXT_VERT_STRETCH, pATIHW->ext_vert_stretch); + ATIMach64PutLCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl); + ATIMach64PutLCDReg(LCD_HORZ_STRETCHING, pATIHW->horz_stretching); + ATIMach64PutLCDReg(LCD_VERT_STRETCHING, pATIHW->vert_stretching); + ATIMach64PutLCDReg(LCD_EXT_VERT_STRETCH, pATIHW->ext_vert_stretch); outr(LCD_INDEX, pATIHW->lcd_index); } } diff --git a/src/atimodule.c b/src/atimodule.c index 842d659c..ed6b6215 100644 --- a/src/atimodule.c +++ b/src/atimodule.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimodule.c,v 1.15 2003/01/01 19:16:32 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimodule.c,v 1.16 2003/05/28 14:08:03 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -67,6 +67,7 @@ const char *RADEONSymbols[] = "RADEONFreeScreen", "RADEONValidMode", "RADEONOptions", + "RADEONHandleMessage", NULL }; diff --git a/src/atioption.c b/src/atioption.c index 573bb100..6b84128c 100644 --- a/src/atioption.c +++ b/src/atioption.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atioption.c,v 1.21 2003/01/01 19:16:33 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atioption.c,v 1.22 2003/04/23 21:51:29 tsi Exp $ */ /* * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -81,6 +81,13 @@ const OptionInfoRec ATIPublicOptions[] = FALSE }, { + ATI_OPTION_TEST_MMIO_CACHE, + "test_mmio_cache", + OPTV_BOOLEAN, + {0, }, + FALSE + }, + { ATI_OPTION_PANEL_DISPLAY, "panel_display", OPTV_BOOLEAN, diff --git a/src/atioption.h b/src/atioption.h index ea66018f..2e629b8d 100644 --- a/src/atioption.h +++ b/src/atioption.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atioption.h,v 1.11 2003/01/01 19:16:33 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atioption.h,v 1.12 2003/04/23 21:51:29 tsi Exp $ */ /* * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -45,6 +45,7 @@ typedef enum #endif /* AVOID_CPIO */ ATI_OPTION_MMIO_CACHE, + ATI_OPTION_TEST_MMIO_CACHE, ATI_OPTION_PANEL_DISPLAY, ATI_OPTION_PROBE_CLOCKS, ATI_OPTION_REFERENCE_CLOCK, diff --git a/src/atipreinit.c b/src/atipreinit.c index 675b036d..914476a1 100644 --- a/src/atipreinit.c +++ b/src/atipreinit.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atipreinit.c,v 1.65 2003/01/01 19:16:33 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atipreinit.c,v 1.71 2003/11/13 21:21:34 tsi Exp $ */ /* * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -24,22 +24,26 @@ #include "ati.h" #include "atiadapter.h" #include "atiadjust.h" +#include "atiaudio.h" #include "atibus.h" #include "atichip.h" #include "aticonfig.h" #include "aticursor.h" #include "atidac.h" #include "atidsp.h" +#include "atii2c.h" #include "atiident.h" #include "atiload.h" #include "atilock.h" #include "atimach64.h" +#include "atimach64accel.h" #include "atimach64io.h" #include "atimode.h" #include "atipreinit.h" #include "atiprint.h" #include "atividmem.h" #include "atiwonderio.h" +#include "atixv.h" #include "vbe.h" #include "xf86RAC.h" @@ -248,12 +252,14 @@ ATIMach32videoRam /* Test for lost pixels */ AllPixelsOK = TRUE; ForEachTestPixel + { if (ATIMach32ReadPixel(TestPixel.x, TestPixel.y) != Test_Pixel[Pixel_Number]) { AllPixelsOK = FALSE; break; } + } /* Restore clobbered pixels */ ForEachTestPixel @@ -319,8 +325,10 @@ ATIReportMemory #endif /* AVOID_CPIO */ if (pATI->VideoRAM > pScreenInfo->videoRam) + { Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message, " (using %d kB)", pScreenInfo->videoRam); + } xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s.\n", Buffer); } @@ -330,12 +338,12 @@ static const rgb defaultWeight = {0, 0, 0}; static const Gamma defaultGamma = {0.0, 0.0, 0.0}; /* - * ATIMapMach64 -- + * ATIMach64Map -- * * This function attempts to mmap() a Mach64's MMIO aperture. */ static void -ATIMapMach64 +ATIMach64Map ( int iScreen, ATIPtr pATI @@ -394,7 +402,8 @@ ATIPreInit (BIOS[(_n) + 3] << 24))) unsigned int BIOSSize = 0; unsigned int ROMTable = 0, ClockTable = 0, FrequencyTable = 0; - unsigned int LCDTable = 0, LCDPanelInfo = 0; + unsigned int LCDTable = 0, LCDPanelInfo = 0, VideoTable = 0; + unsigned int HardwareTable = 0; char Buffer[128], *Message; ATIPtr pATI; @@ -412,7 +421,9 @@ ATIPreInit int DefaultmaxClock = 0; int minPitch, maxPitch = 0xFFU, maxHeight = 0; int ApertureSize = 0x00010000U; + int ModeType = M_T_BUILTIN; LookupModeFlags Strategy = LOOKUP_CLOSEST_CLOCK; + int DefaultDepth; # define pATIHW (&pATI->OldHW) @@ -509,10 +520,17 @@ ATIPreInit /* Set depth, bpp, etc. */ if ((pATI->Chipset != ATI_CHIPSET_ATI) || (pATI->Chip < ATI_CHIP_264CT)) + { i = NoDepth24Support; /* No support for >8bpp either */ + DefaultDepth = 8; + } else + { i = Support24bppFb | Support32bppFb; - if (!xf86SetDepthBpp(pScreenInfo, 8, 8, 8, i)) + DefaultDepth = 0; + } + + if (!xf86SetDepthBpp(pScreenInfo, DefaultDepth, 0, 0, i)) return FALSE; for (j = 0; ; j++) @@ -573,7 +591,9 @@ ATIPreInit #ifdef AVOID_CPIO else /* if (flags & PROBE_DETECT) */ + { return TRUE; + } #else /* AVOID_CPIO */ @@ -582,20 +602,28 @@ ATIPreInit * has been executed, and retrieve DDC and VBE information from it. */ if (!(pInt10Module = ATILoadModule(pScreenInfo, "int10", ATIint10Symbols))) + { xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "Unable to load int10 module.\n"); + } else if (!(pInt10Info = xf86InitInt10(pATI->iEntity))) + { xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "Unable to initialise int10 interface.\n"); + } else { if (!(pDDCModule = ATILoadModule(pScreenInfo, "ddc", ATIddcSymbols))) + { xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "Unable to load ddc module.\n"); + } else if (!(pVBEModule = ATILoadModule(pScreenInfo, "vbe", ATIvbeSymbols))) + { xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "Unable to load vbe module.\n"); + } else { if ((pVBE = VBEInit(pInt10Info, pATI->iEntity))) @@ -612,8 +640,10 @@ ATIPreInit CARD8 *pBIOS = xf86int10Addr(pInt10Info, pInt10Info->BIOSseg << 4); if ((pBIOS[0] != 0x55U) || (pBIOS[1] != 0xAAU) || !pBIOS[2]) + { xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "Unable to correctly retrieve adapter BIOS.\n"); + } else { BIOSSize = pBIOS[2] << 9; @@ -722,6 +752,7 @@ ATIPreInit pATI->LCDPanelID = -1; pATI->nFIFOEntries = 16; /* For now */ + pATI->Audio = ATI_AUDIO_NONE; /* Finish probing the adapter */ switch (pATI->Adapter) @@ -805,12 +836,12 @@ ATIPreInit if ((pATI->Block0Base = pVideo->memBase[0])) { pATI->Block0Base += 0x007FFC00U; - ATIMapMach64(pScreenInfo->scrnIndex, pATI); + ATIMach64Map(pScreenInfo->scrnIndex, pATI); if (pATI->pBlock[0]) break; pATI->Block0Base -= 0x00400000U; - ATIMapMach64(pScreenInfo->scrnIndex, pATI); + ATIMach64Map(pScreenInfo->scrnIndex, pATI); if (pATI->pBlock[0]) break; } @@ -820,7 +851,7 @@ ATIPreInit pATI->Block0Base = 0x000BFC00U; } - ATIMapMach64(pScreenInfo->scrnIndex, pATI); + ATIMach64Map(pScreenInfo->scrnIndex, pATI); } while (0); pATI->Block0Base = Block0Base; @@ -862,8 +893,10 @@ ATIPreInit pATIHW->mem_cntl = inr(MEM_CNTL); if (pATI->Chip < ATI_CHIP_264VTB) + { pATI->VideoRAM = videoRamSizes[GetBits(pATIHW->mem_cntl, CTL_MEM_SIZE) + 2]; + } else { pATI->nFIFOEntries = /* Don't care */ @@ -885,7 +918,7 @@ ATIPreInit { pATI->MemoryType = GetBits(IOValue, CFG_MEM_TYPE_T); - /* Get LCD panel id and set LCD & TV I/O port numbers */ + /* Get LCD panel id */ if (pATI->Chip == ATI_CHIP_264LT) { pATI->LCDPanelID = GetBits(IOValue, CFG_PANEL_ID); @@ -902,7 +935,7 @@ ATIPreInit pATIHW->lcd_index = inr(LCD_INDEX); pATIHW->horz_stretching = - ATIGetMach64LCDReg(LCD_HORZ_STRETCHING); + ATIMach64GetLCDReg(LCD_HORZ_STRETCHING); pATI->LCDHorizontal = GetBits(pATIHW->horz_stretching, HORZ_PANEL_SIZE); if (pATI->LCDHorizontal) @@ -914,7 +947,7 @@ ATIPreInit (pATI->LCDHorizontal + 1) << 3; } pATIHW->ext_vert_stretch = - ATIGetMach64LCDReg(LCD_EXT_VERT_STRETCH); + ATIMach64GetLCDReg(LCD_EXT_VERT_STRETCH); pATI->LCDVertical = GetBits(pATIHW->ext_vert_stretch, VERT_PANEL_SIZE); if (pATI->LCDVertical) @@ -925,8 +958,8 @@ ATIPreInit pATI->LCDVertical++; } pATIHW->vert_stretching = - ATIGetMach64LCDReg(LCD_VERT_STRETCHING); - pATIHW->lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL); + ATIMach64GetLCDReg(LCD_VERT_STRETCHING); + pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); outr(LCD_INDEX, pATIHW->lcd_index); } @@ -993,7 +1026,9 @@ ATIPreInit pATI->ClockNumberToProgramme = -1; ROMTable = BIOSWord(0x48U); - if ((ROMTable + 0x12U) > BIOSSize) + if ((ROMTable < 0x0002U) || + (BIOSWord(ROMTable - 0x02U) < 0x0012U) || + ((ROMTable + BIOSWord(ROMTable - 0x02U)) > BIOSSize)) ROMTable = 0; if (ROMTable > 0) @@ -1001,6 +1036,26 @@ ATIPreInit ClockTable = BIOSWord(ROMTable + 0x10U); if ((ClockTable + 0x20U) > BIOSSize) ClockTable = 0; + + if (BIOSWord(ROMTable - 0x02U) >= 0x0048U) + { + VideoTable = BIOSWord(ROMTable + 0x46U); + if ((VideoTable < 0x08U) || + (BIOSByte(VideoTable - 0x01U) < 0x08U) || + (BIOSByte(VideoTable - 0x02U) > 0x01U) || + ((VideoTable + BIOSByte(VideoTable - 0x01U)) > BIOSSize)) + VideoTable = 0; + } + + if (BIOSWord(ROMTable - 0x02U) >= 0x004AU) + { + HardwareTable = BIOSWord(ROMTable + 0x48U); + if (((HardwareTable + 0x08U) <= BIOSSize) && + !memcmp(BIOS + HardwareTable, "$ATI", 4)) + pATI->I2CType = BIOSByte(HardwareTable + 0x06U) & 0x0FU; + else + HardwareTable = 0; + } } if (ClockTable > 0) @@ -1043,7 +1098,9 @@ ATIPreInit * frequency has already been set by option processing. */ if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL) + { pATI->ProgrammableClock = ATI_CLOCK_INTERNAL; + } else switch (pATI->DAC) { case ATI_DAC_STG1703: @@ -1135,7 +1192,7 @@ ATIPreInit * graphics controller's tolerance. */ pATI->ClockDescriptor.MinM = pATI->ClockDescriptor.MaxM = - ATIGetMach64PLLReg(PLL_REF_DIV); + ATIMach64GetPLLReg(PLL_REF_DIV); /* The DAC is also integrated */ if ((pATI->DAC & ~0x0FU) != ATI_DAC_INTERNAL) @@ -1178,7 +1235,55 @@ ATIPreInit pATI->ClockNumberToProgramme = 7; } else + { pATI->DAC = ClockDac; /* For now */ + } + } + + /* + * Pick up multimedia information, which will be at different + * displacements depending on table revision. + */ + if (VideoTable > 0) + { + switch (BIOSByte(VideoTable - 0x02U)) + { + case 0x00U: + pATI->Tuner = BIOSByte(VideoTable) & 0x1FU; + + /* + * XXX The VideoTable[1] byte is known to have been + * omitted in LTPro and Mobility BIOS'es. Any others? + */ + switch (pATI->Chip) + { + case ATI_CHIP_264LTPRO: + case ATI_CHIP_MOBILITY: + pATI->Decoder = + BIOSByte(VideoTable + 0x01U) & 0x07U; + pATI->Audio = + BIOSByte(VideoTable + 0x02U) & 0x0FU; + break; + + default: + pATI->Decoder = + BIOSByte(VideoTable + 0x02U) & 0x07U; + pATI->Audio = + BIOSByte(VideoTable + 0x03U) & 0x0FU; + break; + } + + break; + + case 0x01U: + pATI->Tuner = BIOSByte(VideoTable) & 0x1FU; + pATI->Audio = BIOSByte(VideoTable + 0x01U) & 0x0FU; + pATI->Decoder = BIOSByte(VideoTable + 0x05U) & 0x0FU; + break; + + default: + break; + } } /* Determine panel dimensions */ @@ -1213,11 +1318,13 @@ ATIPreInit /* ... followed by 24-byte panel model name ... */ for (j = 0; j < 24; j++) + { if ((CARD8)(BIOSByte(i + j + 1) - 0x20U) > 0x5FU) { i += j; goto NextBIOSByte; } + } /* ... verify panel width ... */ if (pATI->LCDHorizontal && @@ -1262,6 +1369,23 @@ ATIPreInit pATI->LCDVertical = BIOSWord(LCDPanelInfo + 0x1BU); } } + + xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3, + "BIOS Data: BIOSSize=0x%04X, ROMTable=0x%04X.\n", + BIOSSize, ROMTable); + xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3, + "BIOS Data: ClockTable=0x%04X, FrequencyTable=0x%04X.\n", + ClockTable, FrequencyTable); + xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3, + "BIOS Data: LCDTable=0x%04X, LCDPanelInfo=0x%04X.\n", + LCDTable, LCDPanelInfo); + xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3, + "BIOS Data: VideoTable=0x%04X, HardwareTable=0x%04X.\n", + VideoTable, HardwareTable); + xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3, + "BIOS Data: I2CType=0x%02X, Tuner=0x%02X, Decoder=0x%02X," + " Audio=0x%02X.\n", + pATI->I2CType, pATI->Tuner, pATI->Decoder, pATI->Audio); } ATIUnlock(pATI); /* Unlock registers */ @@ -1323,7 +1447,6 @@ ATIPreInit #ifndef AVOID_CPIO if (pATI->Adapter >= ATI_ADAPTER_MACH64) - { Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message, "; %s I/O base is 0x%04lX", @@ -1340,7 +1463,7 @@ ATIPreInit if (pATI->CPIO_VGAWonder) xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, - "VGA Wonder registers at I/O port 0x%04X.\n", + "VGA Wonder registers at I/O port 0x%04lX.\n", pATI->CPIO_VGAWonder); if (pATI->Coprocessor != ATI_CHIP_NONE) @@ -1360,8 +1483,10 @@ ATIPreInit " adapter, please see http://gatos.sf.net.\n"); if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL) + { xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "Internal RAMDAC (subtype %d) detected.\n", pATI->DAC & 0x0FU); + } else { const SymTabRec *DAC; @@ -1424,8 +1549,8 @@ ATIPreInit { xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, "Driver does not support weight %d%d%d for depth %d.\n", - pScreenInfo->weight.red, pScreenInfo->weight.green, - pScreenInfo->weight.blue, pScreenInfo->depth); + (int)pScreenInfo->weight.red, (int)pScreenInfo->weight.green, + (int)pScreenInfo->weight.blue, pScreenInfo->depth); ATILock(pATI); ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize); ATIUnmapApertures(pScreenInfo->scrnIndex, pATI); @@ -1585,77 +1710,223 @@ ATIPreInit } else { - int HDisplay, VDisplay; + unsigned HDisplay, VDisplay; CARD8 ClockMask, PostMask; /* - * Determine porch data. The following is inaccurate (but still - * good enough) when BIOS initialisation has set things up so that - * the registers read here are not the ones actually in use by the - * panel. Thus, a further refinement here would be to flip back - * and forth between shadow and non-shadow registers as dictated by - * the various LCD_GEN_CNTL and CONFIG_PANEL bits involved. - * - * This groks the mode on entry to extract the width and position - * of its sync and blanking pulses, and considers any overscan as - * part of the displayed area, given that the overscan is also - * stretched. + * Determine porch data. This groks the mode on entry to extract + * the width and position of its sync and blanking pulses, and + * considers any overscan as part of the displayed area, given that + * the overscan is also stretched. * * This also attempts to determine panel dimensions but cannot do * so for one that is "auto-stretched". */ + if (pATI->Chip == ATI_CHIP_264LT) + { + pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL); + + /* Set up to read non-shadow registers */ + if (pATIHW->lcd_gen_ctrl & SHADOW_RW_EN) + outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN); + } + else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || + (pATI->Chip == ATI_CHIP_264XL) || + (pATI->Chip == ATI_CHIP_MOBILITY)) */ + { + pATIHW->lcd_index = inr(LCD_INDEX); + pATIHW->config_panel = ATIMach64GetLCDReg(LCD_CONFIG_PANEL); + pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); + + /* Set up to read non-shadow registers */ + if (pATIHW->lcd_gen_ctrl & SHADOW_RW_EN) + ATIMach64PutLCDReg(LCD_GEN_CNTL, + pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN); + } + #ifndef AVOID_CPIO if (!(pATIHW->crtc_gen_cntl & CRTC_EXT_DISP_EN)) { + unsigned HBlankStart, HSyncStart, HSyncEnd, HBlankEnd, HTotal; + unsigned VBlankStart, VSyncStart, VSyncEnd, VBlankEnd, VTotal; + pATIHW->clock = (inb(R_GENMO) & 0x0CU) >> 2; - pATIHW->crt[0] = GetReg(CRTX(pATI->CPIO_VGABase), 0x00U); pATIHW->crt[2] = GetReg(CRTX(pATI->CPIO_VGABase), 0x02U); pATIHW->crt[3] = GetReg(CRTX(pATI->CPIO_VGABase), 0x03U); - pATIHW->crt[4] = GetReg(CRTX(pATI->CPIO_VGABase), 0x04U); pATIHW->crt[5] = GetReg(CRTX(pATI->CPIO_VGABase), 0x05U); - pATIHW->crt[6] = GetReg(CRTX(pATI->CPIO_VGABase), 0x06U); pATIHW->crt[7] = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U); pATIHW->crt[9] = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U); - pATIHW->crt[16] = GetReg(CRTX(pATI->CPIO_VGABase), 0x10U); - pATIHW->crt[17] = GetReg(CRTX(pATI->CPIO_VGABase), 0x11U); pATIHW->crt[21] = GetReg(CRTX(pATI->CPIO_VGABase), 0x15U); pATIHW->crt[22] = GetReg(CRTX(pATI->CPIO_VGABase), 0x16U); - pATI->LCDHSyncWidth = - (pATIHW->crt[5] - pATIHW->crt[4]) & 0x1FU; - pATI->LCDHBlankWidth = (((pATIHW->crt[3] & 0x1FU) | - ((pATIHW->crt[5] >> 2) & 0x20U)) - - pATIHW->crt[2]) & 0x3FU; - pATI->LCDVSyncWidth = - (pATIHW->crt[17] - pATIHW->crt[16]) & 0x0FU; - pATI->LCDVBlankWidth = - ((pATIHW->crt[22] - pATIHW->crt[21]) & 0xFFU) + 1; + pATIHW->crtc_h_total_disp = inr(CRTC_H_TOTAL_DISP); + pATIHW->crtc_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID); + pATIHW->crtc_v_total_disp = inr(CRTC_V_TOTAL_DISP); + pATIHW->crtc_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID); - pATI->LCDHSyncStart = - ((pATIHW->crt[4] - pATIHW->crt[2]) & 0xFFU) + 1; - pATI->LCDVSyncStart = (((((pATIHW->crt[7] << 2) & 0x0200U) | - ((pATIHW->crt[7] << 6) & 0x0100U) | - pATIHW->crt[16]) - - (((pATIHW->crt[9] << 4) & 0x0200U) | - ((pATIHW->crt[7] << 5) & 0x0100U) | - pATIHW->crt[21])) & 0xFFU) + 1; - - HDisplay = pATI->LCDHSyncStart + pATI->LCDHSyncWidth - - pATI->LCDHBlankWidth; - if (HDisplay > 0) - pATI->LCDHBlankWidth += (HDisplay + 0x3FU) & ~0x3FU; - VDisplay = pATI->LCDVSyncStart + pATI->LCDVSyncWidth - - pATI->LCDVBlankWidth; - if (VDisplay > 0) - pATI->LCDVBlankWidth += (VDisplay + 0xFFU) & ~0xFFU; - - HDisplay = pATIHW->crt[0] + 5 - pATI->LCDHBlankWidth; - VDisplay = (((pATIHW->crt[7] << 4) & 0x0200U) | - ((pATIHW->crt[7] << 8) & 0x0100U) | - pATIHW->crt[6]) + 3 - pATI->LCDVBlankWidth; + /* Switch to shadow registers */ + if (pATI->Chip == ATI_CHIP_264LT) + outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); + else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || + (pATI->Chip == ATI_CHIP_264XL) || + (pATI->Chip == ATI_CHIP_MOBILITY)) */ + ATIMach64PutLCDReg(LCD_GEN_CNTL, + pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); + + pATIHW->shadow_vga[2] = + GetReg(CRTX(pATI->CPIO_VGABase), 0x02U); + pATIHW->shadow_vga[3] = + GetReg(CRTX(pATI->CPIO_VGABase), 0x03U); + pATIHW->shadow_vga[5] = + GetReg(CRTX(pATI->CPIO_VGABase), 0x05U); + pATIHW->shadow_vga[7] = + GetReg(CRTX(pATI->CPIO_VGABase), 0x07U); + pATIHW->shadow_vga[9] = + GetReg(CRTX(pATI->CPIO_VGABase), 0x09U); + pATIHW->shadow_vga[21] = + GetReg(CRTX(pATI->CPIO_VGABase), 0x15U); + pATIHW->shadow_vga[22] = + GetReg(CRTX(pATI->CPIO_VGABase), 0x16U); + + pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP); + pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID); + pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP); + pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID); + + /* + * HSyncStart and HSyncEnd should equal their shadow + * counterparts. Otherwise, due to a chip bug, the panel might + * not sync, regardless of which register set is used to drive + * the panel. There are certain combinations of register + * values where the panel does in fact sync, but it remains + * impossible to accurately determine the horizontal sync pulse + * timing actually seen by the panel. + * + * Note that this hardware bug does not affect the CRT output. + */ + if (((pATIHW->crtc_h_sync_strt_wid ^ + pATIHW->shadow_h_sync_strt_wid) & + (CRTC_H_SYNC_STRT | CRTC_H_SYNC_STRT_HI | + CRTC_H_SYNC_WID))) + { + xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_NOTICE, 0, + "Invalid horizontal sync pulse timing detected in mode" + " on server entry.\n"); + + /* Don't trust input timing */ + pATI->OptionLCDSync = TRUE; + ModeType = 0; + } + + /* Merge in shadow registers as appropriate */ + if (pATIHW->lcd_gen_ctrl & SHADOW_EN) + { + pATIHW->crt[2] = pATIHW->shadow_vga[2]; + pATIHW->crt[3] = pATIHW->shadow_vga[3]; + pATIHW->crt[5] = pATIHW->shadow_vga[5]; + + /* XXX Does this apply to VGA? If so, what about the LT? */ + if ((pATI->Chip < ATI_CHIP_264LTPRO) || + !(pATIHW->config_panel & DONT_SHADOW_HEND)) + { + pATIHW->crtc_h_total_disp &= ~CRTC_H_DISP; + pATIHW->crtc_h_total_disp |= + pATIHW->shadow_h_total_disp & CRTC_H_DISP; + } + + pATIHW->crtc_h_total_disp &= ~CRTC_H_TOTAL; + pATIHW->crtc_h_total_disp |= + pATIHW->shadow_h_total_disp & CRTC_H_TOTAL; + pATIHW->crtc_h_sync_strt_wid = + pATIHW->shadow_h_sync_strt_wid; + + /* XXX Does this apply to VGA? */ + if (pATIHW->lcd_gen_ctrl & USE_SHADOWED_VEND) + { + pATIHW->crtc_v_total_disp &= ~CRTC_V_DISP; + pATIHW->crtc_v_total_disp |= + pATIHW->shadow_v_total_disp & CRTC_V_DISP; + } + + if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR)) + { + pATIHW->crt[7] = pATIHW->shadow_vga[7]; + pATIHW->crt[9] = pATIHW->shadow_vga[9]; + pATIHW->crt[21] = pATIHW->shadow_vga[21]; + pATIHW->crt[22] = pATIHW->shadow_vga[22]; + + pATIHW->crtc_v_total_disp &= ~CRTC_V_TOTAL; + pATIHW->crtc_v_total_disp |= + pATIHW->shadow_v_total_disp & CRTC_V_TOTAL; + } + } + + if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR)) + pATIHW->crtc_v_sync_strt_wid = + pATIHW->shadow_v_sync_strt_wid; + + /* + * Decipher input timing. This is complicated by the fact that + * the full width of all timing parameters, except for the + * blanking pulses, is only available through the accelerator + * registers, not the VGA ones. Blanking pulse boundaries must + * then be interpolated. + * + * Note that, in VGA mode, the accelerator's sync width fields + * are actually end positions, not widths. + */ + HDisplay = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_DISP); + HSyncStart = + (GetBits(pATIHW->crtc_h_sync_strt_wid, + CRTC_H_SYNC_STRT_HI) * + (MaxBits(CRTC_H_SYNC_STRT) + 1)) | + GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_STRT); + HSyncEnd = (HSyncStart & ~MaxBits(CRTC_H_SYNC_WID)) | + GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_WID); + if (HSyncStart >= HSyncEnd) + HSyncEnd += MaxBits(CRTC_H_SYNC_WID) + 1; + HTotal = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_TOTAL); + + HBlankStart = (HDisplay & ~0xFFU) | pATIHW->crt[2]; + if (HDisplay > HBlankStart) + HBlankStart += 0x0100U; + HBlankEnd = (HSyncEnd & ~0x3FU) | + ((pATIHW->crt[5] >> 2) & 0x20U) | + (pATIHW->crt[3] & 0x1FU); + if (HSyncEnd > (HBlankEnd + 1)) + HBlankEnd += 0x40U; + + VDisplay = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_DISP); + VSyncStart = + GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_STRT); + VSyncEnd = (VSyncStart & ~MaxBits(CRTC_V_SYNC_WID)) | + GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_WID); + if (VSyncStart > VSyncEnd) + VSyncEnd += MaxBits(CRTC_V_SYNC_WID) + 1; + VTotal = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_TOTAL); + + VBlankStart = (VDisplay & ~0x03FFU) | + ((pATIHW->crt[9] << 4) & 0x0200U) | + ((pATIHW->crt[7] << 5) & 0x0100U) | pATIHW->crt[21]; + if (VDisplay > VBlankStart) + VBlankStart += 0x0400U; + VBlankEnd = (VSyncEnd & ~0x00FFU) | pATIHW->crt[22]; + if (VSyncEnd > (VBlankEnd + 1)) + VBlankEnd += 0x0100U; + + pATI->LCDHBlankWidth = HBlankEnd - HBlankStart; + pATI->LCDHSyncStart = HSyncStart - HBlankStart - 1; + pATI->LCDHSyncWidth = HSyncEnd - HSyncStart; + + pATI->LCDVBlankWidth = VBlankEnd - VBlankStart; + pATI->LCDVSyncStart = VSyncStart - VBlankStart - 1; + pATI->LCDVSyncWidth = VSyncEnd - VSyncStart; + + HDisplay = HTotal + 5 - pATI->LCDHBlankWidth; + VDisplay = VTotal + 2 - pATI->LCDVBlankWidth; } else @@ -1671,6 +1942,84 @@ ATIPreInit pATIHW->ovr_wid_left_right = inr(OVR_WID_LEFT_RIGHT); pATIHW->ovr_wid_top_bottom = inr(OVR_WID_TOP_BOTTOM); + /* Switch to shadow registers */ + if (pATI->Chip == ATI_CHIP_264LT) + outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); + else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || + (pATI->Chip == ATI_CHIP_264XL) || + (pATI->Chip == ATI_CHIP_MOBILITY)) */ + ATIMach64PutLCDReg(LCD_GEN_CNTL, + pATIHW->lcd_gen_ctrl | SHADOW_RW_EN); + + /* Oddly enough, there are no shadow overscan registers */ + pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP); + pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID); + pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP); + pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID); + + /* + * HSyncStart and HSyncEnd should equal their shadow + * counterparts. Otherwise, due to a chip bug, the panel might + * not sync, regardless of which register set is used to drive + * the panel. There are certain combinations of register + * values where the panel does in fact sync, but it remains + * impossible to accurately determine the horizontal sync pulse + * timing actually seen by the panel. + * + * Note that this hardware bug does not affect the CRT output. + */ + if (((pATIHW->crtc_h_sync_strt_wid ^ + pATIHW->shadow_h_sync_strt_wid) & + (CRTC_H_SYNC_STRT | CRTC_H_SYNC_STRT_HI | + CRTC_H_SYNC_WID))) + { + xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_NOTICE, 0, + "Invalid horizontal sync pulse timing detected in mode" + " on server entry.\n"); + + /* Don't trust input timing */ + pATI->OptionLCDSync = TRUE; + ModeType = 0; + } + + /* Merge in shadow registers as appropriate */ + if (pATIHW->lcd_gen_ctrl & SHADOW_EN) + { + /* XXX What about the LT? */ + if ((pATI->Chip < ATI_CHIP_264LTPRO) || + !(pATIHW->config_panel & DONT_SHADOW_HEND)) + { + pATIHW->crtc_h_total_disp &= ~CRTC_H_DISP; + pATIHW->crtc_h_total_disp |= + pATIHW->shadow_h_total_disp & CRTC_H_DISP; + } + + pATIHW->crtc_h_total_disp &= ~CRTC_H_TOTAL; + pATIHW->crtc_h_total_disp |= + pATIHW->shadow_h_total_disp & CRTC_H_TOTAL; + pATIHW->crtc_h_sync_strt_wid = + pATIHW->shadow_h_sync_strt_wid; + + if (pATIHW->lcd_gen_ctrl & USE_SHADOWED_VEND) + { + pATIHW->crtc_v_total_disp &= ~CRTC_V_DISP; + pATIHW->crtc_v_total_disp |= + pATIHW->shadow_v_total_disp & CRTC_V_DISP; + } + + if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR)) + { + pATIHW->crtc_v_total_disp &= ~CRTC_V_TOTAL; + pATIHW->crtc_v_total_disp |= + pATIHW->shadow_v_total_disp & CRTC_V_TOTAL; + } + } + + if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR)) + pATIHW->crtc_v_sync_strt_wid = + pATIHW->shadow_v_sync_strt_wid; + + /* Decipher input timing */ HDisplay = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_DISP) + GetBits(pATIHW->ovr_wid_left_right, OVR_WID_LEFT) + GetBits(pATIHW->ovr_wid_left_right, OVR_WID_RIGHT); @@ -1702,6 +2051,19 @@ ATIPreInit VDisplay++; } + /* Restore LCD registers */ + if (pATI->Chip == ATI_CHIP_264LT) + { + outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl); + } + else /* if ((pATI->Chip == ATI_CHIP_264LTPRO) || + (pATI->Chip == ATI_CHIP_264XL) || + (pATI->Chip == ATI_CHIP_MOBILITY)) */ + { + ATIMach64PutLCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl); + outr(LCD_INDEX, pATIHW->lcd_index); + } + HDisplay <<= 3; pATI->LCDHSyncStart <<= 3; pATI->LCDHSyncWidth <<= 3; @@ -1810,7 +2172,7 @@ ATIPreInit (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) pATI->LCDHorizontal = HDisplay; } - else if (pATI->LCDHorizontal != HDisplay) + else if (pATI->LCDHorizontal != (int)HDisplay) { if ((pATIHW->horz_stretching & (HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) != @@ -1827,7 +2189,7 @@ ATIPreInit !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO)) pATI->LCDVertical = VDisplay; } - else if (pATI->LCDVertical != VDisplay) + else if (pATI->LCDVertical != (int)VDisplay) { if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) || !(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO)) @@ -1857,8 +2219,9 @@ ATIPreInit if (!(pATIHW->horz_stretching & HORZ_STRETCH_EN) && ((HDisplay = pATI->LCDHorizontal - HDisplay) > 0)) { - pATI->LCDHSyncStart -= HDisplay; - if (pATI->LCDHSyncStart < 0) + if (pATI->LCDHSyncStart >= HDisplay) + pATI->LCDHSyncStart -= HDisplay; + else pATI->LCDHSyncStart = 0; pATI->LCDHBlankWidth -= HDisplay; HDisplay = pATI->LCDHSyncStart + pATI->LCDHSyncWidth; @@ -1869,8 +2232,9 @@ ATIPreInit if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) && ((VDisplay = pATI->LCDVertical - VDisplay) > 0)) { - pATI->LCDVSyncStart -= VDisplay; - if (pATI->LCDVSyncStart < 0) + if (pATI->LCDVSyncStart >= VDisplay) + pATI->LCDVSyncStart -= VDisplay; + else pATI->LCDVSyncStart = 0; pATI->LCDVBlankWidth -= VDisplay; VDisplay = pATI->LCDVSyncStart + pATI->LCDVSyncWidth; @@ -1911,12 +2275,12 @@ ATIPreInit */ ClockMask = PLL_VCLK0_XDIV << pATIHW->clock; PostMask = PLL_VCLK0_POST_DIV << (pATIHW->clock * 2); - i = GetBits(ATIGetMach64PLLReg(PLL_XCLK_CNTL), ClockMask); + i = GetBits(ATIMach64GetPLLReg(PLL_XCLK_CNTL), ClockMask); i *= MaxBits(PLL_VCLK0_POST_DIV) + 1; - i |= GetBits(ATIGetMach64PLLReg(PLL_VCLK_POST_DIV), PostMask); + i |= GetBits(ATIMach64GetPLLReg(PLL_VCLK_POST_DIV), PostMask); /* Calculate clock of mode on entry */ - Numerator = ATIGetMach64PLLReg(PLL_VCLK0_FB_DIV + pATIHW->clock) * + Numerator = ATIMach64GetPLLReg(PLL_VCLK0_FB_DIV + pATIHW->clock) * pATI->ReferenceNumerator; Denominator = pATI->ClockDescriptor.MinM * pATI->ReferenceDenominator * @@ -2060,14 +2424,17 @@ ATIPreInit else IOValue = ~((CARD32)((1 << 22) - 1)); - if ((IOValue &= pGDev->MemBase) && - (IOValue <= (MaxBits(CFG_MEM_AP_LOC) << 22))) + IOValue &= pGDev->MemBase; + if (IOValue && + (IOValue <= (CARD32)(MaxBits(CFG_MEM_AP_LOC) << 22))) pATI->LinearBase = IOValue; if (!pATI->LinearBase) + { xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "Linear aperture not configured. Specify \"MemBase\"" " override in XF86Config \"Device\" section.\n"); + } else { if (!pATI->LinearSize) @@ -2088,7 +2455,7 @@ ATIPreInit { xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "Unable to register %d MB linear aperture at" - " 0x%08X.\n", pATI->LinearSize >> 10, + " 0x%08lX.\n", pATI->LinearSize >> 10, pATI->LinearBase); pATI->LinearSize = 0; @@ -2108,7 +2475,7 @@ ATIPreInit { pATI->Block0Base = pATI->LinearBase + pATI->LinearSize - 0x00000400U; - pATI->MMIOInLinear = pATI->OptionAccel; + pATI->MMIOInLinear = TRUE; } AcceleratorVideoRAM = pATI->LinearSize >> 10; @@ -2137,7 +2504,7 @@ ATIPreInit pATI->CursorBase = pATI->LinearBase + pATI->CursorOffset; xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, - "Storing hardware cursor image at 0x%08X.\n", + "Storing hardware cursor image at 0x%08lX.\n", pATI->CursorBase); } @@ -2192,7 +2559,7 @@ ATIPreInit (AcceleratorVideoRAM + PageSize) & ~PageSize; xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, - "Using %d MB linear aperture at 0x%08X.\n", + "Using %d MB linear aperture at 0x%08lX.\n", pATI->LinearSize >> 20, pATI->LinearBase); /* Only mmap what is needed */ @@ -2282,28 +2649,17 @@ ATIPreInit } -#ifndef AVOID_CPIO - - if (!pATI->OptionAccel) - { - pATI->Block0Base = 0; /* Not needed */ - pATI->MMIOInLinear = FALSE; - } - else - -#endif - if (pATI->Block0Base) { xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, - "Using Block 0 MMIO aperture at 0x%08X.\n", pATI->Block0Base); + "Using Block 0 MMIO aperture at 0x%08lX.\n", pATI->Block0Base); /* Set Block1 MMIO address if supported */ if (pATI->Chip >= ATI_CHIP_264VT) { pATI->Block1Base = pATI->Block0Base - 0x00000400U; xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, - "Using Block 1 MMIO aperture at 0x%08X.\n", + "Using Block 1 MMIO aperture at 0x%08lX.\n", pATI->Block1Base); } } @@ -2352,23 +2708,20 @@ ATIPreInit "Linear aperture not supported in this configuration.\n"); pATI->OptionLinear = FALSE; } - else + else if (pATI->VGAAdapter != ATI_ADAPTER_NONE) { - if (pATI->VGAAdapter != ATI_ADAPTER_NONE) + /* + * Free VGA memory aperture during operating state (but it is still + * decoded). + */ + pResources = xf86SetOperatingState(resVgaMem, pATI->iEntity, + ResUnusedOpr); + if (pResources) { - /* - * Free VGA memory aperture during operating state (but it is - * still decoded). - */ - pResources = xf86SetOperatingState(resVgaMem, - pATI->iEntity, ResUnusedOpr); - if (pResources) - { - xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, - "Logic error setting operating state for VGA memory" - " aperture.\n"); - xf86FreeResList(pResources); - } + xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, + "Logic error setting operating state for VGA memory" + " aperture.\n"); + xf86FreeResList(pResources); } } } @@ -2437,10 +2790,14 @@ ATIPreInit #ifndef AVOID_CPIO else if (pATI->Adapter >= ATI_ADAPTER_V3) + { ATIReportMemory(pScreenInfo, pATI, (ATIGetExtReg(0xB7U) & 0x04U) ? "DRAM" : "VRAM"); + } else + { ATIReportMemory(pScreenInfo, pATI, "video memory"); + } #endif /* AVOID_CPIO */ @@ -2480,7 +2837,9 @@ ATIPreInit #endif if ((pATI->Chip >= ATI_CHIP_88800GXC) && (pATI->LockData.crtc_gen_cntl & CRTC_EXT_DISP_EN)) + { pATIHW->crtc = ATI_CRTC_MACH64; + } if (pATI->depth <= 4) { @@ -2510,7 +2869,9 @@ ATIPreInit pATIHW->nBank = pATI->NewHW.nBank = 1; } else if (!pATI->UseSmallApertures) + { pATIHW->SetBank = pATI->NewHW.SetBank; + } else if ((pATIHW->crtc == ATI_CRTC_VGA) && !(pATI->LockData.config_cntl & CFG_MEM_VGA_AP_EN)) { @@ -2518,9 +2879,13 @@ ATIPreInit pATIHW->nBank = 1; } else if (pATIHW->nPlane == 1) + { pATIHW->SetBank = ATIMach64SetBankPacked; + } else + { pATIHW->SetBank = ATIMach64SetBankPlanar; + } if (((ApertureSize * pATI->depth) / pATI->BankInfo.nBankDepth) >= (unsigned)(pScreenInfo->videoRam * 1024)) @@ -2558,8 +2923,10 @@ ATIPreInit pATI->OptionShadowFB = FALSE; } else + { xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "Using shadow frame buffer.\n"); + } } /* 264VT-B's and later have DSP registers */ @@ -2704,12 +3071,16 @@ ATIPreInit #ifndef AVOID_CPIO if (pATI->NewHW.crtc == ATI_CRTC_VGA) + { DefaultmaxClock = 100000; + } else #endif /* AVOID_CPIO */ + { DefaultmaxClock = 220000; + } break; default: @@ -2723,12 +3094,16 @@ ATIPreInit */ if ((pATI->Chip == ATI_CHIP_18800) || (pATI->Chip == ATI_CHIP_18800_1)) + { DefaultmaxClock = 40000; + } else if (pATI->CPIO_VGAWonder && (pATI->VideoRAM < 1024) && (pATI->depth >= 8)) + { DefaultmaxClock = (GetBits(BIOSByte(0x44U), 0x04U) * 5000) + 40000; + } else #endif /* AVOID_CPIO */ @@ -2767,12 +3142,16 @@ ATIPreInit #ifdef AVOID_CPIO if (pATI->Chip >= ATI_CHIP_264CT) + { minPitch = 8; + } #else /* AVOID_CPIO */ if ((pATI->depth >= 8) && (pATI->Chip >= ATI_CHIP_264CT)) + { minPitch = 8; + } else if (pATI->CPIO_VGAWonder && (pATI->Chip <= ATI_CHIP_18800_1) && (pATI->VideoRAM == 256) && @@ -2785,7 +3164,9 @@ ATIPreInit #endif /* AVOID_CPIO */ else + { minPitch = 16; + } pATI->pitchInc = minPitch; @@ -2896,7 +3277,8 @@ ATIPreInit pATI->pitchInc = pATI->XModifier * (64 * 8); } - if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0)) + if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0) && + (ModeType == M_T_BUILTIN)) { /* * Given LCD modes are more tightly controlled than CRT modes, allow @@ -2942,7 +3324,9 @@ ATIPreInit pMode->CrtcVTotal = pMode->VTotal; if (!pScreenInfo->monitor->Modes) + { pScreenInfo->monitor->Modes = pMode; + } else { pScreenInfo->monitor->Last->next = pMode; @@ -3072,13 +3456,19 @@ ATIPreInit else if ((pMode->HDisplay & ~pATI->AdjustMask) / pScreenInfo->xInc) xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "Mode \"%s\" cannot scroll to bottom right corner of virtual" - " resolution.\n Horizontal dimension not a multiple of %d.\n", + " resolution.\n Horizontal dimension not a multiple of %ld.\n", pMode->name, ~pATI->AdjustMask + 1); } while ((pMode = pMode->next) != pScreenInfo->modes); + /* Initialise XVideo extension support */ + ATIXVPreInit(pATI); + /* Initialise CRTC code */ ATIModePreInit(pScreenInfo, pATI, &pATI->NewHW); + /* Set up for I2C */ + ATII2CPreInit(pScreenInfo, pATI); + if (!pScreenInfo->chipset || !*pScreenInfo->chipset) pScreenInfo->chipset = (char *)ATIChipsetNames[0]; diff --git a/src/atiprint.c b/src/atiprint.c index 96444040..ac4de48b 100644 --- a/src/atiprint.c +++ b/src/atiprint.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiprint.c,v 1.25 2003/01/01 19:16:33 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiprint.c,v 1.28 2003/11/07 13:45:26 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -121,13 +121,13 @@ ATIPrintIndexedRegisters #endif /* AVOID_CPIO */ /* - * ATIPrintMach64Registers -- + * ATIMach64PrintRegisters -- * * Display a Mach64's main register bank when the server is invoked with * -verbose. */ static void -ATIPrintMach64Registers +ATIMach64PrintRegisters ( ATIPtr pATI, CARD8 *crtc, @@ -184,7 +184,7 @@ ATIPrintMach64Registers (IOValue & CRTC_EXT_DISP_EN)) *crtc = ATI_CRTC_MACH64; - xf86ErrorFVerb(4, " %08X", IOValue); + xf86ErrorFVerb(4, " %08lX", (unsigned long)IOValue); } } @@ -223,7 +223,7 @@ ATIPrintMach64Registers (IOValue & CRTC_EXT_DISP_EN)) *crtc = ATI_CRTC_MACH64; - xf86ErrorFVerb(4, " %08X", IOValue); + xf86ErrorFVerb(4, " %08lX", (unsigned long)IOValue); } } @@ -233,13 +233,13 @@ ATIPrintMach64Registers } /* - * ATIPrintMach64PLLRegisters -- + * ATIMach64PrintPLLRegisters -- * * Display an integrated Mach64's PLL registers when the server is invoked with * -verbose. */ static void -ATIPrintMach64PLLRegisters +ATIMach64PrintPLLRegisters ( ATIPtr pATI ) @@ -248,7 +248,7 @@ ATIPrintMach64PLLRegisters CARD8 PLLReg[MaxBits(PLL_ADDR) + 1]; for (Limit = 0; Limit < SizeOf(PLLReg); Limit++) - PLLReg[Limit] = ATIGetMach64PLLReg(Limit); + PLLReg[Limit] = ATIMach64GetPLLReg(Limit); /* Determine how many PLL registers there really are */ while ((Limit = Limit >> 1)) @@ -274,12 +274,12 @@ FoundLimit: } /* - * ATIPrintRGB514Registers -- + * ATIRGB514PrintRegisters -- * * Display IBM RGB 514 registers when the server is invoked with -verbose. */ static void -ATIPrintRGB514Registers +ATIRGB514PrintRegisters ( ATIPtr pATI ) @@ -374,11 +374,11 @@ ATIPrintRegisters { lcd_gen_ctrl = inr(LCD_GEN_CTRL); - outr(LCD_GEN_CTRL, lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN)); + outr(LCD_GEN_CTRL, lcd_gen_ctrl & ~SHADOW_RW_EN); ATIPrintIndexedRegisters(CRTX(ColourIOBase), 0, 64, "Non-shadow colour CRT controller", 0); - outr(LCD_GEN_CTRL, lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN)); + outr(LCD_GEN_CTRL, lcd_gen_ctrl | SHADOW_RW_EN); ATIPrintIndexedRegisters(CRTX(ColourIOBase), 0, 64, "Shadow colour CRT controller", 0); @@ -389,19 +389,19 @@ ATIPrintRegisters (pATI->Chip == ATI_CHIP_MOBILITY)) { lcd_index = inr(LCD_INDEX); - lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL); + lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); - ATIPutMach64LCDReg(LCD_GEN_CNTL, - lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN)); + ATIMach64PutLCDReg(LCD_GEN_CNTL, + lcd_gen_ctrl & ~(CRTC_RW_SELECT | SHADOW_RW_EN)); ATIPrintIndexedRegisters(CRTX(ColourIOBase), 0, 64, "Non-shadow colour CRT controller", 0); - ATIPutMach64LCDReg(LCD_GEN_CNTL, - lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN)); + ATIMach64PutLCDReg(LCD_GEN_CNTL, + (lcd_gen_ctrl & ~CRTC_RW_SELECT) | SHADOW_RW_EN); ATIPrintIndexedRegisters(CRTX(ColourIOBase), 0, 64, "Shadow colour CRT controller", 0); - ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); + ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); outr(LCD_INDEX, lcd_index); } else @@ -419,11 +419,11 @@ ATIPrintRegisters { lcd_gen_ctrl = inr(LCD_GEN_CTRL); - outr(LCD_GEN_CTRL, lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN)); + outr(LCD_GEN_CTRL, lcd_gen_ctrl & ~SHADOW_RW_EN); ATIPrintIndexedRegisters(CRTX(MonochromeIOBase), 0, 64, "Non-shadow monochrome CRT controller", 0); - outr(LCD_GEN_CTRL, lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN)); + outr(LCD_GEN_CTRL, lcd_gen_ctrl | SHADOW_RW_EN); ATIPrintIndexedRegisters(CRTX(MonochromeIOBase), 0, 64, "Shadow monochrome CRT controller", 0); @@ -434,19 +434,19 @@ ATIPrintRegisters (pATI->Chip == ATI_CHIP_MOBILITY)) { lcd_index = inr(LCD_INDEX); - lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL); + lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); - ATIPutMach64LCDReg(LCD_GEN_CNTL, - lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN)); + ATIMach64PutLCDReg(LCD_GEN_CNTL, + lcd_gen_ctrl & ~(CRTC_RW_SELECT | SHADOW_RW_EN)); ATIPrintIndexedRegisters(CRTX(MonochromeIOBase), 0, 64, "Non-shadow monochrome CRT controller", 0); - ATIPutMach64LCDReg(LCD_GEN_CNTL, - lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN)); + ATIMach64PutLCDReg(LCD_GEN_CNTL, + (lcd_gen_ctrl & ~CRTC_RW_SELECT) | SHADOW_RW_EN); ATIPrintIndexedRegisters(CRTX(MonochromeIOBase), 0, 64, "Shadow monochrome CRT controller", 0); - ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); + ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); outr(LCD_INDEX, lcd_index); } else @@ -499,47 +499,47 @@ ATIPrintRegisters { lcd_gen_ctrl = inr(LCD_GEN_CTRL); - outr(LCD_GEN_CTRL, lcd_gen_ctrl & ~(SHADOW_EN | SHADOW_RW_EN)); - ATIPrintMach64Registers(pATI, &crtc, "non-shadow"); + outr(LCD_GEN_CTRL, lcd_gen_ctrl & ~SHADOW_RW_EN); + ATIMach64PrintRegisters(pATI, &crtc, "non-shadow"); - outr(LCD_GEN_CTRL, lcd_gen_ctrl | (SHADOW_EN | SHADOW_RW_EN)); - ATIPrintMach64Registers(pATI, &crtc, "shadow"); + outr(LCD_GEN_CTRL, lcd_gen_ctrl | SHADOW_RW_EN); + ATIMach64PrintRegisters(pATI, &crtc, "shadow"); outr(LCD_GEN_CTRL, lcd_gen_ctrl); - ATIPrintMach64PLLRegisters(pATI); + ATIMach64PrintPLLRegisters(pATI); } else if ((pATI->Chip == ATI_CHIP_264LTPRO) || (pATI->Chip == ATI_CHIP_264XL) || (pATI->Chip == ATI_CHIP_MOBILITY)) { lcd_index = inr(LCD_INDEX); - lcd_gen_ctrl = ATIGetMach64LCDReg(LCD_GEN_CNTL); + lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL); - ATIPutMach64LCDReg(LCD_GEN_CNTL, - lcd_gen_ctrl & ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN)); - ATIPrintMach64Registers(pATI, &crtc, "non-shadow"); + ATIMach64PutLCDReg(LCD_GEN_CNTL, + lcd_gen_ctrl & ~(CRTC_RW_SELECT | SHADOW_RW_EN)); + ATIMach64PrintRegisters(pATI, &crtc, "non-shadow"); - ATIPutMach64LCDReg(LCD_GEN_CNTL, - (lcd_gen_ctrl & ~CRTC_RW_SELECT) | (SHADOW_EN | SHADOW_RW_EN)); - ATIPrintMach64Registers(pATI, &crtc, "shadow"); + ATIMach64PutLCDReg(LCD_GEN_CNTL, + (lcd_gen_ctrl & ~CRTC_RW_SELECT) | SHADOW_RW_EN); + ATIMach64PrintRegisters(pATI, &crtc, "shadow"); if (pATI->Chip != ATI_CHIP_264XL) { - ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl | CRTC_RW_SELECT); - ATIPrintMach64Registers(pATI, &crtc, "secondary"); + ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl | CRTC_RW_SELECT); + ATIMach64PrintRegisters(pATI, &crtc, "secondary"); } - ATIPutMach64LCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); + ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); - ATIPrintMach64PLLRegisters(pATI); + ATIMach64PrintPLLRegisters(pATI); xf86ErrorFVerb(4, "\n LCD register values:"); for (Index = 0; Index < 64; Index++) { if (!(Index & 3)) xf86ErrorFVerb(4, "\n 0x%02X: ", Index); - xf86ErrorFVerb(4, " %08X", ATIGetMach64LCDReg(Index)); + xf86ErrorFVerb(4, " %08X", ATIMach64GetLCDReg(Index)); } outr(LCD_INDEX, lcd_index); @@ -551,7 +551,7 @@ ATIPrintRegisters { if (!(Index & 3)) xf86ErrorFVerb(4, "\n 0x%02X: ", Index); - xf86ErrorFVerb(4, " %08X", ATIGetMach64TVReg(Index)); + xf86ErrorFVerb(4, " %08X", ATIMach64GetTVReg(Index)); } outr(TV_OUT_INDEX, tv_out_index); @@ -570,20 +570,20 @@ ATIPrintRegisters #ifdef AVOID_CPIO - ATIPrintMach64Registers(pATI, &crtc, "MMIO"); + ATIMach64PrintRegisters(pATI, &crtc, "MMIO"); #else /* AVOID_CPIO */ - ATIPrintMach64Registers(pATI, &crtc, + ATIMach64PrintRegisters(pATI, &crtc, (pATI->CPIODecoding == SPARSE_IO) ? "sparse" : "block"); #endif /* AVOID_CPIO */ if (pATI->Chip >= ATI_CHIP_264CT) - ATIPrintMach64PLLRegisters(pATI); + ATIMach64PrintPLLRegisters(pATI); if (pATI->DAC == ATI_DAC_IBMRGB514) - ATIPrintRGB514Registers(pATI); + ATIRGB514PrintRegisters(pATI); } #ifdef AVOID_CPIO @@ -685,7 +685,8 @@ ATIPrintRegisters { if (!(Index & 15)) xf86ErrorFVerb(4, "\n 0x%02X: ", Index); - xf86ErrorFVerb(4, " 0x%08X", pciReadLong(pPCI->tag, Index)); + xf86ErrorFVerb(4, " 0x%08lX", + (unsigned long)pciReadLong(pPCI->tag, Index)); } } @@ -695,12 +696,14 @@ ATIPrintRegisters if (pATI->pBank) xf86ErrorFVerb(4, "\n Banked aperture at 0x%0lX.", - pATI->pBank); + (unsigned long)pATI->pBank); else xf86ErrorFVerb(4, "\n No banked aperture."); if (pATI->pMemory == pATI->pBank) + { xf86ErrorFVerb(4, "\n No linear aperture.\n"); + } else #else /* AVOID_CPIO */ @@ -710,25 +713,27 @@ ATIPrintRegisters #endif /* AVOID_CPIO */ { - xf86ErrorFVerb(4, "\n Linear aperture at 0x%0lX.\n", pATI->pMemory); + xf86ErrorFVerb(4, "\n Linear aperture at %p.\n", pATI->pMemory); } if (pATI->pBlock[0]) { - xf86ErrorFVerb(4, " Block 0 aperture at 0x%0lX.\n", pATI->pBlock[0]); + xf86ErrorFVerb(4, " Block 0 aperture at %p.\n", pATI->pBlock[0]); if (inr(CONFIG_CHIP_ID) == pATI->config_chip_id) xf86ErrorFVerb(4, " MMIO registers are correctly mapped.\n"); else xf86ErrorFVerb(4, " MMIO mapping is in error!\n"); if (pATI->pBlock[1]) - xf86ErrorFVerb(4, " Block 1 aperture at 0x%0lX.\n", + xf86ErrorFVerb(4, " Block 1 aperture at %p.\n", pATI->pBlock[1]); } else + { xf86ErrorFVerb(4, " No MMIO aperture.\n"); + } if (pATI->pCursorImage) - xf86ErrorFVerb(4, " Hardware cursor image aperture at 0x%0lX.\n", + xf86ErrorFVerb(4, " Hardware cursor image aperture at %p.\n", pATI->pCursorImage); else xf86ErrorFVerb(4, " No hardware cursor image aperture.\n"); @@ -776,7 +781,9 @@ ATIPrintMode else hSync = mClock / pMode->HTotal; if (pMode->VRefresh > 0.0) + { vRefresh = pMode->VRefresh; + } else { vRefresh = (hSync * 1000.0) / pMode->VTotal; @@ -814,7 +821,8 @@ ATIPrintMode if (flags & pSymbol->token) { xf86ErrorFVerb(4, " %s", pSymbol->name); - if (!(flags &= ~pSymbol->token)) + flags &= ~pSymbol->token; + if (!flags) break; } } diff --git a/src/atiprobe.c b/src/atiprobe.c index 05d2f340..e910eedb 100644 --- a/src/atiprobe.c +++ b/src/atiprobe.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiprobe.c,v 1.54 2003/01/01 19:16:33 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiprobe.c,v 1.61 2003/11/07 13:45:26 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -206,7 +206,7 @@ ATICheckSparseIOBases /* User might wish to override this decision */ xf86Msg(X_WARNING, - ATI_NAME ": Sparse I/O base 0x%04X not probed.\n", IOBase); + ATI_NAME ": Sparse I/O base 0x%04lX not probed.\n", IOBase); return Allowed; } } @@ -279,7 +279,9 @@ ATIVGAProbe pVGA->Adapter = ATI_ADAPTER_VGA; } else + { pVGA->VGAAdapter = ATI_ADAPTER_NONE; + } return pVGA; } @@ -308,7 +310,7 @@ ATIVGAWonderProbe case 0: xf86Msg(X_WARNING, ATI_NAME ": Expected VGA Wonder capability could not be" - " detected at I/O port 0x%04X because it would conflict with" + " detected at I/O port 0x%04lX because it would conflict with" " a non-video PCI/AGP device.\n", pATI->CPIO_VGAWonder); pATI->CPIO_VGAWonder = 0; break; @@ -316,7 +318,7 @@ ATIVGAWonderProbe case Detected8514A: xf86Msg(X_WARNING, ATI_NAME ": Expected VGA Wonder capability could not be" - " detected at I/O port 0x%04X because it would conflict with" + " detected at I/O port 0x%04lX because it would conflict with" " a %s %s.\n", pATI->CPIO_VGAWonder, ATIBusNames[p8514->BusType], ATIAdapterNames[p8514->Adapter]); pATI->CPIO_VGAWonder = 0; @@ -325,7 +327,7 @@ ATIVGAWonderProbe case DetectedMach64: xf86Msg(X_WARNING, ATI_NAME ": Expected VGA Wonder capability could not be" - " detected at I/O port 0x%04X because it would conflict with" + " detected at I/O port 0x%04lX because it would conflict with" " a Mach64.\n", pATI->CPIO_VGAWonder); pATI->CPIO_VGAWonder = 0; break; @@ -365,14 +367,14 @@ ATIVGAWonderProbe (IOValue6 == 0)) { xf86MsgVerb(X_INFO, 3, - ATI_NAME ": VGA Wonder at I/O port 0x%04X detected.\n", + ATI_NAME ": VGA Wonder at I/O port 0x%04lX detected.\n", pATI->CPIO_VGAWonder); } else { xf86Msg(X_WARNING, ATI_NAME ": Expected VGA Wonder capability at I/O port" - " 0x%04X was not detected.\n", pATI->CPIO_VGAWonder); + " 0x%04lX was not detected.\n", pATI->CPIO_VGAWonder); pATI->CPIO_VGAWonder = 0; } break; @@ -525,13 +527,13 @@ ATI8514Probe #endif /* AVOID_CPIO */ /* - * ATIDetectMach64 -- + * ATIMach64Detect -- * * This function determines if a Mach64 is detectable at a particular base * address. */ static Bool -ATIDetectMach64 +ATIMach64Detect ( ATIPtr pATI, const CARD16 ChipType, @@ -662,11 +664,11 @@ ATIMach64Probe { pATI->Block0Base += 0x007FFC00U; if ((pVideo->size[0] >= 23) && - ATIDetectMach64(pATI, ChipType, Chip)) + ATIMach64Detect(pATI, ChipType, Chip)) return pATI; pATI->Block0Base -= 0x00400000U; - if (ATIDetectMach64(pATI, ChipType, Chip)) + if (ATIMach64Detect(pATI, ChipType, Chip)) return pATI; } } @@ -679,7 +681,7 @@ ATIMach64Probe pATI->Block0Base = 0x000BFC00U; LastProbe: - if (ATIDetectMach64(pATI, ChipType, Chip)) + if (ATIMach64Detect(pATI, ChipType, Chip)) return pATI; xfree(pATI); @@ -725,7 +727,7 @@ ATIMach64Probe pATI->CPIODecoding = IODecoding; pATI->PCIInfo = pVideo; - if (!ATIDetectMach64(pATI, ChipType, Chip)) + if (!ATIMach64Detect(pATI, ChipType, Chip)) { xfree(pATI); return NULL; @@ -736,7 +738,9 @@ ATIMach64Probe * controllers. For the GX/CX, it's a board strap. */ if (pATI->Chip >= ATI_CHIP_264CT) + { pATI->VGAAdapter = ATI_ADAPTER_MACH64; + } else { IOValue = inr(CONFIG_STATUS64_0); @@ -1155,11 +1159,10 @@ ATIProbe { for (i = 0; (pVideo = xf86PciVideoInfo[i++]); ) { - if (pVideo->vendor == PCI_VENDOR_ATI) + if ((pVideo->vendor == PCI_VENDOR_ATI) || + !(pPCI = pVideo->thisCard)) continue; - pPCI = pVideo->thisCard; - ATIScanPCIBases(&PCIPorts, &nPCIPort, &pPCI->pci_base0, pVideo->size, (pciReadLong(pPCI->tag, PCI_CMD_STAT_REG) & @@ -1297,7 +1300,7 @@ ATIProbe 4, fChipsets[ATI_CHIPSET_MACH64]) != DoProbe) { xf86MsgVerb(X_INFO, 2, - ATI_NAME ": Unshared Mach64 at PIO base 0x%04X not" + ATI_NAME ": Unshared Mach64 at PIO base 0x%04lX not" " probed.\n", Mach64SparseIOBases[i]); continue; @@ -1307,7 +1310,7 @@ ATIProbe if (!pATI) { xf86MsgVerb(X_INFO, 4, - ATI_NAME ": Unshared Mach64 at PIO base 0x%04X not" + ATI_NAME ": Unshared Mach64 at PIO base 0x%04lX not" " detected.\n", Mach64SparseIOBases[i]); continue; } @@ -1343,10 +1346,10 @@ ATIProbe { if ((pVideo->vendor != PCI_VENDOR_ATI) || (pVideo->chipType == PCI_CHIP_MACH32) || - pVideo->size[1]) + pVideo->size[1] || + !(pPCI = pVideo->thisCard)) continue; - pPCI = pVideo->thisCard; PciReg = pciReadLong(pPCI->tag, PCI_REG_USERCONFIG); /* Possibly fix block I/O indicator */ @@ -1367,7 +1370,7 @@ ATIProbe "Unshared PCI sparse I/O Mach64 in slot %d:%d:%d", pVideo->bus, pVideo->device, pVideo->func); xf86MsgVerb(X_INFO, 3, - ATI_NAME ": %s detected through Block 0 at 0x%08X.\n", + ATI_NAME ": %s detected through Block 0 at 0x%08lX.\n", Identifier, pATI->Block0Base); AddAdapter(pATI); pATI->PCIInfo = pVideo; @@ -1384,11 +1387,10 @@ ATIProbe /* For now, ignore Rage128's and Radeon's */ Chip = ATIChipID(pVideo->chipType, pVideo->chipRev); - if (Chip > ATI_CHIP_Mach64) + if ((Chip > ATI_CHIP_Mach64) || + !(pPCI = pVideo->thisCard)) continue; - pPCI = pVideo->thisCard; - /* * Possibly fix block I/O indicator in PCI configuration space. */ @@ -1521,10 +1523,12 @@ ATIProbe xf86SetPciVideo(pVideo, MEM_IO); if (!(pATI = ATI8514Probe(pVideo))) + { xf86Msg(X_WARNING, ATI_NAME ": PCI Mach32 in slot %d:%d:%d could" " not be detected!\n", pVideo->bus, pVideo->device, pVideo->func); + } else { sprintf(Identifier, @@ -1565,11 +1569,13 @@ ATIProbe PciReg = pciReadLong(pPCI->tag, PCI_REG_USERCONFIG); j = PciReg & 0x03U; if (j == 0x03U) + { xf86Msg(X_WARNING, ATI_NAME ": PCI Mach64 in slot %d:%d:%d cannot be" " enabled\n because it has neither a block, nor a" " sparse, I/O base.\n", pVideo->bus, pVideo->device, pVideo->func); + } else switch(ATICheckSparseIOBases(pVideo, ProbeFlags, Mach64SparseIOBases[j], 4, TRUE)) { @@ -1598,7 +1604,7 @@ ATIProbe ATI_NAME ": PCI Mach64 in slot %d:%d:%d will" " not be enabled\n because it conflicts with" " another %s Mach64 at sparse I/O base" - " 0x%04X.\n", + " 0x%04lX.\n", pVideo->bus, pVideo->device, pVideo->func, ATIBusNames[pATI->BusType], Mach64SparseIOBases[j]); @@ -1621,17 +1627,19 @@ ATIProbe pATI = ATIMach64Probe(pVideo, Mach64SparseIOBases[j], SPARSE_IO, Chip); if (!pATI) + { xf86Msg(X_WARNING, ATI_NAME ": PCI Mach64 in slot %d:%d:%d could" " not be detected!\n", pVideo->bus, pVideo->device, pVideo->func); + } else { sprintf(Identifier, "Shared PCI Mach64 in slot %d:%d:%d", pVideo->bus, pVideo->device, pVideo->func); xf86MsgVerb(X_INFO, 3, - ATI_NAME ": %s with sparse PIO base 0x%04X" + ATI_NAME ": %s with sparse PIO base 0x%04lX" " detected.\n", Identifier, Mach64SparseIOBases[j]); AddAdapter(pATI); @@ -1681,7 +1689,7 @@ ATIProbe sprintf(Identifier, "Shared PCI Mach64 in slot %d:%d:%d", pVideo->bus, pVideo->device, pVideo->func); xf86MsgVerb(X_INFO, 3, - ATI_NAME ": %s with Block 0 base 0x%08X detected.\n", + ATI_NAME ": %s with Block 0 base 0x%08lX detected.\n", Identifier, pATI->Block0Base); AddAdapter(pATI); pATI->SharedAccelerator = TRUE; @@ -1731,12 +1739,21 @@ ATIProbe case ATI_CHIP_RADEON: case ATI_CHIP_RADEONVE: case ATI_CHIP_RADEONMOBILITY6: + case ATI_CHIP_RS100: + case ATI_CHIP_RS200: + case ATI_CHIP_RS250: case ATI_CHIP_RADEONMOBILITY7: case ATI_CHIP_R200: case ATI_CHIP_RV200: case ATI_CHIP_RV250: case ATI_CHIP_RADEONMOBILITY9: + case ATI_CHIP_RS300: + case ATI_CHIP_RV280: + case ATI_CHIP_RADEONMOBILITY9PLUS: case ATI_CHIP_R300: + case ATI_CHIP_RV350: + case ATI_CHIP_R350: + case ATI_CHIP_R360: DoRadeon = TRUE; continue; diff --git a/src/atiregs.h b/src/atiregs.h index 6ef71601..943dbadd 100644 --- a/src/atiregs.h +++ b/src/atiregs.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiregs.h,v 1.23 2003/01/10 17:43:40 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiregs.h,v 1.24 2003/04/23 21:51:30 tsi Exp $ */ /* * Copyright 1994 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -2308,7 +2308,7 @@ #define FORCE_DAC_DATA_X 0xff000000ul #define LCD_TMDS_CNTL 0x15u /* XC/XL */ #define LCD_SCRATCH_PAD_4M 0x15u /* Mobility */ -#define LCD_TMDS_SYNC_CHAR_SETA 0x16u /* XC/XL */ +#define LCD_TMDS_SYNC_CHAR_SETA 0x16u /* XC/XL */ #define LCD_SCRATCH_PAD_5M 0x16u /* Mobility */ #define LCD_TMDS_SYNC_CHAR_SETB 0x17u /* XC/XL */ #define LCD_SCRATCH_PAD_6M 0x17u /* Mobility */ @@ -2715,4 +2715,14 @@ #define MIX_AVERAGE_SAT 0x001fu #define MIX_FN_PAINT MIX_SRC +/* Video/Graphics mix functions for overlay */ +#define OVERLAY_MIX_FALSE 0x00u +#define OVERLAY_MIX_TRUE 0x01u +/* ? 0x02u */ +/* ? 0x03u */ +#define OVERLAY_MIX_NOT_EQUAL 0x04u +#define OVERLAY_MIX_EQUAL 0x05u +/* ? 0x06u */ +/* ? 0x07u */ + #endif /* ___ATIREGS_H___ */ diff --git a/src/atiscreen.c b/src/atiscreen.c index 59b04e09..daf5a8ce 100644 --- a/src/atiscreen.c +++ b/src/atiscreen.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiscreen.c,v 1.29 2003/01/01 19:16:34 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiscreen.c,v 1.30 2003/04/23 21:51:30 tsi Exp $ */ /* * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -63,10 +63,9 @@ ATIRefreshArea while (nBox-- > 0) { - w = (pBox->x2 - pBox->x1) * pATI->FBBytesPerPixel; + w = (pBox->x2 - pBox->x1) * pATI->AdjustDepth; h = pBox->y2 - pBox->y1; - offset = - (pBox->y1 * pATI->FBPitch) + (pBox->x1 * pATI->FBBytesPerPixel); + offset = (pBox->y1 * pATI->FBPitch) + (pBox->x1 * pATI->AdjustDepth); pSrc = (char *)pATI->pShadow + offset; pDst = (char *)pATI->pMemory + offset; @@ -120,12 +119,13 @@ ATIScreenInit return FALSE; pFB = pATI->pMemory; + pATI->FBPitch = PixmapBytePad(pATI->displayWidth, pATI->depth); if (pATI->OptionShadowFB) { - pATI->FBBytesPerPixel = pATI->bitsPerPixel >> 3; - pATI->FBPitch = PixmapBytePad(pATI->displayWidth, pATI->depth); if ((pATI->pShadow = xalloc(pATI->FBPitch * pScreenInfo->virtualY))) + { pFB = pATI->pShadow; + } else { xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, @@ -216,8 +216,10 @@ ATIScreenInit else if (!fbPictureInit(pScreen, NULL, 0) && (serverGeneration == 1)) + { xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "RENDER extension initialisation failed.\n"); + } } xf86SetBlackWhitePixels(pScreen); @@ -239,7 +241,7 @@ ATIScreenInit #ifndef AVOID_DGA /* Initialise DGA support */ - (void)ATIDGAInit(pScreenInfo, pScreen, pATI); + (void)ATIDGAInit(pScreen, pScreenInfo, pATI); #endif /* AVOID_DGA */ @@ -311,6 +313,8 @@ ATICloseScreen ATIPtr pATI = ATIPTR(pScreenInfo); Bool Closed = TRUE; + ATICloseXVideo(pScreen, pScreenInfo, pATI); + if (pATI->pXAAInfo) { XAADestroyInfoRec(pATI->pXAAInfo); diff --git a/src/atistruct.h b/src/atistruct.h index 641fe062..b77d7cdc 100644 --- a/src/atistruct.h +++ b/src/atistruct.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atistruct.h,v 1.37 2003/01/10 20:57:58 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atistruct.h,v 1.40 2003/11/13 21:21:34 tsi Exp $ */ /* * Copyright 1999 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -119,7 +119,16 @@ typedef struct _ATIHWRec CARD32 context_mask, context_load_cntl; /* Mach64 MMIO Block 1 registers */ - CARD32 gui_cntl; + CARD32 overlay_y_x_start, overlay_y_x_end, overlay_graphics_key_clr, + overlay_graphics_key_msk, overlay_key_cntl, overlay_scale_inc, + overlay_scale_cntl, scaler_height_width, scaler_test, + scaler_buf0_offset, scaler_buf1_offset, scaler_buf_pitch, + video_format, overlay_exclusive_horz, overlay_exclusive_vert, + buf0_offset, buf0_pitch, buf1_offset, buf1_pitch, + scaler_colour_cntl, scaler_h_coeff0, scaler_h_coeff1, + scaler_h_coeff2, scaler_h_coeff3, scaler_h_coeff4, gui_cntl, + scaler_buf0_offset_u, scaler_buf0_offset_v, scaler_buf1_offset_u, + scaler_buf1_offset_v; /* Clock map pointers */ const CARD8 *ClockMap, *ClockUnmap; @@ -233,13 +242,15 @@ typedef struct _ATIRec * BIOS-related definitions. */ unsigned long BIOSBase; + CARD8 I2CType, Tuner, Decoder, Audio; /* * Definitions related to video memory apertures. */ pointer pMemory, pShadow; + pointer pMemoryLE; /* Always little-endian */ unsigned long LinearBase; - int LinearSize, FBPitch, FBBytesPerPixel; + int LinearSize, FBPitch; #ifndef AVOID_CPIO @@ -307,8 +318,8 @@ typedef struct _ATIRec * LCD panel data. */ int LCDPanelID, LCDClock, LCDHorizontal, LCDVertical; - int LCDHSyncStart, LCDHSyncWidth, LCDHBlankWidth; - int LCDVSyncStart, LCDVSyncWidth, LCDVBlankWidth; + unsigned LCDHSyncStart, LCDHSyncWidth, LCDHBlankWidth; + unsigned LCDVSyncStart, LCDVSyncWidth, LCDVBlankWidth; int LCDVBlendFIFOSize; /* @@ -344,6 +355,15 @@ typedef struct _ATIRec #endif /* AVOID_DGA */ /* + * XVideo-related data. + */ + DevUnion XVPortPrivate[1]; + FBLinearPtr pXVBuffer; + RegionRec VideoClip; + int SurfacePitch, SurfaceOffset; + CARD8 AutoPaint, DoubleBuffer, CurrentBuffer, ActiveSurface; + + /* * Data saved by ATIUnlock() and restored by ATILock(). */ struct @@ -399,10 +419,11 @@ typedef struct _ATIRec #endif /* AVOID_CPIO */ CARD8 OptionMMIOCache; /* Cache MMIO writes */ - CARD8 OptionPanelDisplay; /* Prefer CRT over digital panel */ + CARD8 OptionTestMMIOCache; /* Test MMIO cache integrity */ + CARD8 OptionPanelDisplay; /* Prefer digital panel over CRT */ CARD8 OptionProbeClocks; /* Force probe for fixed clocks */ CARD8 OptionShadowFB; /* Use shadow frame buffer */ - CARD8 OptionSync; /* Temporary */ + CARD8 OptionLCDSync; /* Temporary */ /* * State flags. diff --git a/src/atituner.c b/src/atituner.c new file mode 100644 index 00000000..55dc7c2e --- /dev/null +++ b/src/atituner.c @@ -0,0 +1,174 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atituner.c,v 1.1 2003/07/24 22:08:28 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#include "atituner.h" + +/* Temporary interface glitch */ +#if 0 +# include "fi12x6.h" +#else + typedef enum { + FI12x6_TYPE_UNKNOWN = -1, + FI12x6_TYPE_FI1236 = 0, + FI12x6_TYPE_FI1216, + FI12x6_TYPE_FI1216MF, + FI12x6_TYPE_TEMIC_FN5AL, + FI12x6_TYPE_MT2032, + FI12x6_TYPE_MAX /* Must be last */ + } FI12x6TunerType; +#endif + +/* + * TV tuner definitions. + */ +const SymTabRec ATITuners[] = +{ + { + FI12x6_TYPE_UNKNOWN, + "No tuner" + }, + { + FI12x6_TYPE_FI1236, + "Philips FI1236 MK1 NTSC M/N North America" + }, + { + FI12x6_TYPE_FI1236, + "Philips FI1236 MK2 NTSC M/N Japan" + }, + { + FI12x6_TYPE_FI1216, + "Philips FI1216 MK2 PAL B/G" + }, + { + FI12x6_TYPE_UNKNOWN, + "Philips FI1246 MK2 PAL I" + }, + { + FI12x6_TYPE_FI1216MF, + "Philips FI1216 MF MK2 PAL B/G, SECAM L/L" + }, + { + FI12x6_TYPE_FI1236, + "Philips FI1236 MK2 NTSC M/N North America" + }, + { + FI12x6_TYPE_UNKNOWN, + "Philips FI1256 MK2 SECAM D/K" + }, + { + FI12x6_TYPE_FI1236, + "Philips FM1236 MK2 NTSC M/N North America" + }, + { + FI12x6_TYPE_FI1216, + "Philips FI1216 MK2 PAL B/G - External Tuner POD" + }, + { + FI12x6_TYPE_UNKNOWN, + "Philips FI1246 MK2 PAL I - External Tuner POD" + }, + { + FI12x6_TYPE_FI1216MF, + "Philips FI1216 MF MK2 PAL B/G, SECAM L/L - External Tuner POD" + }, + { + FI12x6_TYPE_FI1236, + "Philips FI1236 MK2 NTSC M/N North America - External Tuner POD" + }, + { + FI12x6_TYPE_TEMIC_FN5AL, + "Temic FN5AL.RF3X7595 PAL I/B/G/DK & SECAM DK" + }, + { + FI12x6_TYPE_FI1216MF, + "Philips FQ1216 ME/P" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (15)" + }, + { + FI12x6_TYPE_UNKNOWN, + "Alps TSBH5 NTSC M/N North America" + }, + { + FI12x6_TYPE_UNKNOWN, + "Alps TSC?? NTSC M/N North America" + }, + { + FI12x6_TYPE_UNKNOWN, + "Alps TSCH5 NTSC M/N North America with FM" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (19)" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (20)" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (21)" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (22)" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (23)" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (24)" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (25)" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (26)" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (27)" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (28)" + }, + { + FI12x6_TYPE_MT2032, + "Microtune MT2032" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (30)" + }, + { + FI12x6_TYPE_UNKNOWN, + "Unknown type (31)" + } +}; diff --git a/src/atituner.h b/src/atituner.h new file mode 100644 index 00000000..0c3c67f4 --- /dev/null +++ b/src/atituner.h @@ -0,0 +1,70 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atituner.h,v 1.1 2003/07/24 22:08:28 tsi Exp $ */ +/* + * Copyright 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + */ + +#ifndef ___ATITUNER_H___ +#define ___ATITUNER_H___ 1 + +#include "xf86str.h" + +/* + * TV Tuner definitions. Most of these are from Philips. + */ +typedef enum +{ + ATI_TUNER_NONE, + ATI_TUNER_FI1236MK1NA, + ATI_TUNER_FI1236MK2J, + ATI_TUNER_FI1216MK2BG, + ATI_TUNER_FI1246MK2I, + ATI_TUNER_FI1216MFMK2, + ATI_TUNER_FI1236MK2NA, + ATI_TUNER_FI1256MK2DK, + ATI_TUNER_FM1236MK2NA, + ATI_TUNER_FI1216MK2BGEXT, + ATI_TUNER_FI1246MK2IEXT, + ATI_TUNER_FI1216MFMK2EXT, + ATI_TUNER_FI1236MK2NAEXT, + ATI_TUNER_TEMIC_FN5AL, + ATI_TUNER_FQ1216MEP, + ATI_TUNER_15, + ATI_TUNER_ALPS_TSBH5, + ATI_TUNER_ALPS_TSCXX, + ATI_TUNER_ALPS_TSCH5, + ATI_TUNER_19, + ATI_TUNER_20, + ATI_TUNER_21, + ATI_TUNER_22, + ATI_TUNER_23, + ATI_TUNER_24, + ATI_TUNER_25, + ATI_TUNER_26, + ATI_TUNER_27, + ATI_TUNER_28, + ATI_TUNER_MT2032, + ATI_TUNER_30, + ATI_TUNER_31 +} ATITunerType; + +extern const SymTabRec ATITuners[]; + +#endif /* ___ATITUNER_H___ */ diff --git a/src/ativalid.c b/src/ativalid.c index adc87342..42ab3edf 100644 --- a/src/ativalid.c +++ b/src/ativalid.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativalid.c,v 1.15 2003/01/01 19:16:34 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativalid.c,v 1.17 2003/10/30 17:36:58 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -34,7 +34,7 @@ * * This checks for hardware-related limits on mode timings. */ -int +ModeStatus ATIValidMode ( int iScreen, @@ -102,7 +102,7 @@ ATIValidMode (pMode->CrtcVDisplay > pATI->LCDVertical)) return MODE_PANEL; - if (!pATI->OptionSync || (pMode->type & M_T_BUILTIN)) + if (!pATI->OptionLCDSync || (pMode->type & M_T_BUILTIN)) { if ((pMode->HDisplay > pATI->LCDHorizontal) || (pMode->VDisplay > pATI->LCDVertical)) diff --git a/src/ativalid.h b/src/ativalid.h index 055ed509..65e744ec 100644 --- a/src/ativalid.h +++ b/src/ativalid.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativalid.h,v 1.8 2003/01/01 19:16:34 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativalid.h,v 1.9 2003/10/30 17:36:58 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -28,6 +28,7 @@ #include "xf86str.h" -extern int ATIValidMode FunctionPrototype((int, DisplayModePtr, Bool, int)); +extern ModeStatus ATIValidMode FunctionPrototype((int, DisplayModePtr, Bool, + int)); #endif /* ___ATIVALID_H___ */ diff --git a/src/ativersion.h b/src/ativersion.h index 082cbb14..b088bc71 100644 --- a/src/ativersion.h +++ b/src/ativersion.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativersion.h,v 1.58 2003/01/10 20:57:58 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativersion.h,v 1.63 2003/11/13 21:21:34 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -38,8 +38,8 @@ #define ATI_DRIVER_NAME "ati" #define ATI_VERSION_MAJOR 6 -#define ATI_VERSION_MINOR 4 -#define ATI_VERSION_PATCH 18 +#define ATI_VERSION_MINOR 5 +#define ATI_VERSION_PATCH 4 #ifndef ATI_VERSION_EXTRA #define ATI_VERSION_EXTRA "" diff --git a/src/ativga.c b/src/ativga.c index 9a732a37..62edf02f 100644 --- a/src/ativga.c +++ b/src/ativga.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativga.c,v 1.19 2003/01/01 19:16:34 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/ativga.c,v 1.20 2003/04/23 21:51:31 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -318,7 +318,9 @@ ATIVGACalculate pMode->CrtcVTotal >>= 1; } else + { pATIHW->crt[23] &= ~0x04U; + } pMode->CrtcVDisplay--; if (pATI->Chip == ATI_CHIP_18800) diff --git a/src/atividmem.c b/src/atividmem.c index 32ea23fc..1b866598 100644 --- a/src/atividmem.c +++ b/src/atividmem.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atividmem.c,v 1.14 2003/01/01 19:16:34 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atividmem.c,v 1.15 2003/04/23 21:51:31 tsi Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -115,9 +115,17 @@ ATIUnmapLinear { xf86UnMapVidMem(iScreen, pATI->pMemory, pATI->LinearSize); + +#if X_BYTE_ORDER != X_LITTLE_ENDIAN + + if (pATI->pMemoryLE) + xf86UnMapVidMem(iScreen, pATI->pMemoryLE, pATI->LinearSize); + +#endif /* X_BYTE_ORDER */ + } - pATI->pMemory = NULL; + pATI->pMemory = pATI->pMemoryLE = NULL; } /* @@ -252,6 +260,34 @@ ATIMapApertures ((pATI->CursorOffset + 0x00000400UL) <= (CARD32)pATI->LinearSize)) pATI->pCursorImage = (char *)pATI->pMemory + pATI->CursorOffset; + pATI->pMemoryLE = pATI->pMemory; + +#else /* if X_BYTE_ORDER != X_LITTLE_ENDIAN */ + + /* + * Map the little-endian aperture (used for video, etc.). Note that + * caching of this area is _not_ wanted. + */ + if (pVideo) + { + pATI->pMemoryLE = xf86MapPciMem(iScreen, VIDMEM_MMIO, Tag, + pATI->LinearBase - 0x00800000U, pATI->LinearSize); + + if (!pATI->pMemoryLE) + { + ATIUnmapLinear(iScreen, pATI); + +#ifndef AVOID_CPIO + + ATIUnmapVGA(iScreen, pATI); + +#endif /* AVOID_CPIO */ + + pATI->Mapped = FALSE; + return FALSE; + } + } + #endif /* X_BYTE_ORDER */ } diff --git a/src/atixv.c b/src/atixv.c index b15aa53f..417373a1 100644 --- a/src/atixv.c +++ b/src/atixv.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atixv.c,v 1.3 2003/01/01 19:16:35 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atixv.c,v 1.5 2003/04/25 04:09:54 tsi Exp $ */ /* * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -21,10 +21,93 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include "atiadapter.h" +#include "atimach64xv.h" #include "atistruct.h" #include "atixv.h" -#include "xf86xv.h" +/* + * ATIXVFreeAdaptorInfo -- + * + * Free XVideo adaptor information. + */ +static void +ATIXVFreeAdaptorInfo +( + XF86VideoAdaptorPtr *ppAdaptor, + int nAdaptor +) +{ + if (!ppAdaptor) + return; + + while (nAdaptor > 0) + xfree(ppAdaptor[--nAdaptor]); + + xfree(ppAdaptor); +} + +/* + * ATIXVInitializeAdaptor -- + * + * This is called by the server's XVideo support layer to initialise an XVideo + * adapter. + */ +static int +ATIXVInitializeAdaptor +( + ScrnInfoPtr pScreenInfo, + XF86VideoAdaptorPtr **pppAdaptor +) +{ + ScreenPtr pScreen = screenInfo.screens[pScreenInfo->scrnIndex]; + ATIPtr pATI = ATIPTR(pScreenInfo); + XF86VideoAdaptorPtr *ppAdaptor = NULL; + int nAdaptor; + + switch (pATI->Adapter) + { + case ATI_ADAPTER_MACH64: + nAdaptor = ATIMach64XVInitialiseAdaptor(pScreen, pScreenInfo, pATI, + &ppAdaptor); + break; + + default: + nAdaptor = 0; + break; + } + + if (pppAdaptor) + *pppAdaptor = ppAdaptor; + else + ATIXVFreeAdaptorInfo(ppAdaptor, nAdaptor); + + return nAdaptor; +} + +/* + * ATIXVPreInit -- + * + * This function is called by ATIPreInit() to set up the environment required + * to support the XVideo extension. + */ +void +ATIXVPreInit +( + ATIPtr pATI +) +{ + +#ifndef AVOID_CPIO + + /* Currently a linear aperture is needed ... */ + if (!pATI->LinearBase) + return; + +#endif /* AVOID_CPIO */ + + (void)xf86XVRegisterGenericAdaptorDriver(ATIXVInitializeAdaptor); +} /* * ATIInitializeXVideo -- @@ -41,6 +124,7 @@ ATIInitializeXVideo { XF86VideoAdaptorPtr *ppAdaptor; int nAdaptor; + Bool result; if (!(pScreenInfo->memPhysBase = pATI->LinearBase)) return FALSE; @@ -48,5 +132,34 @@ ATIInitializeXVideo pScreenInfo->fbOffset = 0; nAdaptor = xf86XVListGenericAdaptors(pScreenInfo, &ppAdaptor); - return xf86XVScreenInit(pScreen, ppAdaptor, nAdaptor); + result = xf86XVScreenInit(pScreen, ppAdaptor, nAdaptor); + + ATIXVFreeAdaptorInfo(ppAdaptor, nAdaptor); + + return result; +} + +/* + * ATICloseXVideo -- + * + * This function is called during screen termination to clean up after XVideo + * initialisation. + */ +void +ATICloseXVideo +( + ScreenPtr pScreen, + ScrnInfoPtr pScreenInfo, + ATIPtr pATI +) +{ + switch (pATI->Adapter) + { + case ATI_ADAPTER_MACH64: + ATIMach64CloseXVideo(pScreen, pScreenInfo, pATI); + break; + + default: + break; + } } diff --git a/src/atixv.h b/src/atixv.h index a5a3de60..56f8da82 100644 --- a/src/atixv.h +++ b/src/atixv.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atixv.h,v 1.3 2003/01/01 19:16:35 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atixv.h,v 1.4 2003/04/23 21:51:31 tsi Exp $ */ /* * Copyright 2001 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -29,7 +29,10 @@ #include "xf86str.h" +extern void ATIXVPreInit FunctionPrototype((ATIPtr)); extern Bool ATIInitializeXVideo FunctionPrototype((ScreenPtr, ScrnInfoPtr, ATIPtr)); +extern void ATICloseXVideo FunctionPrototype((ScreenPtr, ScrnInfoPtr, + ATIPtr)); #endif /* ___ATIXV_H___ */ @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h,v 1.24 2002/12/16 16:19:10 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h,v 1.27 2003/11/10 18:41:20 tsi Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -172,8 +172,8 @@ typedef struct { typedef struct { CARD16 reference_freq; CARD16 reference_div; - CARD32 min_pll_freq; - CARD32 max_pll_freq; + unsigned min_pll_freq; + unsigned max_pll_freq; CARD16 xclk; } R128PLLRec, *R128PLLPtr; @@ -304,6 +304,10 @@ typedef struct { drmHandle pciMemHandle; unsigned char *PCI; /* Map */ + Bool allowPageFlip; /* Enable 3d page flipping */ + Bool have3DWindows; /* Are there any 3d clients? */ + int drmMinor; + drmSize agpSize; drmHandle agpMemHandle; /* Handle from drmAgpAlloc */ unsigned long agpOffset; @@ -487,7 +491,7 @@ do { \ !info->CCEInUse , __FUNCTION__ ); \ } \ if ( !info->CCEInUse ) { \ - R128CCEWaitForIdle(pScrn); \ + R128CCEWaitForIdle(pScrn); \ BEGIN_RING( 6 ); \ OUT_RING_REG( R128_RE_TOP_LEFT, info->re_top_left ); \ OUT_RING_REG( R128_RE_WIDTH_HEIGHT, info->re_width_height ); \ @@ -519,9 +523,9 @@ do { \ xf86DrvMsg( pScrn->scrnIndex, X_INFO, \ "ADVANCE_RING() used: %d+%d=%d/%d\n", \ info->indirectBuffer->used - info->indirectStart, \ - __count * sizeof(CARD32), \ + __count * (int)sizeof(CARD32), \ info->indirectBuffer->used - info->indirectStart + \ - __count * sizeof(CARD32), \ + __count * (int)sizeof(CARD32), \ info->indirectBuffer->total - info->indirectStart ); \ } \ info->indirectBuffer->used += __count * (int)sizeof(CARD32); \ diff --git a/src/r128_accel.c b/src/r128_accel.c index 9329ad25..884aa22e 100644 --- a/src/r128_accel.c +++ b/src/r128_accel.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c,v 1.16 2002/11/15 03:01:35 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c,v 1.18 2003/11/10 18:41:20 tsi Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -82,7 +82,6 @@ /* Driver data structures */ #include "r128.h" #include "r128_reg.h" -#include "r128_sarea.h" #ifdef XF86DRI #include "r128_sarea.h" #define _XF86DRI_SERVER_ @@ -1101,7 +1100,7 @@ static void R128CCESetupForSolidFill(ScrnInfoPtr pScrn, OUT_RING_REG( R128_DP_BRUSH_FRGD_CLR, color ); OUT_RING_REG( R128_DP_WRITE_MASK, planemask ); - OUT_RING_REG( R128_DP_CNTL, (R128_DST_X_LEFT_TO_RIGHT | + OUT_RING_REG( R128_DP_CNTL, (R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM)); ADVANCE_RING(); } @@ -1576,7 +1575,7 @@ drmBufPtr R128CCEGetBuffer( ScrnInfoPtr pScrn ) xf86DrvMsg( pScrn->scrnIndex, X_ERROR, "GetBuffer timed out, resetting engine...\n"); R128EngineReset( pScrn ); - /* R128EngineRestore( pScrn ); FIXME ??? */ + /* R128EngineRestore( pScrn ); FIXME ??? */ /* Always restart the engine when doing CCE 2D acceleration */ R128CCE_RESET( pScrn, info ); @@ -1656,7 +1655,7 @@ static void R128CCEAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a) a->PolyFillRectSolidFlags = 0; a->SetupForSolidFill = R128CCESetupForSolidFill; a->SubsequentSolidFillRect = R128CCESubsequentSolidFillRect; - + /* Screen-to-screen Copy */ /* Transparency uses the wrong colors for 24 bpp mode -- the transparent part is diff --git a/src/r128_common.h b/src/r128_common.h index 6f2c13a7..53dc940c 100644 --- a/src/r128_common.h +++ b/src/r128_common.h @@ -31,7 +31,7 @@ * Converted to common header format: * Jens Owen <jens@tungstengraphics.com> * - * $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_common.h,v 1.2 2002/12/16 16:19:10 dawes Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_common.h,v 1.3 2003/09/28 20:15:53 alanh Exp $ * */ @@ -67,6 +67,7 @@ #define DRM_R128_FULLSCREEN 0x10 #define DRM_R128_CLEAR2 0x11 #define DRM_R128_GETPARAM 0x12 +#define DRM_R128_FLIP 0x13 #define DRM_R128_FRONT_BUFFER 0x1 #define DRM_R128_BACK_BUFFER 0x2 diff --git a/src/r128_dga.c b/src/r128_dga.c index 6c0013af..97f83981 100644 --- a/src/r128_dga.c +++ b/src/r128_dga.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dga.c,v 1.9 2002/10/30 12:52:12 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dga.c,v 1.10 2003/11/10 18:41:20 tsi Exp $ */ /* * Authors: * Ove Kåven <ovek@transgaming.com>, @@ -65,7 +65,7 @@ SECOND_PASS: pitch = secondPitch; if (!(newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec)))) - break; + break; modes = newmodes; currentMode = modes + *num; @@ -74,7 +74,7 @@ SECOND_PASS: currentMode->flags = DGA_CONCURRENT_ACCESS; if (pixmap) - currentMode->flags |= DGA_PIXMAP_AVAILABLE; + currentMode->flags |= DGA_PIXMAP_AVAILABLE; if (info->accel) { if (info->accel->SetupForSolidFill && @@ -91,7 +91,7 @@ SECOND_PASS: if (pMode->Flags & V_DBLSCAN) currentMode->flags |= DGA_DOUBLESCAN; if (pMode->Flags & V_INTERLACE) - currentMode->flags |= DGA_INTERLACED; + currentMode->flags |= DGA_INTERLACED; currentMode->byteOrder = pScrn->imageByteOrder; currentMode->depth = depth; @@ -240,16 +240,16 @@ R128_SetMode( pScrn->SwitchMode(indx, pScrn->currentMode, 0); #ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled) { R128CCE_STOP(pScrn, info); - } + } #endif if (info->accelOn) R128EngineInit(pScrn); #ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled) { R128CCE_START(pScrn, info); - } + } #endif pScrn->AdjustFrame(indx, 0, 0, 0); info->DGAactive = FALSE; @@ -272,16 +272,16 @@ R128_SetMode( pScrn->SwitchMode(indx, pMode->mode, 0); #ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled) { R128CCE_STOP(pScrn, info); - } + } #endif if (info->accelOn) R128EngineInit(pScrn); #ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled) { R128CCE_START(pScrn, info); - } + } #endif } diff --git a/src/r128_dri.c b/src/r128_dri.c index 63cedb59..f92e4c50 100644 --- a/src/r128_dri.c +++ b/src/r128_dri.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c,v 1.28 2003/02/07 20:41:14 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c,v 1.32 2003/11/10 18:41:20 tsi Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -49,6 +49,7 @@ #include "windowstr.h" #include "xf86PciInfo.h" +#include "shadowfb.h" /* GLX/DRI/DRM definitions */ #define _XF86DRI_SERVER_ #include "GL/glxtokens.h" @@ -64,6 +65,13 @@ # define DRM_PAGE_SIZE 4096 #endif +static void R128DRITransitionTo2d(ScreenPtr pScreen); +static void R128DRITransitionTo3d(ScreenPtr pScreen); +static void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen); +static void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen); + +static void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); + /* Initialize the visual configs that are supported by the hardware. These are combined with the visual configs that the indirect rendering core supports, and the intersection is exported to the @@ -144,7 +152,7 @@ static Bool R128InitVisualConfigs(ScreenPtr pScreen) pConfigs[i].accumBlueSize = 0; pConfigs[i].accumAlphaSize = 0; } - if (db) + if (db) pConfigs[i].doubleBuffer = TRUE; else pConfigs[i].doubleBuffer = FALSE; @@ -158,9 +166,9 @@ static Bool R128InitVisualConfigs(ScreenPtr pScreen) pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; if (accum || stencil) { - pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT; + pConfigs[i].visualRating = GLX_SLOW_CONFIG; } else { - pConfigs[i].visualRating = GLX_NONE_EXT; + pConfigs[i].visualRating = GLX_NONE; } pConfigs[i].transparentPixel = GLX_NONE; pConfigs[i].transparentRed = 0; @@ -243,9 +251,9 @@ static Bool R128InitVisualConfigs(ScreenPtr pScreen) pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; if (accum || stencil) { - pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT; + pConfigs[i].visualRating = GLX_SLOW_CONFIG; } else { - pConfigs[i].visualRating = GLX_NONE_EXT; + pConfigs[i].visualRating = GLX_NONE; } pConfigs[i].transparentPixel = GLX_NONE; pConfigs[i].transparentRed = 0; @@ -355,7 +363,11 @@ static void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx) int nbox, nboxSave; int depth; - /* FIXME: Use accel when CCE 2D code is written */ + /* FIXME: Use accel when CCE 2D code is written + * EA: What is this code kept for? Radeon doesn't have it and + * has a comment: "There's no need for the 2d driver to be clearing + * buffers for the 3d client. It knows how to do that on its own." + */ if (info->directRenderingEnabled) return; @@ -477,7 +489,7 @@ static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen) return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, - "[agp] %d kB allocated with handle 0x%08x\n", + "[agp] %d kB allocated with handle 0x%08lx\n", info->agpSize*1024, info->agpMemHandle); if (drmAgpBind(info->drmFD, info->agpMemHandle, info->agpOffset) < 0) { @@ -606,7 +618,7 @@ static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen) return FALSE; } agpBase = drmAgpBase(info->drmFD); - OUTREG(R128_AGP_BASE, agpBase); + OUTREG(R128_AGP_BASE, agpBase); OUTREG(R128_AGP_CNTL, cntl); /* Disable Rage 128's PCIGART registers */ @@ -637,7 +649,7 @@ static Bool R128DRIPciInit(R128InfoPtr info, ScreenPtr pScreen) return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, - "[pci] %d kB allocated with handle 0x%08x\n", + "[pci] %d kB allocated with handle 0x%08lx\n", info->agpSize*1024, info->pciMemHandle); /* Initialize the CCE ring buffer data */ @@ -1063,6 +1075,10 @@ Bool R128DRIScreenInit(ScreenPtr pScreen) pDRIInfo->InitBuffers = R128DRIInitBuffers; pDRIInfo->MoveBuffers = R128DRIMoveBuffers; pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; + pDRIInfo->TransitionTo2d = R128DRITransitionTo2d; + pDRIInfo->TransitionTo3d = R128DRITransitionTo3d; + pDRIInfo->TransitionSingleToMulti3D = R128DRITransitionSingleToMulti3d; + pDRIInfo->TransitionMultiToSingle3D = R128DRITransitionMultiToSingle3d; pDRIInfo->createDummyCtx = TRUE; pDRIInfo->createDummyCtxPriv = FALSE; @@ -1130,6 +1146,7 @@ Bool R128DRIScreenInit(ScreenPtr pScreen) R128DRICloseScreen(pScreen); return FALSE; } + info->drmMinor = version->version_minor; drmFreeVersion(version); } @@ -1161,9 +1178,9 @@ Bool R128DRIScreenInit(ScreenPtr pScreen) { void *scratch_ptr; int scratch_int; - + DRIGetDeviceInfo(pScreen, &info->fbHandle, - &scratch_int, &scratch_int, + &scratch_int, &scratch_int, &scratch_int, &scratch_int, &scratch_ptr); } @@ -1253,6 +1270,15 @@ Bool R128DRIFinishScreenInit(ScreenPtr pScreen) pR128DRI->agpTexOffset = info->agpTexStart; pR128DRI->sarea_priv_offset = sizeof(XF86DRISAREARec); + /* Have shadowfb run only while there is 3d active. */ + if (info->allowPageFlip && info->drmMinor >= 5 ) { + ShadowFBInit( pScreen, R128DRIRefreshArea ); + } else if (info->allowPageFlip) { + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[dri] Kernel module version 2.5.0 or newer is required for pageflipping.\n"); + info->allowPageFlip = 0; + } + return TRUE; } @@ -1303,10 +1329,10 @@ void R128DRICloseScreen(ScreenPtr pScreen) drmUnmap(info->ring, info->ringMapSize); info->ring = NULL; } - if (info->agpMemHandle) { + if (info->agpMemHandle != DRM_AGP_NO_HANDLE) { drmAgpUnbind(info->drmFD, info->agpMemHandle); drmAgpFree(info->drmFD, info->agpMemHandle); - info->agpMemHandle = 0; + info->agpMemHandle = DRM_AGP_NO_HANDLE; drmAgpRelease(info->drmFD); } if (info->pciMemHandle) { @@ -1335,3 +1361,129 @@ void R128DRICloseScreen(ScreenPtr pScreen) info->pVisualConfigsPriv = NULL; } } + +/* Use callbacks from dri.c to support pageflipping mode for a single + * 3d context without need for any specific full-screen extension. + */ + +/* Use the shadowfb module to maintain a list of dirty rectangles. + * These are blitted to the back buffer to keep both buffers clean + * during page-flipping when the 3d application isn't fullscreen. + * + * Unlike most use of the shadowfb code, both buffers are in video memory. + * + * An alternative to this would be to organize for all on-screen drawing + * operations to be duplicated for the two buffers. That might be + * faster, but seems like a lot more work... + */ + + +static void R128DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + R128InfoPtr info = R128PTR(pScrn); + int i; + R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + + /* Don't want to do this when no 3d is active and pages are + * right-way-round + */ + if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) + return; + + (*info->accel->SetupForScreenToScreenCopy)(pScrn, + 1, 1, GXcopy, + (CARD32)(-1), -1); + + for (i = 0 ; i < num ; i++, pbox++) { + int xa = max(pbox->x1, 0), xb = min(pbox->x2, pScrn->virtualX-1); + int ya = max(pbox->y1, 0), yb = min(pbox->y2, pScrn->virtualY-1); + + if (xa <= xb && ya <= yb) { + (*info->accel->SubsequentScreenToScreenCopy)(pScrn, xa, ya, + xa + info->backX, + ya + info->backY, + xb - xa + 1, + yb - ya + 1); + } + } +} + +static void R128EnablePageFlip(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + if (info->allowPageFlip) { + /* Duplicate the frontbuffer to the backbuffer */ + (*info->accel->SetupForScreenToScreenCopy)(pScrn, + 1, 1, GXcopy, + (CARD32)(-1), -1); + + (*info->accel->SubsequentScreenToScreenCopy)(pScrn, + 0, + 0, + info->backX, + info->backY, + pScrn->virtualX, + pScrn->virtualY); + + pSAREAPriv->pfAllowPageFlip = 1; + } +} + +static void R128DisablePageFlip(ScreenPtr pScreen) +{ + /* Tell the clients not to pageflip. How? + * -- Field in sarea, plus bumping the window counters. + * -- DRM needs to cope with Front-to-Back swapbuffers. + */ + R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + pSAREAPriv->pfAllowPageFlip = 0; +} + +static void R128DRITransitionSingleToMulti3d(ScreenPtr pScreen) +{ + R128DisablePageFlip(pScreen); +} + +static void R128DRITransitionMultiToSingle3d(ScreenPtr pScreen) +{ + /* Let the remaining 3d app start page flipping again */ + R128EnablePageFlip(pScreen); +} + +static void R128DRITransitionTo3d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + + R128EnablePageFlip(pScreen); + + info->have3DWindows = 1; + + if (info->cursor_start) + xf86ForceHWCursor(pScreen, TRUE); +} + +static void R128DRITransitionTo2d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + /* Shut down shadowing if we've made it back to the front page */ + if (pSAREAPriv->pfCurrentPage == 0) { + R128DisablePageFlip(pScreen); + } else { + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[dri] R128DRITransitionTo2d: " + "kernel failed to unflip buffers.\n"); + } + + info->have3DWindows = 0; + + if (info->cursor_start) + xf86ForceHWCursor(pScreen, FALSE); +} diff --git a/src/r128_driver.c b/src/r128_driver.c index 271c2fb8..68287a14 100644 --- a/src/r128_driver.c +++ b/src/r128_driver.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c,v 1.75 2003/02/19 01:19:41 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c,v 1.87 2003/11/10 18:41:21 tsi Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -70,20 +70,7 @@ #include "r128_sarea.h" #endif -#define USE_FB /* not until overlays */ -#ifdef USE_FB #include "fb.h" -#else - - /* CFB support */ -#define PSZ 8 -#include "cfb.h" -#undef PSZ -#include "cfb16.h" -#include "cfb24.h" -#include "cfb32.h" -#include "cfb24_32.h" -#endif /* colormap initialization */ #include "micmap.h" @@ -135,6 +122,7 @@ typedef enum { OPTION_AGP_SIZE, OPTION_RING_SIZE, OPTION_BUFFER_SIZE, + OPTION_PAGE_FLIP, #endif #if USE_CRT_ONLY /* FIXME: Disable CRTOnly until it is tested */ @@ -164,6 +152,7 @@ const OptionInfoRec R128Options[] = { { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_BUFFER_SIZE, "BufferSize", OPTV_INTEGER, {0}, FALSE }, + { OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE }, #endif { OPTION_DISPLAY, "Display", OPTV_STRING, {0}, FALSE }, { OPTION_PANEL_WIDTH, "PanelWidth", OPTV_INTEGER, {0}, FALSE }, @@ -238,22 +227,11 @@ static const char *i2cSymbols[] = { NULL }; -#ifdef USE_FB static const char *fbSymbols[] = { "fbPictureInit", "fbScreenInit", NULL }; -#else -static const char *cfbSymbols[] = { - "cfbScreenInit", - "cfb16ScreenInit", - "cfb24ScreenInit", - "cfb32ScreenInit", - "cfb24_32ScreenInit", - NULL -}; -#endif static const char *xaaSymbols[] = { "XAACreateInfoRec", @@ -275,6 +253,7 @@ static const char *drmSymbols[] = { "drmAddMap", "drmAgpAcquire", "drmAgpAlloc", + "drmAgpBase", "drmAgpBind", "drmAgpDeviceId", "drmAgpEnable", @@ -288,8 +267,11 @@ static const char *drmSymbols[] = { "drmCommandRead", "drmCommandWrite", "drmCommandWriteRead", + "drmCtlInstHandler", + "drmCtlUninstHandler", "drmFreeBufs", "drmFreeVersion", + "drmGetInterruptFromBusID", "drmGetLibVersion", "drmGetVersion", "drmMap", @@ -307,6 +289,7 @@ static const char *driSymbols[] = { "DRICreateInfoRec", "DRIDestroyInfoRec", "DRIFinishScreenInit", + "DRIGetDeviceInfo", "DRIGetSAREAPrivate", "DRILock", "DRIQueryVersion", @@ -315,6 +298,11 @@ static const char *driSymbols[] = { "GlxSetVisualConfigs", NULL }; + +static const char *driShadowFBSymbols[] = { + "ShadowFBInit", + NULL +}; #endif static const char *vbeSymbols[] = { @@ -338,16 +326,13 @@ void R128LoaderRefSymLists(void) * refer to. */ xf86LoaderRefSymLists(vgahwSymbols, -#ifdef USE_FB fbSymbols, -#else - cfbSymbols, -#endif xaaSymbols, ramdacSymbols, #ifdef XF86DRI drmSymbols, driSymbols, + driShadowFBSymbols, #endif fbdevHWSymbols, int10Symbols, @@ -652,7 +637,7 @@ static Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) info->HasPanelRegs = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Can't determine panel dimensions, and none specified. \ - Disabling programming of FP registers.\n"); + Disabling programming of FP registers.\n"); } return TRUE; @@ -741,7 +726,7 @@ static Bool R128PreInitVisual(ScrnInfoPtr pScrn) { R128InfoPtr info = R128PTR(pScrn); - if (!xf86SetDepthBpp(pScrn, 8, 8, 8, (Support24bppFb + if (!xf86SetDepthBpp(pScrn, 0, 0, 0, (Support24bppFb | Support32bppFb | SupportConvert32to24 ))) @@ -869,7 +854,7 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) pScrn->memPhysBase = info->LinearAddr; if (dev->MemBase) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Linear address override, using 0x%08x instead of 0x%08x\n", + "Linear address override, using 0x%08lx instead of 0x%08lx\n", dev->MemBase, info->LinearAddr); info->LinearAddr = dev->MemBase; @@ -887,7 +872,7 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) info->MMIOAddr = info->PciInfo->memBase[2] & 0xffffff00; if (dev->IOBase) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "MMIO address override, using 0x%08x instead of 0x%08x\n", + "MMIO address override, using 0x%08lx instead of 0x%08lx\n", dev->IOBase, info->MMIOAddr); info->MMIOAddr = dev->IOBase; @@ -904,7 +889,7 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) info->BIOSAddr = info->PciInfo->biosBase & 0xfffe0000; if (dev->BiosBase) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS address override, using 0x%08x instead of 0x%08x\n", + "BIOS address override, using 0x%08lx instead of 0x%08lx\n", dev->BiosBase, info->BIOSAddr); info->BIOSAddr = dev->BiosBase; @@ -929,8 +914,8 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) switch (info->Chipset) { /* R128 Pro and Pro2 can have DFP, we will deal with it. No support for dual-head/xinerama yet. - M3 can also have DFP, no support for now */ - case PCI_CHIP_RAGE128TF: + M3 can also have DFP, no support for now */ + case PCI_CHIP_RAGE128TF: case PCI_CHIP_RAGE128TL: case PCI_CHIP_RAGE128TR: /* FIXME: RAGE128 TS/TT/TU are assumed to be PRO2 as all 6 chips came @@ -938,9 +923,9 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) * This requires confirmation however to be fully correct. * Mike A. Harris <mharris@redhat.com> */ - case PCI_CHIP_RAGE128TS: + case PCI_CHIP_RAGE128TS: case PCI_CHIP_RAGE128TT: - case PCI_CHIP_RAGE128TU: info->isPro2 = TRUE; + case PCI_CHIP_RAGE128TU: info->isPro2 = TRUE; /* FIXME: RAGE128 P[ABCEGHIJKLMNOQSTUVWX] are assumed to have DFP * capability, as the comment at the top suggests. * This requires confirmation however to be fully correct. @@ -1245,7 +1230,7 @@ R128I2CPutBits(I2CBusPtr b, int Clock, int data) unsigned long val; unsigned char *R128MMIO = info->MMIO; - val = INREG(info->DDCReg) + val = INREG(info->DDCReg) & ~(CARD32)(R128_GPIO_MONID_EN_0 | R128_GPIO_MONID_EN_3); val |= (Clock ? 0:R128_GPIO_MONID_EN_3); val |= (data ? 0:R128_GPIO_MONID_EN_0); @@ -1260,7 +1245,7 @@ R128I2cInit(ScrnInfoPtr pScrn) if ( xf86LoadSubModule(pScrn, "i2c") ) xf86LoaderReqSymLists(i2cSymbols,NULL); else{ - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load i2c module\n"); return FALSE; } @@ -1291,11 +1276,11 @@ static Bool R128GetDFPInfo(ScrnInfoPtr pScrn) unsigned char *R128MMIO = info->MMIO; if(!R128I2cInit(pScrn)){ - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I2C initialization failed!\n"); } - OUTREG(info->DDCReg, (INREG(info->DDCReg) + OUTREG(info->DDCReg, (INREG(info->DDCReg) | R128_GPIO_MONID_MASK_0 | R128_GPIO_MONID_MASK_3)); OUTREG(info->DDCReg, INREG(info->DDCReg) @@ -1303,7 +1288,7 @@ static Bool R128GetDFPInfo(ScrnInfoPtr pScrn) MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); if(!MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No DFP detected\n"); return FALSE; } @@ -1321,19 +1306,19 @@ static Bool R128GetDFPInfo(ScrnInfoPtr pScrn) info->HOverPlus = ddc->det_mon[i].section.d_timings.h_sync_off; - info->HSyncWidth = + info->HSyncWidth = ddc->det_mon[i].section.d_timings.h_sync_width; info->HBlank = ddc->det_mon[i].section.d_timings.h_blanking; info->VOverPlus = ddc->det_mon[i].section.d_timings.v_sync_off; - info->VSyncWidth = + info->VSyncWidth = ddc->det_mon[i].section.d_timings.v_sync_width; info->VBlank = ddc->det_mon[i].section.d_timings.v_blanking; - } + } } - return TRUE; + return TRUE; } @@ -1348,63 +1333,63 @@ static void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) if(ddc->det_mon[i].type == DS_RANGES) { pScrn->monitor->nHsync = 1; - pScrn->monitor->hsync[0].lo = + pScrn->monitor->hsync[0].lo = ddc->det_mon[i].section.ranges.min_h; - pScrn->monitor->hsync[0].hi = + pScrn->monitor->hsync[0].hi = ddc->det_mon[i].section.ranges.max_h; return; } } /*if no sync ranges detected in detailed timing table, let's try to derive them from supported VESA modes - Are we doing too much here!!!? + Are we doing too much here!!!? **/ i = 0; if(ddc->timings1.t1 & 0x02) /*800x600@56*/ { - pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].lo = pScrn->monitor->hsync[i].hi = 35.2; i++; - } + } if(ddc->timings1.t1 & 0x04) /*640x480@75*/ { - pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].lo = pScrn->monitor->hsync[i].hi = 37.5; i++; - } + } if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) { - pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].lo = pScrn->monitor->hsync[i].hi = 37.9; i++; - } + } if(ddc->timings1.t2 & 0x40) { - pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].lo = pScrn->monitor->hsync[i].hi = 46.9; i++; } if((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) { - pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].lo = pScrn->monitor->hsync[i].hi = 48.1; i++; - } + } if(ddc->timings1.t2 & 0x04) { - pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].lo = pScrn->monitor->hsync[i].hi = 56.5; i++; - } + } if(ddc->timings1.t2 & 0x02) { - pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].lo = pScrn->monitor->hsync[i].hi = 60.0; i++; - } + } if(ddc->timings1.t2 & 0x01) { - pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].lo = pScrn->monitor->hsync[i].hi = 64.0; i++; } @@ -1417,42 +1402,42 @@ static void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) if(ddc->det_mon[i].type == DS_RANGES) { pScrn->monitor->nVrefresh = 1; - pScrn->monitor->vrefresh[0].lo = + pScrn->monitor->vrefresh[0].lo = ddc->det_mon[i].section.ranges.min_v; - pScrn->monitor->vrefresh[0].hi = + pScrn->monitor->vrefresh[0].hi = ddc->det_mon[i].section.ranges.max_v; return; } } i = 0; if(ddc->timings1.t1 & 0x02) /*800x600@56*/ - { - pScrn->monitor->vrefresh[i].lo = + { + pScrn->monitor->vrefresh[i].lo = pScrn->monitor->vrefresh[i].hi = 56; i++; } if((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) - { - pScrn->monitor->vrefresh[i].lo = + { + pScrn->monitor->vrefresh[i].lo = pScrn->monitor->vrefresh[i].hi = 60; i++; } if(ddc->timings1.t2 & 0x04) - { - pScrn->monitor->vrefresh[i].lo = + { + pScrn->monitor->vrefresh[i].lo = pScrn->monitor->vrefresh[i].hi = 70; i++; } if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) - { - pScrn->monitor->vrefresh[i].lo = + { + pScrn->monitor->vrefresh[i].lo = pScrn->monitor->vrefresh[i].hi = 72; i++; } if((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) || (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) - { - pScrn->monitor->vrefresh[i].lo = + { + pScrn->monitor->vrefresh[i].lo = pScrn->monitor->vrefresh[i].hi = 75; i++; } @@ -1460,13 +1445,13 @@ static void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) } } -/*********** +/*********** xfree's xf86ValidateModes routine deosn't work well with DFPs - here is our own validation routine. All modes between - 640<=XRes<=MaxRes and 480<=YRes<=MaxYRes will be permitted. - NOTE: RageProII doesn't support rmx, can only work with the + here is our own validation routine. All modes between + 640<=XRes<=MaxRes and 480<=YRes<=MaxYRes will be permitted. + NOTE: RageProII doesn't support rmx, can only work with the standard modes the monitor can support (scale). -************/ +************/ static int R128ValidateFPModes(ScrnInfoPtr pScrn) { @@ -1501,15 +1486,15 @@ static int R128ValidateFPModes(ScrnInfoPtr pScrn) if (sscanf(pScrn->display->modes[i], "%dx%d", &width, &height) == 2) { - if(width < 640 || width > info->PanelXRes || + if(width < 640 || width > info->PanelXRes || height < 480 || height > info->PanelYRes) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode %s is out of range.\n" "Valid mode should be between 640x480-%dx%d\n", pScrn->display->modes[i], info->PanelXRes, info->PanelYRes); continue; - } + } new = xnfcalloc(1, sizeof(DisplayModeRec)); new->prev = last; @@ -1539,8 +1524,8 @@ static int R128ValidateFPModes(ScrnInfoPtr pScrn) } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Mode name %s is invalid\n", pScrn->display->modes[i]); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Mode name %s is invalid\n", pScrn->display->modes[i]); continue; } } @@ -1582,10 +1567,6 @@ static Bool R128PreInitModes(ScrnInfoPtr pScrn) R128InfoPtr info = R128PTR(pScrn); ClockRangePtr clockRanges; int modesFound; - char *mod = NULL; -#ifndef USE_FB - const char *Sym = NULL; -#endif if(info->isDFP) { R128MapMem(pScrn); @@ -1595,16 +1576,16 @@ static Bool R128PreInitModes(ScrnInfoPtr pScrn) info->isDFP = FALSE; info->BIOSDisplay = R128_BIOS_DISPLAY_CRT; } else if(!info->isPro2) { - /* RageProII doesn't support rmx, we can't use native-mode + /* RageProII doesn't support rmx, we can't use native-mode stretching for other non-native modes. It will rely on whatever VESA modes monitor can support. */ modesFound = R128ValidateFPModes(pScrn); if(modesFound < 1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid mode found for this DFP/LCD\n"); R128UnmapMem(pScrn); return FALSE; - + } } R128UnmapMem(pScrn); @@ -1640,7 +1621,6 @@ static Bool R128PreInitModes(ScrnInfoPtr pScrn) R128SetSyncRangeFromEdid(pScrn, 0); } - modesFound = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, @@ -1657,9 +1637,9 @@ static Bool R128PreInitModes(ScrnInfoPtr pScrn) LOOKUP_BEST_REFRESH); if (modesFound < 1 && info->FBDev) { - fbdevHWUseBuildinMode(pScrn); - pScrn->displayWidth = fbdevHWGetLineLength(pScrn)/(pScrn->bitsPerPixel/8); - modesFound = 1; + fbdevHWUseBuildinMode(pScrn); + pScrn->displayWidth = fbdevHWGetLineLength(pScrn)/(pScrn->bitsPerPixel/8); + modesFound = 1; } if (modesFound == -1) return FALSE; @@ -1677,28 +1657,8 @@ static Bool R128PreInitModes(ScrnInfoPtr pScrn) xf86SetDpi(pScrn, 0, 0); /* Get ScreenInit function */ -#ifdef USE_FB - mod = "fb"; -#else - switch (pScrn->bitsPerPixel) { - case 8: mod = "cfb"; Sym = "cfbScreenInit"; break; - case 16: mod = "cfb16"; Sym = "cfb16ScreenInit"; break; - case 24: - if (info->pix24bpp == 24) { - mod = "cfb24"; Sym = "cfb24ScreenInit"; - } else { - mod = "xf24_32bpp"; Sym = "cfb24_32ScreenInit"; - } - break; - case 32: mod = "cfb32"; Sym = "cfb32ScreenInit"; break; - } -#endif - if (mod && !xf86LoadSubModule(pScrn, mod)) return FALSE; -#ifdef USE_FB + if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; xf86LoaderReqSymLists(fbSymbols, NULL); -#else - xf86LoaderReqSymbols(Sym, NULL); -#endif info->CurrentLayout.displayWidth = pScrn->displayWidth; info->CurrentLayout.mode = pScrn->currentMode; @@ -1845,6 +1805,21 @@ static Bool R128PreInitDRI(ScrnInfoPtr pScrn) /* This option checked by the R128 DRM kernel module */ } + if (!xf86LoadSubModule(pScrn, "shadowfb")) { + info->allowPageFlip = 0; + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't load shadowfb module:\n"); + } else { + xf86LoaderReqSymLists(driShadowFBSymbols, NULL); + + info->allowPageFlip = xf86ReturnOptValBool(info->Options, + OPTION_PAGE_FLIP, + FALSE); + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n", + info->allowPageFlip ? "en" : "dis"); + return TRUE; } #endif @@ -2121,8 +2096,8 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #ifdef XF86DRI /* Setup DRI after visuals have been - established, but before cfbScreenInit is - called. cfbScreenInit will eventually + established, but before fbScreenInit is + called. fbScreenInit will eventually call the driver's InitGLXVisuals call back. */ { @@ -2150,53 +2125,12 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } #endif -#ifdef USE_FB if (!fbScreenInit (pScreen, info->FB, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel)) return FALSE; -#else - switch (pScrn->bitsPerPixel) { - case 8: - if (!cfbScreenInit(pScreen, info->FB, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth)) - return FALSE; - break; - case 16: - if (!cfb16ScreenInit(pScreen, info->FB, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth)) - return FALSE; - break; - case 24: - if (info->pix24bpp == 24) { - if (!cfb24ScreenInit(pScreen, info->FB, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, - pScrn->displayWidth)) - return FALSE; - } else { - if (!cfb24_32ScreenInit(pScreen, info->FB, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, - pScrn->displayWidth)) - return FALSE; - } - break; - case 32: - if (!cfb32ScreenInit(pScreen, info->FB, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth)) - return FALSE; - break; - default: - xf86DrvMsg(scrnIndex, X_ERROR, - "Invalid bpp (%d)\n", pScrn->bitsPerPixel); - return FALSE; - } -#endif + xf86SetBlackWhitePixels(pScreen); if (pScrn->bitsPerPixel > 8) { @@ -2215,10 +2149,9 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } } -#ifdef USE_FB /* must be after RGB order fixed */ fbPictureInit (pScreen, 0, 0); -#endif + /* Memory manager setup */ #ifdef XF86DRI if (info->directRenderingEnabled) { @@ -2467,7 +2400,7 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) int width, height; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using hardware cursor (scanline %d)\n", + "Using hardware cursor (scanline %ld)\n", info->cursor_start / pScrn->displayWidth); if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0)) { @@ -2523,7 +2456,7 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #ifdef XF86DRI /* DRI finalization */ if (info->directRenderingEnabled) { - /* Now that mi, cfb, drm and others have + /* Now that mi, fb, drm and others have done their thing, complete the DRI setup. */ info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen); @@ -2915,7 +2848,11 @@ static void R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info) save->subpic_cntl = 0; save->viph_control = 0; save->i2c_cntl_1 = 0; +#ifdef XF86DRI + save->gen_int_cntl = info->gen_int_cntl; +#else save->gen_int_cntl = 0; +#endif save->cap0_trig_cntl = 0; save->cap1_trig_cntl = 0; save->bus_cntl = info->BusCntl; @@ -2935,25 +2872,23 @@ static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, int hsync_wid; int hsync_fudge; int vsync_wid; - int bytpp; int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; int hsync_fudge_fp[] = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 }; int hsync_fudge_fp_crt[] = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 }; switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; bytpp = 0; break; - case 8: format = 2; bytpp = 1; break; - case 15: format = 3; bytpp = 2; break; /* 555 */ - case 16: format = 4; bytpp = 2; break; /* 565 */ - case 24: format = 5; bytpp = 3; break; /* RGB */ - case 32: format = 6; bytpp = 4; break; /* xRGB */ + 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; } - R128TRACE(("Format = %d (%d bytes per pixel)\n", format, bytpp)); switch (info->BIOSDisplay) { case R128_BIOS_DISPLAY_FP: @@ -3079,7 +3014,7 @@ static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, R128_FP_CRTC_DONT_SHADOW_VPAR); save->fp_panel_cntl = orig->fp_panel_cntl & (CARD32)~R128_FP_DIGON; save->lvds_gen_cntl = orig->lvds_gen_cntl & - (CARD32)~(R128_LVDS_ON | R128_LVDS_BLON); + (CARD32)~(R128_LVDS_ON | R128_LVDS_BLON); return; } @@ -3097,9 +3032,9 @@ static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, R128_HORZ_STRETCH_RESERVED))); save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN; save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO; - if (xres == info->PanelXRes) + if (xres == info->PanelXRes) save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE); - else + else save->fp_horz_stretch |= (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE); save->fp_vert_stretch = @@ -3108,9 +3043,9 @@ static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE | R128_VERT_STRETCH_RESERVED))); save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN; - if (yres == info->PanelYRes) + if (yres == info->PanelYRes) save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND); - else + else save->fp_vert_stretch |= (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND); save->fp_gen_cntl = (orig->fp_gen_cntl & @@ -3119,7 +3054,7 @@ static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, R128_FP_CRTC_HORZ_DIV2_EN | R128_FP_CRTC_HOR_CRT_DIV2_DIS | R128_FP_USE_SHADOW_EN)); - + save->fp_panel_cntl = orig->fp_panel_cntl; save->lvds_gen_cntl = orig->lvds_gen_cntl; save->tmds_crc = orig->tmds_crc; @@ -3129,28 +3064,28 @@ static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, want to use the dual CRTC capabilities of the R128 to allow both the flat panel and external CRT to either simultaneously display the same image or display two different images. */ - + if(!info->isDFP){ if (info->BIOSDisplay == R128_BIOS_DISPLAY_FP_CRT) { - save->crtc_ext_cntl |= R128_CRTC_CRT_ON; + save->crtc_ext_cntl |= R128_CRTC_CRT_ON; } else { - save->crtc_ext_cntl &= ~R128_CRTC_CRT_ON; - save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2; - save->crtc2_gen_cntl = 0; + save->crtc_ext_cntl &= ~R128_CRTC_CRT_ON; + save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2; + save->crtc2_gen_cntl = 0; } } /* WARNING: Be careful about turning on the flat panel */ if(info->isDFP){ save->fp_gen_cntl = orig->fp_gen_cntl; - + save->fp_gen_cntl &= ~(R128_FP_CRTC_USE_SHADOW_VEND | R128_FP_CRTC_USE_SHADOW_ROWCUR | R128_FP_CRTC_HORZ_DIV2_EN | R128_FP_CRTC_HOR_CRT_DIV2_DIS | R128_FP_CRT_SYNC_SEL | R128_FP_USE_SHADOW_EN); - + save->fp_panel_cntl |= (R128_FP_DIGON | R128_FP_BLON); save->fp_gen_cntl |= (R128_FP_FPON | R128_FP_TDMS_EN | R128_FP_CRTC_DONT_SHADOW_VPAR | R128_FP_CRTC_DONT_SHADOW_HEND); @@ -3220,7 +3155,7 @@ static void R128InitPLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save, /* Define DDA registers for requested video mode. */ static Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save, - R128PLLPtr pll, R128InfoPtr info, + R128PLLPtr pll, R128InfoPtr info, DisplayModePtr mode) { int DisplayFifoWidth = 128; @@ -3361,7 +3296,7 @@ static Bool R128Init(ScrnInfoPtr pScrn, DisplayModePtr mode, R128SavePtr save) if(dot_clock > 0){ R128InitPLLRegisters(pScrn, save, &info->pll, dot_clock); if (!R128InitDDARegisters(pScrn, save, &info->pll, info, mode)) - return FALSE; + return FALSE; } else{ save->ppll_ref_div = info->SavedReg.ppll_ref_div; @@ -3416,8 +3351,8 @@ Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } /* Used to disallow modes that are not supported by the hardware. */ -int R128ValidMode(int scrnIndex, DisplayModePtr mode, - Bool verbose, int flag) +ModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode, + Bool verbose, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); @@ -3444,33 +3379,47 @@ int R128ValidMode(int scrnIndex, DisplayModePtr mode, if (mode->CrtcHDisplay == R128_BIOS16(j) && mode->CrtcVDisplay == R128_BIOS16(j+2)) { - /* Assume we are using expanded mode */ - if (R128_BIOS16(j+5)) j = R128_BIOS16(j+5); - else j += 9; - - mode->Clock = (CARD32)R128_BIOS16(j) * 10; - - mode->HDisplay = mode->CrtcHDisplay = - ((R128_BIOS16(j+10) & 0x01ff)+1)*8; - mode->HSyncStart = mode->CrtcHSyncStart = - ((R128_BIOS16(j+12) & 0x01ff)+1)*8; - mode->HSyncEnd = mode->CrtcHSyncEnd = - mode->CrtcHSyncStart + (R128_BIOS8(j+14) & 0x1f); - mode->HTotal = mode->CrtcHTotal = - ((R128_BIOS16(j+8) & 0x01ff)+1)*8; - - mode->VDisplay = mode->CrtcVDisplay = - (R128_BIOS16(j+17) & 0x07ff)+1; - mode->VSyncStart = mode->CrtcVSyncStart = - (R128_BIOS16(j+19) & 0x07ff)+1; - mode->VSyncEnd = mode->CrtcVSyncEnd = - mode->CrtcVSyncStart + ((R128_BIOS16(j+19) >> 11) & 0x1f); - mode->VTotal = mode->CrtcVTotal = - (R128_BIOS16(j+15) & 0x07ff)+1; - + if ((flags & MODECHECK_FINAL) == MODECHECK_FINAL) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Modifying mode according to VBIOS: %ix%i [pclk %.1f MHz] for FP to: ", + mode->CrtcHDisplay,mode->CrtcVDisplay, + (float)mode->Clock/1000); + + /* Assume we are using expanded mode */ + if (R128_BIOS16(j+5)) j = R128_BIOS16(j+5); + else j += 9; + + mode->Clock = (CARD32)R128_BIOS16(j) * 10; + + mode->HDisplay = mode->CrtcHDisplay = + ((R128_BIOS16(j+10) & 0x01ff)+1)*8; + mode->HSyncStart = mode->CrtcHSyncStart = + ((R128_BIOS16(j+12) & 0x01ff)+1)*8; + mode->HSyncEnd = mode->CrtcHSyncEnd = + mode->CrtcHSyncStart + (R128_BIOS8(j+14) & 0x1f); + mode->HTotal = mode->CrtcHTotal = + ((R128_BIOS16(j+8) & 0x01ff)+1)*8; + + mode->VDisplay = mode->CrtcVDisplay = + (R128_BIOS16(j+17) & 0x07ff)+1; + mode->VSyncStart = mode->CrtcVSyncStart = + (R128_BIOS16(j+19) & 0x07ff)+1; + mode->VSyncEnd = mode->CrtcVSyncEnd = + mode->CrtcVSyncStart + ((R128_BIOS16(j+19) >> 11) & 0x1f); + mode->VTotal = mode->CrtcVTotal = + (R128_BIOS16(j+15) & 0x07ff)+1; + xf86ErrorF("%ix%i [pclk %.1f MHz]\n", + mode->CrtcHDisplay,mode->CrtcVDisplay, + (float)mode->Clock/1000); + } return MODE_OK; } } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, + "Mode rejected for FP %ix%i [pclk: %.1f] " + "(not listed in VBIOS)\n", + mode->CrtcHDisplay, mode->CrtcVDisplay, + (float)mode->Clock / 1000); return MODE_NOMODE; } @@ -3714,7 +3663,7 @@ static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on) lvds_gen_cntl |= R128_LVDS_DISPLAY_DIS; OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); usleep(10); - lvds_gen_cntl &= ~(R128_LVDS_ON | R128_LVDS_EN | R128_LVDS_BLON + lvds_gen_cntl &= ~(R128_LVDS_ON | R128_LVDS_EN | R128_LVDS_BLON | R128_LVDS_DIGON); } diff --git a/src/r128_probe.h b/src/r128_probe.h index 094a9b69..746de023 100644 --- a/src/r128_probe.h +++ b/src/r128_probe.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.h,v 1.6 2002/04/06 19:06:06 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.h,v 1.7 2003/10/30 17:36:58 tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -69,7 +69,7 @@ extern void R128LeaveVT FunctionPrototype((int, int)); extern void R128FreeScreen FunctionPrototype((int, int)); -extern int R128ValidMode +extern ModeStatus R128ValidMode FunctionPrototype((int, DisplayModePtr, Bool, int)); diff --git a/src/r128_reg.h b/src/r128_reg.h index 3968bd57..8f486e8c 100644 --- a/src/r128_reg.h +++ b/src/r128_reg.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h,v 1.15 2002/12/16 16:19:11 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h,v 1.17 2003/09/28 20:15:54 alanh Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -935,6 +935,7 @@ #define R128_TRAIL_X_SUB 0x1620 #define R128_VCLK_ECP_CNTL 0x0008 /* PLL */ +# define R128_ECP_DIV_MASK (3 << 8) #define R128_VENDOR_ID 0x0f00 /* PCI */ #define R128_VGA_DDA_CONFIG 0x02e8 #define R128_VGA_DDA_ON_OFF 0x02ec @@ -1287,8 +1288,8 @@ # define R128_DATATYPE_Y8 (8 << 16) # define R128_DATATYPE_RGB8 (9 << 16) # define R128_DATATYPE_CI16 (10 << 16) -# define R128_DATATYPE_YUV422 (11 << 16) -# define R128_DATATYPE_YUV422_2 (12 << 16) +# define R128_DATATYPE_YVYU422 (11 << 16) +# define R128_DATATYPE_VYUY422 (12 << 16) # define R128_DATATYPE_AYUV444 (14 << 16) # define R128_DATATYPE_ARGB4444 (15 << 16) # define R128_PALLETE_EITHER (0 << 20) diff --git a/src/r128_sarea.h b/src/r128_sarea.h index 2ac863fb..d583091a 100644 --- a/src/r128_sarea.h +++ b/src/r128_sarea.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h,v 1.7 2002/02/16 21:26:35 herrb Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h,v 1.9 2003/10/03 20:11:11 herrb Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -149,12 +149,6 @@ typedef struct { } r128_texture_regs_t; typedef struct { - unsigned char next, prev; /* indices to form a circular LRU */ - unsigned char in_use; /* owned by a client, or free? */ - int age; /* tracked by clients to update local LRU's */ -} r128_tex_region_t; - -typedef struct { /* The channel for communication of state information to the kernel * on firing a vertex buffer. */ @@ -164,12 +158,10 @@ typedef struct { unsigned int vertsize; unsigned int vc_format; -#ifdef XF86DRI /* The current cliprects, or a subset thereof. */ XF86DRIClipRectRec boxes[R128_NR_SAREA_CLIPRECTS]; unsigned int nbox; -#endif /* Counters for throttling of rendering clients. */ @@ -191,11 +183,13 @@ typedef struct { * else's - simply eject them all in LRU order. */ /* Last elt is sentinal */ - r128_tex_region_t texList[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1]; + drmTextureRegion texList[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1]; /* last time texture was uploaded */ - int texAge[R128_NR_TEX_HEAPS]; + unsigned int texAge[R128_NR_TEX_HEAPS]; int ctxOwner; /* last context to upload state */ + int pfAllowPageFlip; /* set by the 2d driver, read by the client */ + int pfCurrentPage; /* set by kernel, read by others */ } R128SAREAPriv, *R128SAREAPrivPtr; #endif diff --git a/src/r128_video.c b/src/r128_video.c index 119971fd..912fceee 100644 --- a/src/r128_video.c +++ b/src/r128_video.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_video.c,v 1.26 2003/02/19 01:19:41 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_video.c,v 1.31 2003/11/10 18:41:21 tsi Exp $ */ #include "r128.h" #include "r128_reg.h" @@ -23,10 +23,6 @@ #define TIMER_MASK (OFF_TIMER | FREE_TIMER) -#ifndef XvExtension -void R128InitVideo(ScreenPtr pScreen) {} -#else - static XF86VideoAdaptorPtr R128SetupImageVideo(ScreenPtr); static int R128SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); static int R128GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); @@ -61,19 +57,30 @@ typedef struct { CARD32 videoStatus; Time offTime; Time freeTime; + int ecp_div; } R128PortPrivRec, *R128PortPrivPtr; +static void R128ECP(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + int dot_clock = info->ModeReg.dot_clock_freq; + + if (dot_clock < 12500) pPriv->ecp_div = 0; + else if (dot_clock < 25000) pPriv->ecp_div = 1; + else pPriv->ecp_div = 2; + + OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, pPriv->ecp_div<<8, ~R128_ECP_DIV_MASK); +} void R128InitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - R128InfoPtr info = R128PTR(pScrn); XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; XF86VideoAdaptorPtr newAdaptor = NULL; int num_adaptors; - if(info->accel && info->accel->FillSolidRects) - newAdaptor = R128SetupImageVideo(pScreen); + newAdaptor = R128SetupImageVideo(pScreen); num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); @@ -196,6 +203,7 @@ R128AllocAdaptor(ScrnInfoPtr pScrn) pPriv->brightness = 0; pPriv->saturation = 16; pPriv->currentBuffer = 0; + R128ECP(pScrn, pPriv); return adapt; } @@ -237,134 +245,13 @@ R128SetupImageVideo(ScreenPtr pScreen) info->adaptor = adapt; pPriv = (R128PortPrivPtr)(adapt->pPortPrivates[0].ptr); - REGION_INIT(pScreen, &(pPriv->clip), NullBox, 0); + REGION_NULL(pScreen, &(pPriv->clip)); R128ResetVideo(pScrn); return adapt; } -/* I really should stick this in miregion */ -static Bool -RegionsEqual(RegionPtr A, RegionPtr B) -{ - int *dataA, *dataB; - int num; - - num = REGION_NUM_RECTS(A); - if(num != REGION_NUM_RECTS(B)) - return FALSE; - - if((A->extents.x1 != B->extents.x1) || - (A->extents.x2 != B->extents.x2) || - (A->extents.y1 != B->extents.y1) || - (A->extents.y2 != B->extents.y2)) - return FALSE; - - dataA = (pointer)REGION_RECTS(A); - dataB = (pointer)REGION_RECTS(B); - - while(num--) { - if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) - return FALSE; - dataA += 2; - dataB += 2; - } - - return TRUE; -} - - -/* R128ClipVideo - - - Takes the dst box in standard X BoxRec form (top and left - edges inclusive, bottom and right exclusive). The new dst - box is returned. The source boundaries are given (xa, ya - inclusive, xb, yb exclusive) and returned are the new source - boundaries in 16.16 fixed point. -*/ - -#define DummyScreen screenInfo.screens[0] - -static Bool -R128ClipVideo( - BoxPtr dst, - INT32 *xa, - INT32 *xb, - INT32 *ya, - INT32 *yb, - RegionPtr reg, - INT32 width, - INT32 height -){ - INT32 vscale, hscale, delta; - BoxPtr extents = REGION_EXTENTS(DummyScreen, reg); - int diff; - - hscale = ((*xb - *xa) << 16) / (dst->x2 - dst->x1); - vscale = ((*yb - *ya) << 16) / (dst->y2 - dst->y1); - - *xa <<= 16; *xb <<= 16; - *ya <<= 16; *yb <<= 16; - - diff = extents->x1 - dst->x1; - if(diff > 0) { - dst->x1 = extents->x1; - *xa += diff * hscale; - } - diff = dst->x2 - extents->x2; - if(diff > 0) { - dst->x2 = extents->x2; - *xb -= diff * hscale; - } - diff = extents->y1 - dst->y1; - if(diff > 0) { - dst->y1 = extents->y1; - *ya += diff * vscale; - } - diff = dst->y2 - extents->y2; - if(diff > 0) { - dst->y2 = extents->y2; - *yb -= diff * vscale; - } - - if(*xa < 0) { - diff = (- *xa + hscale - 1)/ hscale; - dst->x1 += diff; - *xa += diff * hscale; - } - delta = *xb - (width << 16); - if(delta > 0) { - diff = (delta + hscale - 1)/ hscale; - dst->x2 -= diff; - *xb -= diff * hscale; - } - if(*xa >= *xb) return FALSE; - - if(*ya < 0) { - diff = (- *ya + vscale - 1)/ vscale; - dst->y1 += diff; - *ya += diff * vscale; - } - delta = *yb - (height << 16); - if(delta > 0) { - diff = (delta + vscale - 1)/ vscale; - dst->y2 -= diff; - *yb -= diff * vscale; - } - if(*ya >= *yb) return FALSE; - - if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) || - (dst->y1 != extents->y1) || (dst->y2 != extents->y2)) - { - RegionRec clipReg; - REGION_INIT(DummyScreen, &clipReg, dst, 1); - REGION_INTERSECT(DummyScreen, reg, reg, &clipReg); - REGION_UNINIT(DummyScreen, &clipReg); - } - return TRUE; -} - static void R128StopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) { @@ -377,8 +264,6 @@ R128StopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) if(cleanup) { if(pPriv->videoStatus & CLIENT_VIDEO_ON) { OUTREG(R128_OV0_SCALE_CNTL, 0); - if (info->cursor_start) - xf86ForceHWCursor (pScrn->pScreen, FALSE); } if(pPriv->linear) { xf86FreeOffscreenLinear(pPriv->linear); @@ -545,7 +430,7 @@ R128DMA( return FALSE; } - /* Copy parts of the block into buffers and fire them */ + /* Copy parts of the block into buffers and fire them */ dstpassbytes = hpass*dstPitch; dstPitch /= 8; @@ -564,7 +449,7 @@ R128DMA( } else { int count = hpass; while(count--) { - memcpy(buf, src, w); + memcpy(buf, src, w); src += srcPitch; buf += w; } @@ -728,12 +613,15 @@ R128DisplayVideo422( ){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; + R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; int v_inc, h_inc, step_by, tmp; int p1_h_accum_init, p23_h_accum_init; int p1_v_accum_init; + R128ECP(pScrn, pPriv); + v_inc = (src_h << 20) / drw_h; - h_inc = (src_w << 12) / drw_w; + h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w; step_by = 1; while(h_inc >= (2 << 12)) { @@ -799,12 +687,13 @@ R128DisplayVideo420( ){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; + R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; int v_inc, h_inc, step_by, tmp, leftUV; int p1_h_accum_init, p23_h_accum_init; int p1_v_accum_init, p23_v_accum_init; v_inc = (src_h << 20) / drw_h; - h_inc = (src_w << 12) / drw_w; + h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w; step_by = 1; while(h_inc >= (2 << 12)) { @@ -881,7 +770,7 @@ R128PutImage( R128InfoPtr info = R128PTR(pScrn); R128PortPrivPtr pPriv = (R128PortPrivPtr)data; INT32 xa, xb, ya, yb; - int pitch, new_size, offset, s1offset, s2offset, s3offset; + int new_size, offset, s1offset, s2offset, s3offset; int srcPitch, srcPitch2, dstPitch; int d1line, d2line, d3line, d1offset, d2offset, d3offset; int top, left, npixels, nlines, bpp; @@ -927,7 +816,8 @@ R128PutImage( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; - if(!R128ClipVideo(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height)) + if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, + clipBoxes, width, height)) return Success; dstBox.x1 -= pScrn->frameX0; @@ -936,7 +826,6 @@ R128PutImage( dstBox.y2 -= pScrn->frameY0; bpp = pScrn->bitsPerPixel >> 3; - pitch = bpp * pScrn->displayWidth; switch(id) { case FOURCC_YV12: @@ -1030,13 +919,10 @@ R128PutImage( #endif /* update cliplist */ - if(!RegionsEqual(&pPriv->clip, clipBoxes)) { - REGION_COPY(pScreen, &pPriv->clip, clipBoxes); + if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { + REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); /* draw these */ - (*info->accel->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, - (CARD32)~0, - REGION_NUM_RECTS(clipBoxes), - REGION_RECTS(clipBoxes)); + xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); } @@ -1055,8 +941,6 @@ R128PutImage( break; } - if (info->cursor_start && !(pPriv->videoStatus & CLIENT_VIDEO_ON)) - xf86ForceHWCursor (pScrn->pScreen, TRUE); pPriv->videoStatus = CLIENT_VIDEO_ON; info->VideoTimerCallback = R128VideoTimerCallback; @@ -1118,8 +1002,6 @@ R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now) if(pPriv->offTime < now) { unsigned char *R128MMIO = info->MMIO; OUTREG(R128_OV0_SCALE_CNTL, 0); - if (info->cursor_start && pPriv->videoStatus & CLIENT_VIDEO_ON) - xf86ForceHWCursor (pScrn->pScreen, FALSE); pPriv->videoStatus = FREE_TIMER; pPriv->freeTime = now + FREE_DELAY; } @@ -1129,8 +1011,6 @@ R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now) xf86FreeOffscreenLinear(pPriv->linear); pPriv->linear = NULL; } - if (info->cursor_start && pPriv->videoStatus & CLIENT_VIDEO_ON) - xf86ForceHWCursor (pScrn->pScreen, FALSE); pPriv->videoStatus = 0; info->VideoTimerCallback = NULL; } @@ -1138,6 +1018,3 @@ R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now) } else /* shouldn't get here */ info->VideoTimerCallback = NULL; } - - -#endif /* !XvExtension */ diff --git a/src/radeon.h b/src/radeon.h index 81e0db7b..ded0bde1 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h,v 1.37 2003/02/23 23:28:48 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h,v 1.44 2003/11/10 18:41:21 tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -72,8 +72,8 @@ #define RADEON_MMIOSIZE 0x80000 #define RADEON_VBIOS_SIZE 0x00010000 -#define RADEON_USE_RMX 0x80000000 /* mode flag for using RMX - * Need to comfirm this is not used +#define RADEON_USE_RMX 0x80000000 /* mode flag for using RMX + * Need to comfirm this is not used * for something else. */ @@ -94,20 +94,6 @@ do { \ #define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate) typedef struct { - /* All values in XCLKS */ - int ML; /* Memory Read Latency */ - int MB; /* Memory Burst Length */ - int Trcd; /* RAS to CAS delay */ - int Trp; /* RAS percentage */ - int Twr; /* Write Recovery */ - int CL; /* CAS Latency */ - int Tr2w; /* Read to Write Delay */ - int Rloop; /* Loop Latency */ - int Rloop_fudge; /* Add to ML to get Rloop */ - char *name; -} RADEONRAMRec, *RADEONRAMPtr; - -typedef struct { /* Common registers */ CARD32 ovr_clr; CARD32 ovr_wid_left_right; @@ -123,7 +109,7 @@ typedef struct { CARD32 cap1_trig_cntl; CARD32 bus_cntl; CARD32 surface_cntl; - + CARD32 bios_5_scratch; /* Other registers to save for VT switches */ CARD32 dp_datatype; CARD32 rbbm_soft_reset; @@ -142,6 +128,9 @@ typedef struct { CARD32 crtc_offset; CARD32 crtc_offset_cntl; CARD32 crtc_pitch; + CARD32 disp_merge_cntl; + CARD32 grph_buffer_cntl; + CARD32 crtc_more_cntl; /* CRTC2 registers */ CARD32 crtc2_gen_cntl; @@ -149,6 +138,8 @@ typedef struct { CARD32 dac2_cntl; CARD32 disp_output_cntl; CARD32 disp_hw_debug; + CARD32 disp2_merge_cntl; + CARD32 grph2_buffer_cntl; CARD32 crtc2_h_total_disp; CARD32 crtc2_h_sync_strt_wid; CARD32 crtc2_v_total_disp; @@ -171,6 +162,7 @@ typedef struct { CARD32 lvds_gen_cntl; CARD32 lvds_pll_cntl; CARD32 tmds_pll_cntl; + CARD32 tmds_transmitter_cntl; /* Computed values for PLL */ CARD32 dot_clock_freq; @@ -179,8 +171,8 @@ typedef struct { int post_div; /* PLL registers */ - CARD32 ppll_ref_div; - CARD32 ppll_div_3; + unsigned ppll_ref_div; + unsigned ppll_div_3; CARD32 htotal_cntl; /* Computed values for PLL2 */ @@ -245,20 +237,27 @@ typedef enum { typedef enum { CHIP_FAMILY_UNKNOW, CHIP_FAMILY_LEGACY, - CHIP_FAMILY_R128, - CHIP_FAMILY_M3, CHIP_FAMILY_RADEON, - CHIP_FAMILY_VE, - CHIP_FAMILY_M6, + CHIP_FAMILY_RV100, + CHIP_FAMILY_RS100, /* U1 (IGP320M) or A3 (IGP320)*/ CHIP_FAMILY_RV200, - CHIP_FAMILY_M7, + CHIP_FAMILY_RS200, /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350), RS250 (IGP 7000) */ CHIP_FAMILY_R200, CHIP_FAMILY_RV250, - CHIP_FAMILY_M9, - CHIP_FAMILY_R300 + CHIP_FAMILY_RS300, /* Radeon 9000 IGP */ + CHIP_FAMILY_RV280, + CHIP_FAMILY_R300, + CHIP_FAMILY_R350, + CHIP_FAMILY_RV350, + CHIP_FAMILY_LAST } RADEONChipFamily; typedef struct { + CARD32 freq; + CARD32 value; +}RADEONTMDSPll; + +typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; PCITAG PciTag; @@ -285,10 +284,10 @@ typedef struct { RADEONDDCType DDCType; RADEONConnectorType ConnectorType; Bool HasCRTC2; /* All cards except original Radeon */ + Bool IsMobility; /* Mobile chips for laptops */ + Bool IsIGP; /* IGP chips */ Bool IsSecondary; /* Second Screen */ Bool IsSwitching; /* Flag for switching mode */ - Bool IsDell; /* Dell OEM VE card */ - int DellType; Bool Clone; /* Force second head to clone primary*/ RADEONMonitorType CloneType; RADEONDDCType CloneDDCType; @@ -299,7 +298,7 @@ typedef struct { Bool OverlayOnCRTC2; Bool PanelOff; /* Force panel (LCD/DFP) off */ int FPBIOSstart; /* Start of the flat panel info */ - Bool ddc_mode; /* Validate mode by matching exactly + Bool ddc_mode; /* Validate mode by matching exactly * the modes supported in DDC data */ Bool R300CGWorkaround; @@ -315,7 +314,10 @@ typedef struct { int VBlank; int PanelPwrDly; int DotClock; - + int RefDivider; + int FeedbackDivider; + int PostDivider; + Bool UseBiosDividers; /* EDID data using DDC interface */ Bool ddc_bios; Bool ddc1; @@ -324,7 +326,12 @@ typedef struct { CARD32 DDCReg; RADEONPLLRec pll; - RADEONRAMPtr ram; + RADEONTMDSPll tmds_pll[4]; + int RamWidth; + float sclk; /* in MHz */ + float mclk; /* in MHz */ + Bool IsDDR; + int DispPriority; RADEONSaveRec SavedReg; /* Original (text) mode */ RADEONSaveRec ModeReg; /* Current mode */ @@ -420,9 +427,9 @@ typedef struct { Bool have3DWindows; /* Are there any 3d clients? */ int drmMinor; - drmSize agpSize; + drmSize gartSize; drmHandle agpMemHandle; /* Handle from drmAgpAlloc */ - unsigned long agpOffset; + unsigned long gartOffset; unsigned char *AGP; /* Map */ int agpMode; int agpFastWrite; @@ -437,20 +444,20 @@ typedef struct { int CPusecTimeout; /* CP timeout in usecs */ /* CP ring buffer data */ - unsigned long ringStart; /* Offset into AGP space */ + unsigned long ringStart; /* Offset into GART space */ drmHandle ringHandle; /* Handle from drmAddMap */ drmSize ringMapSize; /* Size of map */ int ringSize; /* Size of ring (in MB) */ unsigned char *ring; /* Map */ int ringSizeLog2QW; - unsigned long ringReadOffset; /* Offset into AGP space */ + unsigned long ringReadOffset; /* Offset into GART space */ drmHandle ringReadPtrHandle; /* Handle from drmAddMap */ drmSize ringReadMapSize; /* Size of map */ unsigned char *ringReadPtr; /* Map */ /* CP vertex/indirect buffer data */ - unsigned long bufStart; /* Offset into AGP space */ + unsigned long bufStart; /* Offset into GART space */ drmHandle bufHandle; /* Handle from drmAddMap */ drmSize bufMapSize; /* Size of map */ int bufSize; /* Size of buffers (in MB) */ @@ -458,13 +465,13 @@ typedef struct { int bufNumBufs; /* Number of buffers */ drmBufMapPtr buffers; /* Buffer map */ - /* CP AGP Texture data */ - unsigned long agpTexStart; /* Offset into AGP space */ - drmHandle agpTexHandle; /* Handle from drmAddMap */ - drmSize agpTexMapSize; /* Size of map */ - int agpTexSize; /* Size of AGP tex space (in MB) */ - unsigned char *agpTex; /* Map */ - int log2AGPTexGran; + /* CP GART Texture data */ + unsigned long gartTexStart; /* Offset into GART space */ + drmHandle gartTexHandle; /* Handle from drmAddMap */ + drmSize gartTexMapSize; /* Size of map */ + int gartTexSize; /* Size of GART tex space (in MB) */ + unsigned char *gartTex; /* Map */ + int log2GARTTexGran; /* CP accleration */ drmBufPtr indirectBuffer; @@ -566,12 +573,13 @@ extern Bool RADEONDGAInit(ScreenPtr pScreen); extern int RADEONMinBits(int val); extern void RADEONInitVideo(ScreenPtr pScreen); - +extern void RADEONResetVideo(ScrnInfoPtr pScrn); extern void R300CGWorkaround(ScrnInfoPtr pScrn); #ifdef XF86DRI extern Bool RADEONDRIScreenInit(ScreenPtr pScreen); extern void RADEONDRICloseScreen(ScreenPtr pScreen); +extern void RADEONDRIResume(ScreenPtr pScreen); extern Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen); extern drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn); @@ -667,7 +675,7 @@ do { \ "ADVANCE_RING() start: %d used: %d count: %d\n", \ info->indirectStart, \ info->indirectBuffer->used, \ - __count * sizeof(CARD32)); \ + __count * (int)sizeof(CARD32)); \ } \ info->indirectBuffer->used += __count * (int)sizeof(CARD32); \ } while (0) diff --git a/src/radeon_accel.c b/src/radeon_accel.c index 1d9fbcf3..49690fb3 100644 --- a/src/radeon_accel.c +++ b/src/radeon_accel.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c,v 1.32 2003/01/17 19:54:03 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c,v 1.36 2003/11/10 18:41:22 tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -207,7 +207,9 @@ void RADEONEngineReset(ScrnInfoPtr pScrn) host_path_cntl = INREG(RADEON_HOST_PATH_CNTL); rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); - if (info->ChipFamily == CHIP_FAMILY_R300) { + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) { CARD32 tmp; OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | @@ -243,7 +245,9 @@ void RADEONEngineReset(ScrnInfoPtr pScrn) INREG(RADEON_HOST_PATH_CNTL); OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl); - if (info->ChipFamily != CHIP_FAMILY_R300) + if ((info->ChipFamily != CHIP_FAMILY_R300) && + (info->ChipFamily != CHIP_FAMILY_R350) && + (info->ChipFamily != CHIP_FAMILY_RV350)) OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); @@ -271,13 +275,15 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) */ /* Turn of all automatic flushing - we'll do it all */ - if (info->ChipFamily != CHIP_FAMILY_R300) + if ((info->ChipFamily != CHIP_FAMILY_R300) && + (info->ChipFamily != CHIP_FAMILY_R350) && + (info->ChipFamily != CHIP_FAMILY_RV350)) OUTREG(RADEON_RB2D_DSTCACHE_MODE, 0); pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6; RADEONWaitForFifo(pScrn, 1); - OUTREG(RADEON_DEFAULT_OFFSET, ((INREG(RADEON_DEFAULT_OFFSET) & 0xC0000000) + OUTREG(RADEON_DEFAULT_OFFSET, ((INREG(RADEON_DISPLAY_BASE_ADDR) >> 10) | (pitch64 << 22))); RADEONWaitForFifo(pScrn, 1); @@ -329,7 +335,7 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) #endif { OUTREG(RADEON_MC_FB_LOCATION, 0xffff0000); - OUTREG(RADEON_MC_AGP_LOCATION, 0xfffff000); + OUTREG(RADEON_MC_AGP_LOCATION, 0xfffff000); } #endif @@ -413,7 +419,7 @@ int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info) stop.flush = 1; stop.idle = 1; - ret = drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP, &stop, + ret = drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP, &stop, sizeof(drmRadeonCPStop)); if (ret == 0) { @@ -423,10 +429,10 @@ int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info) } stop.flush = 0; - + i = 0; do { - ret = drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP, &stop, + ret = drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP, &stop, sizeof(drmRadeonCPStop)); } while (ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY); @@ -493,7 +499,7 @@ drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn) buf->used = 0; if (RADEON_VERBOSE) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - " GetBuffer returning %d %08x\n", + " GetBuffer returning %d %p\n", buf->idx, buf->address); } return buf; diff --git a/src/radeon_accelfuncs.c b/src/radeon_accelfuncs.c index 06dcfd63..0090671d 100644 --- a/src/radeon_accelfuncs.c +++ b/src/radeon_accelfuncs.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c,v 1.6 2003/01/29 18:06:06 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accelfuncs.c,v 1.8 2003/11/03 05:11:05 tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -178,21 +178,10 @@ FUNC_NAME(RADEONRestoreAccelState)(ScrnInfoPtr pScrn) #ifdef ACCEL_MMIO CARD32 pitch64; - RADEONEntPtr pRADEONEnt; - DevUnion *pPriv; - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; -#if 0 - /* Not working yet */ - if (pRADEONEnt->IsDRIEnabled) { - RADEONInfoPtr info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn); - RADEONCP_TO_MMIO(pRADEONEnt->pPrimaryScrn, info0); - } -#endif pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6; - OUTREG(RADEON_DEFAULT_OFFSET, ((pScrn->fbOffset>>10) | + OUTREG(RADEON_DEFAULT_OFFSET, (((INREG(RADEON_DISPLAY_BASE_ADDR) + pScrn->fbOffset) >> 10) | (pitch64 << 22))); /* FIXME: May need to restore other things, like BKGD_CLK FG_CLK... */ @@ -1315,22 +1304,12 @@ FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a) | HARDWARE_CLIP_MONO_8x8_FILL | HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY); - if (xf86IsEntityShared(pScrn->entityList[0])) { - DevUnion *pPriv; - RADEONEntPtr pRADEONEnt; - - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; - + if (xf86IsEntityShared(info->pEnt->index)) { /* If there are more than one devices sharing this entity, we * have to assign this call back, otherwise the XAA will be * disabled */ -#ifdef ACCEL_MMIO - if (pRADEONEnt->HasSecondary || pRADEONEnt->BypassSecondary) -#else /* ACCEL_CP */ - if (!info->IsSecondary && xf86IsEntityShared(pScrn->entityList[0])) -#endif + if (xf86GetNumEntityInstances(info->pEnt->index) > 1) a->RestoreAccelState = FUNC_NAME(RADEONRestoreAccelState); } diff --git a/src/radeon_common.h b/src/radeon_common.h index bbc80a79..d9261234 100644 --- a/src/radeon_common.h +++ b/src/radeon_common.h @@ -31,7 +31,7 @@ * Converted to common header format: * Jens Owen <jens@tungstengraphics.com> * - * $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v 1.1 2002/10/30 12:52:13 alanh Exp $ + * $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v 1.4 2003/11/10 18:41:22 tsi Exp $ * */ @@ -70,6 +70,7 @@ #define DRM_RADEON_INIT_HEAP 0x15 #define DRM_RADEON_IRQ_EMIT 0x16 #define DRM_RADEON_IRQ_WAIT 0x17 +#define DRM_RADEON_CP_RESUME 0x18 #define DRM_RADEON_MAX_DRM_COMMAND_INDEX 0x39 @@ -94,7 +95,7 @@ typedef struct { unsigned long sarea_priv_offset; int is_pci; int cp_mode; - int agp_size; + int gart_size; int ring_size; int usec_timeout; @@ -109,7 +110,7 @@ typedef struct { unsigned long ring_offset; unsigned long ring_rptr_offset; unsigned long buffers_offset; - unsigned long agp_textures_offset; + unsigned long gart_textures_offset; } drmRadeonInit; typedef struct { @@ -169,7 +170,7 @@ typedef struct { #define RADEON_MAX_TEXTURE_UNITS 3 -/* Layout matches drm_radeon_state_t in linux drm_radeon.h. +/* Layout matches drm_radeon_state_t in linux drm_radeon.h. */ typedef struct { struct { @@ -232,7 +233,7 @@ typedef struct { unsigned int pp_border_color; } texture[RADEON_MAX_TEXTURE_UNITS]; struct { - unsigned int se_zbias_factor; + unsigned int se_zbias_factor; unsigned int se_zbias_constant; } zbias; unsigned int dirty; @@ -342,7 +343,22 @@ typedef struct { #define R200_EMIT_SE_VTX_STATE_CNTL 58 /* cst/1 */ #define R200_EMIT_RE_POINTSIZE 59 /* cst/1 */ #define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60 /* cst/4 */ -#define RADEON_MAX_STATE_PACKETS 61 +#define R200_EMIT_PP_CUBIC_FACES_0 61 +#define R200_EMIT_PP_CUBIC_OFFSETS_0 62 +#define R200_EMIT_PP_CUBIC_FACES_1 63 +#define R200_EMIT_PP_CUBIC_OFFSETS_1 64 +#define R200_EMIT_PP_CUBIC_FACES_2 65 +#define R200_EMIT_PP_CUBIC_OFFSETS_2 66 +#define R200_EMIT_PP_CUBIC_FACES_3 67 +#define R200_EMIT_PP_CUBIC_OFFSETS_3 68 +#define R200_EMIT_PP_CUBIC_FACES_4 69 +#define R200_EMIT_PP_CUBIC_OFFSETS_4 70 +#define R200_EMIT_PP_CUBIC_FACES_5 71 +#define R200_EMIT_PP_CUBIC_OFFSETS_5 72 +#define RADEON_EMIT_PP_TEX_SIZE_0 73 +#define RADEON_EMIT_PP_TEX_SIZE_1 74 +#define RADEON_EMIT_PP_TEX_SIZE_2 75 +#define RADEON_MAX_STATE_PACKETS 76 /* Commands understood by cmd_buffer ioctl. More can be added but @@ -359,23 +375,23 @@ typedef struct { typedef union { int i; - struct { + struct { unsigned char cmd_type, pad0, pad1, pad2; } header; - struct { + struct { unsigned char cmd_type, packet_id, pad0, pad1; } packet; - struct { - unsigned char cmd_type, offset, stride, count; + struct { + unsigned char cmd_type, offset, stride, count; } scalars; - struct { - unsigned char cmd_type, offset, stride, count; + struct { + unsigned char cmd_type, offset, stride, count; } vectors; - struct { - unsigned char cmd_type, buf_idx, pad0, pad1; + struct { + unsigned char cmd_type, buf_idx, pad0, pad1; } dma; - struct { - unsigned char cmd_type, flags, pad0, pad1; + struct { + unsigned char cmd_type, flags, pad0, pad1; } wait; } drmRadeonCmdHeader; @@ -389,22 +405,22 @@ typedef struct drm_radeon_getparam { int *value; } drmRadeonGetParam; -#define RADEON_PARAM_AGP_BUFFER_OFFSET 1 -#define RADEON_PARAM_LAST_FRAME 2 -#define RADEON_PARAM_LAST_DISPATCH 3 -#define RADEON_PARAM_LAST_CLEAR 4 -#define RADEON_PARAM_IRQ_NR 5 -#define RADEON_PARAM_AGP_BASE 6 +#define RADEON_PARAM_GART_BUFFER_OFFSET 1 +#define RADEON_PARAM_LAST_FRAME 2 +#define RADEON_PARAM_LAST_DISPATCH 3 +#define RADEON_PARAM_LAST_CLEAR 4 +#define RADEON_PARAM_IRQ_NR 5 +#define RADEON_PARAM_GART_BASE 6 -#define RADEON_MEM_REGION_AGP 1 -#define RADEON_MEM_REGION_FB 2 +#define RADEON_MEM_REGION_GART 1 +#define RADEON_MEM_REGION_FB 2 typedef struct drm_radeon_mem_alloc { int region; int alignment; int size; - int *region_offset; /* offset from start of fb or agp */ + int *region_offset; /* offset from start of fb or GART */ } drmRadeonMemAlloc; typedef struct drm_radeon_mem_free { @@ -415,7 +431,7 @@ typedef struct drm_radeon_mem_free { typedef struct drm_radeon_mem_init_heap { int region; int size; - int start; + int start; } drmRadeonMemInitHeap; /* 1.6: Userspace can request & wait on irq's: diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c index 868703d9..e63005e8 100644 --- a/src/radeon_cursor.c +++ b/src/radeon_cursor.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c,v 1.23 2003/02/24 20:34:55 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c,v 1.26 2003/11/10 18:41:22 tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -64,7 +64,7 @@ static CARD32 mono_cursor_color[] = { #define CURSOR_HEIGHT 64 /* - * The cursor bits are always 32bpp. On MSBFirst busses, + * The cursor bits are always 32bpp. On MSBFirst buses, * configure byte swapping to swap 32 bit units when writing * the cursor image. Byte swapping must always be returned * to its previous value before returning. @@ -103,16 +103,16 @@ static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) if (info->cursor_argb) return; #endif - + fg |= 0xff000000; bg |= 0xff000000; - + /* Don't recolour the image if we don't have to. */ if (fg == info->cursor_fg && bg == info->cursor_bg) return; CURSOR_SWAPPING_START(); - + /* 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 @@ -285,7 +285,7 @@ static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) *d++ = mono_cursor_color[chunk & 3]; } CURSOR_SWAPPING_END(); - + info->cursor_bg = mono_cursor_color[2]; info->cursor_fg = mono_cursor_color[3]; @@ -362,7 +362,7 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) if (!image) return; /* XXX can't happen */ - + if (!info->IsSecondary) { save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20); save1 |= (CARD32) (2 << 20); @@ -370,7 +370,7 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) } if (info->IsSecondary || info->Clone) { - save2 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20); + save2 = INREG(RADEON_CRTC2_GEN_CNTL) & ~(CARD32) (3 << 20); save2 |= (CARD32) (2 << 20); OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN); } @@ -378,7 +378,7 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) #ifdef ARGB_CURSOR info->cursor_argb = TRUE; #endif - + CURSOR_SWAPPING_START(); w = pCurs->bits->width; @@ -413,7 +413,7 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) } #endif - + /* Initialize hardware cursor support. */ Bool RADEONCursorInit(ScreenPtr pScreen) @@ -434,7 +434,7 @@ Bool RADEONCursorInit(ScreenPtr pScreen) cursor->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK #if X_BYTE_ORDER == X_BIG_ENDIAN - /* this is a lie -- + /* this is a lie -- * HARDWARE_CURSOR_BIT_ORDER_MSBFIRST * actually inverts the bit order, so * this switches to LSBFIRST @@ -472,7 +472,7 @@ Bool RADEONCursorInit(ScreenPtr pScreen) "Hardware cursor disabled" " due to insufficient offscreen memory\n"); } else { - info->cursor_start = RADEON_ALIGN((fbarea->box.x1 + + info->cursor_start = RADEON_ALIGN((fbarea->box.x1 + fbarea->box.y1 * width) * info->CurrentLayout.pixel_bytes, 256); diff --git a/src/radeon_dga.c b/src/radeon_dga.c index a0fe9389..525abba3 100644 --- a/src/radeon_dga.c +++ b/src/radeon_dga.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dga.c,v 1.11 2002/09/18 18:14:58 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dga.c,v 1.12 2003/11/10 18:41:22 tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -97,7 +97,7 @@ SECOND_PASS: pitch = secondPitch; if (!(newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec)))) - break; + break; modes = newmodes; currentMode = modes + *num; @@ -106,7 +106,7 @@ SECOND_PASS: currentMode->flags = DGA_CONCURRENT_ACCESS; if (pixmap) - currentMode->flags |= DGA_PIXMAP_AVAILABLE; + currentMode->flags |= DGA_PIXMAP_AVAILABLE; if (info->accel) { if (info->accel->SetupForSolidFill && @@ -123,7 +123,7 @@ SECOND_PASS: if (pMode->Flags & V_DBLSCAN) currentMode->flags |= DGA_DOUBLESCAN; if (pMode->Flags & V_INTERLACE) - currentMode->flags |= DGA_INTERLACED; + currentMode->flags |= DGA_INTERLACED; currentMode->byteOrder = pScrn->imageByteOrder; currentMode->depth = depth; @@ -264,16 +264,16 @@ static Bool RADEON_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode) RADEONSwitchMode(indx, pScrn->currentMode, 0); #ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled) { RADEONCP_STOP(pScrn, info); - } + } #endif if (info->accelOn) RADEONEngineInit(pScrn); #ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled) { RADEONCP_START(pScrn, info); - } + } #endif RADEONAdjustFrame(indx, 0, 0, 0); info->DGAactive = FALSE; @@ -297,16 +297,16 @@ static Bool RADEON_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode) RADEONSwitchMode(indx, pMode->mode, 0); #ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled) { RADEONCP_STOP(pScrn, info); - } + } #endif if (info->accelOn) RADEONEngineInit(pScrn); #ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled) { RADEONCP_START(pScrn, info); - } + } #endif } diff --git a/src/radeon_dri.c b/src/radeon_dri.c index 96787f12..db250098 100644 --- a/src/radeon_dri.c +++ b/src/radeon_dri.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v 1.32.2.1 2003/05/06 23:21:38 daenzer Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v 1.40 2003/11/10 18:41:22 tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, * VA Linux Systems Inc., Fremont, California. @@ -45,8 +45,8 @@ /* X and server generic header files */ #include "xf86.h" -#include "windowstr.h" #include "xf86PciInfo.h" +#include "windowstr.h" #include "shadowfb.h" @@ -173,9 +173,9 @@ static Bool RADEONInitVisualConfigs(ScreenPtr pScreen) pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; if (accum) { - pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT; + pConfigs[i].visualRating = GLX_SLOW_CONFIG; } else { - pConfigs[i].visualRating = GLX_NONE_EXT; + pConfigs[i].visualRating = GLX_NONE; } pConfigs[i].transparentPixel = GLX_NONE; pConfigs[i].transparentRed = 0; @@ -258,9 +258,9 @@ static Bool RADEONInitVisualConfigs(ScreenPtr pScreen) pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; if (accum) { - pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT; + pConfigs[i].visualRating = GLX_SLOW_CONFIG; } else { - pConfigs[i].visualRating = GLX_NONE_EXT; + pConfigs[i].visualRating = GLX_NONE; } pConfigs[i].transparentPixel = GLX_NONE; pConfigs[i].transparentRed = 0; @@ -516,7 +516,7 @@ static void RADEONScreenToScreenCopyDepth(ScrnInfoPtr pScrn, static void RADEONDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx) { /* NOOP. There's no need for the 2d driver to be clearing buffers - * for the 3d client. It knows how to do that on its own. + * for the 3d client. It knows how to do that on its own. */ } @@ -684,36 +684,40 @@ static void RADEONDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, info->accel->NeedToSync = TRUE; } -/* Initialize the AGP state. Request memory for use in AGP space, and - * initialize the Radeon registers to point to that memory. - */ -static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) +static void RADEONDRIInitGARTValues(RADEONInfoPtr info) { - unsigned char *RADEONMMIO = info->MMIO; - unsigned long mode; - unsigned int vendor, device; - unsigned long agpBase; - int ret; int s, l; - if (drmAgpAcquire(info->drmFD) < 0) { - xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] AGP not available\n"); - return FALSE; - } + info->gartOffset = 0; - /* Workaround for some hardware bugs */ - if (info->ChipFamily < CHIP_FAMILY_R200) - OUTREG(RADEON_AGP_CNTL, INREG(RADEON_AGP_CNTL) | 0x000e0000); + /* Initialize the CP ring buffer data */ + info->ringStart = info->gartOffset; + info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE; + info->ringSizeLog2QW = RADEONMinBits(info->ringSize*1024*1024/8)-1; - /* Modify the mode if the default mode - * is not appropriate for this - * particular combination of graphics - * card and AGP chipset. - */ + info->ringReadOffset = info->ringStart + info->ringMapSize; + info->ringReadMapSize = DRM_PAGE_SIZE; - mode = drmAgpGetMode(info->drmFD); /* Default mode */ - vendor = drmAgpVendorId(info->drmFD); - device = drmAgpDeviceId(info->drmFD); + /* Reserve space for vertex/indirect buffers */ + info->bufStart = info->ringReadOffset + info->ringReadMapSize; + info->bufMapSize = info->bufSize*1024*1024; + + /* Reserve the rest for GART textures */ + info->gartTexStart = info->bufStart + info->bufMapSize; + s = (info->gartSize*1024*1024 - info->gartTexStart); + l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; + info->gartTexMapSize = (s >> l) << l; + info->log2GARTTexGran = l; +} + +/* Set AGP transfer mode according to requests and constraints */ +static Bool RADEONSetAgpMode(RADEONInfoPtr info, ScreenPtr pScreen) +{ + unsigned char *RADEONMMIO = info->MMIO; + unsigned long mode = drmAgpGetMode(info->drmFD); /* Default mode */ + unsigned int vendor = drmAgpVendorId(info->drmFD); + unsigned int device = drmAgpDeviceId(info->drmFD); mode &= ~RADEON_AGP_MODE_MASK; switch (info->agpMode) { @@ -723,16 +727,9 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) } if (info->agpFastWrite) mode |= RADEON_AGP_FW_MODE; - + if ((vendor == PCI_VENDOR_AMD) && (device == PCI_CHIP_AMD761)) { - /* The combination of 761 with MOBILITY chips will lockup the - * system; however, currently there is no such a product on the - * market, so this is not yet a problem. - */ - if ((info->ChipFamily == CHIP_FAMILY_M6) || - (info->ChipFamily == CHIP_FAMILY_M7)) - return FALSE; /* Disable fast write for AMD 761 chipset, since they cause * lockups when enabled. @@ -752,46 +749,62 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) return FALSE; } - info->agpOffset = 0; + /* Workaround for some hardware bugs */ + if (info->ChipFamily < CHIP_FAMILY_R200) + OUTREG(RADEON_AGP_CNTL, INREG(RADEON_AGP_CNTL) | 0x000e0000); + + /* Modify the mode if the default mode + * is not appropriate for this + * particular combination of graphics + * card and AGP chipset. + */ + + return TRUE; +} + +/* Initialize Radeon's AGP registers */ +static void RADEONSetAgpBase(RADEONInfoPtr info) +{ + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG(RADEON_AGP_BASE, drmAgpBase(info->drmFD)); +} + +/* Initialize the AGP state. Request memory for use in AGP space, and + * initialize the Radeon registers to point to that memory. + */ +static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) +{ + int ret; + + if (drmAgpAcquire(info->drmFD) < 0) { + xf86DrvMsg(pScreen->myNum, X_WARNING, "[agp] AGP not available\n"); + return FALSE; + } + + if (!RADEONSetAgpMode(info, pScreen)) + return FALSE; + + RADEONDRIInitGARTValues(info); - if ((ret = drmAgpAlloc(info->drmFD, info->agpSize*1024*1024, 0, NULL, + if ((ret = drmAgpAlloc(info->drmFD, info->gartSize*1024*1024, 0, NULL, &info->agpMemHandle)) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret); drmAgpRelease(info->drmFD); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, - "[agp] %d kB allocated with handle 0x%08x\n", - info->agpSize*1024, info->agpMemHandle); + "[agp] %d kB allocated with handle 0x%08lx\n", + info->gartSize*1024, info->agpMemHandle); if (drmAgpBind(info->drmFD, - info->agpMemHandle, info->agpOffset) < 0) { + info->agpMemHandle, info->gartOffset) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n"); drmAgpFree(info->drmFD, info->agpMemHandle); drmAgpRelease(info->drmFD); return FALSE; } - /* Initialize the CP ring buffer data */ - info->ringStart = info->agpOffset; - info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE; - info->ringSizeLog2QW = RADEONMinBits(info->ringSize*1024*1024/8)-1; - - info->ringReadOffset = info->ringStart + info->ringMapSize; - info->ringReadMapSize = DRM_PAGE_SIZE; - - /* Reserve space for vertex/indirect buffers */ - info->bufStart = info->ringReadOffset + info->ringReadMapSize; - info->bufMapSize = info->bufSize*1024*1024; - - /* Reserve the rest for AGP textures */ - info->agpTexStart = info->bufStart + info->bufMapSize; - s = (info->agpSize*1024*1024 - info->agpTexStart); - l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); - if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; - info->agpTexMapSize = (s >> l) << l; - info->log2AGPTexGran = l; - if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize, DRM_AGP, DRM_READ_ONLY, &info->ringHandle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, @@ -850,67 +863,50 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) "[agp] Vertex/indirect buffers mapped at 0x%08lx\n", (unsigned long)info->buf); - if (drmAddMap(info->drmFD, info->agpTexStart, info->agpTexMapSize, - DRM_AGP, 0, &info->agpTexHandle) < 0) { + if (drmAddMap(info->drmFD, info->gartTexStart, info->gartTexMapSize, + DRM_AGP, 0, &info->gartTexHandle) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, - "[agp] Could not add AGP texture map mapping\n"); + "[agp] Could not add GART texture map mapping\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, - "[agp] AGP texture map handle = 0x%08lx\n", - info->agpTexHandle); + "[agp] GART texture map handle = 0x%08lx\n", + info->gartTexHandle); - if (drmMap(info->drmFD, info->agpTexHandle, info->agpTexMapSize, - (drmAddressPtr)&info->agpTex) < 0) { + if (drmMap(info->drmFD, info->gartTexHandle, info->gartTexMapSize, + (drmAddressPtr)&info->gartTex) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, - "[agp] Could not map AGP texture map\n"); + "[agp] Could not map GART texture map\n"); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, - "[agp] AGP Texture map mapped at 0x%08lx\n", - (unsigned long)info->agpTex); - - /* Initialize Radeon's AGP registers */ + "[agp] GART Texture map mapped at 0x%08lx\n", + (unsigned long)info->gartTex); - agpBase = drmAgpBase(info->drmFD); - OUTREG(RADEON_AGP_BASE, agpBase); + RADEONSetAgpBase(info); return TRUE; } -/* Initialize the PCIGART state. Request memory for use in PCI space, +/* Initialize the PCI GART state. Request memory for use in PCI space, * and initialize the Radeon registers to point to that memory. */ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) { int ret; - int flags; + int flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL; - info->agpOffset = 0; - - ret = drmScatterGatherAlloc(info->drmFD, info->agpSize*1024*1024, + ret = drmScatterGatherAlloc(info->drmFD, info->gartSize*1024*1024, &info->pciMemHandle); if (ret < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Out of memory (%d)\n", ret); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, - "[pci] %d kB allocated with handle 0x%08x\n", - info->agpSize*1024, info->pciMemHandle); + "[pci] %d kB allocated with handle 0x%08lx\n", + info->gartSize*1024, info->pciMemHandle); - /* Initialize the CCE ring buffer data */ - info->ringStart = info->agpOffset; - info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE; - info->ringSizeLog2QW = RADEONMinBits(info->ringSize*1024*1024/8)-1; - - info->ringReadOffset = info->ringStart + info->ringMapSize; - info->ringReadMapSize = DRM_PAGE_SIZE; - - /* Reserve space for vertex/indirect buffers */ - info->bufStart = info->ringReadOffset + info->ringReadMapSize; - info->bufMapSize = info->bufSize*1024*1024; - - flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL; + RADEONDRIInitGARTValues(info); if (drmAddMap(info->drmFD, info->ringStart, info->ringMapSize, DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) { @@ -979,6 +975,26 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) "[pci] Vertex/indirect buffers contents 0x%08lx\n", *(unsigned long *)(pointer)info->buf); + if (drmAddMap(info->drmFD, info->gartTexStart, info->gartTexMapSize, + DRM_SCATTER_GATHER, 0, &info->gartTexHandle) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[pci] Could not add GART texture map mapping\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[pci] GART texture map handle = 0x%08lx\n", + info->gartTexHandle); + + if (drmMap(info->drmFD, info->gartTexHandle, info->gartTexMapSize, + (drmAddressPtr)&info->gartTex) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[pci] Could not map GART texture map\n"); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, + "[pci] GART Texture map mapped at 0x%08lx\n", + (unsigned long)info->gartTex); + return TRUE; } @@ -1008,9 +1024,9 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen) memset(&drmInfo, 0, sizeof(drmRadeonInit)); - if ( (info->ChipFamily == CHIP_FAMILY_R200) || - (info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_M9) ) + if ((info->ChipFamily == CHIP_FAMILY_R200) || + (info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280) ) drmInfo.func = DRM_RADEON_INIT_R200_CP; else drmInfo.func = DRM_RADEON_INIT_CP; @@ -1018,7 +1034,7 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen) drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); drmInfo.is_pci = info->IsPCI; drmInfo.cp_mode = info->CPMode; - drmInfo.agp_size = info->agpSize*1024*1024; + drmInfo.gart_size = info->gartSize*1024*1024; drmInfo.ring_size = info->ringSize*1024*1024; drmInfo.usec_timeout = info->CPusecTimeout; @@ -1037,7 +1053,7 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen) drmInfo.ring_offset = info->ringHandle; drmInfo.ring_rptr_offset = info->ringReadPtrHandle; drmInfo.buffers_offset = info->bufHandle; - drmInfo.agp_textures_offset = info->agpTexHandle; + drmInfo.gart_textures_offset= info->gartTexHandle; if (drmCommandWrite(info->drmFD, DRM_RADEON_CP_INIT, &drmInfo, sizeof(drmRadeonInit)) < 0) @@ -1052,28 +1068,28 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen) return TRUE; } -static void RADEONDRIAgpHeapInit(RADEONInfoPtr info, ScreenPtr pScreen) +static void RADEONDRIGartHeapInit(RADEONInfoPtr info, ScreenPtr pScreen) { drmRadeonMemInitHeap drmHeap; - /* Start up the simple memory manager for agp space */ + /* Start up the simple memory manager for GART space */ if (info->drmMinor >= 6) { - drmHeap.region = RADEON_MEM_REGION_AGP; + drmHeap.region = RADEON_MEM_REGION_GART; drmHeap.start = 0; - drmHeap.size = info->agpTexMapSize; - + drmHeap.size = info->gartTexMapSize; + if (drmCommandWrite(info->drmFD, DRM_RADEON_INIT_HEAP, &drmHeap, sizeof(drmHeap))) { xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] Failed to initialized agp heap manager\n"); + "[drm] Failed to initialize GART heap manager\n"); } else { xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] Initialized kernel agp heap manager, %d\n", - info->agpTexMapSize); + "[drm] Initialized kernel GART heap manager, %d\n", + info->gartTexMapSize); } } else { xf86DrvMsg(pScreen->myNum, X_INFO, - "[drm] Kernel module too old (1.%d) for agp heap manager\n", + "[drm] Kernel module too old (1.%d) for GART heap manager\n", info->drmMinor); } } @@ -1084,19 +1100,12 @@ static void RADEONDRIAgpHeapInit(RADEONInfoPtr info, ScreenPtr pScreen) static Bool RADEONDRIBufInit(RADEONInfoPtr info, ScreenPtr pScreen) { /* Initialize vertex buffers */ - if (info->IsPCI) { - info->bufNumBufs = drmAddBufs(info->drmFD, - info->bufMapSize / RADEON_BUFFER_SIZE, - RADEON_BUFFER_SIZE, - DRM_SG_BUFFER, - info->bufStart); - } else { - info->bufNumBufs = drmAddBufs(info->drmFD, - info->bufMapSize / RADEON_BUFFER_SIZE, - RADEON_BUFFER_SIZE, - DRM_AGP_BUFFER, - info->bufStart); - } + info->bufNumBufs = drmAddBufs(info->drmFD, + info->bufMapSize / RADEON_BUFFER_SIZE, + RADEON_BUFFER_SIZE, + info->IsPCI ? DRM_SG_BUFFER : DRM_AGP_BUFFER, + info->bufStart); + if (info->bufNumBufs <= 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Could not create vertex/indirect buffers list\n"); @@ -1226,12 +1235,11 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) info->pDRIInfo = pDRIInfo; pDRIInfo->drmDriverName = RADEON_DRIVER_NAME; - if (info->ChipFamily == CHIP_FAMILY_R200) + if ( (info->ChipFamily == CHIP_FAMILY_R200) || + (info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280) ) pDRIInfo->clientDriverName = R200_DRIVER_NAME; - else if ((info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_M9)) - pDRIInfo->clientDriverName = RV250_DRIVER_NAME; - else + else pDRIInfo->clientDriverName = RADEON_DRIVER_NAME; pDRIInfo->busIdString = xalloc(64); @@ -1354,24 +1362,24 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) if (version) { int req_minor, req_patch; - if ((info->ChipFamily == CHIP_FAMILY_R200) || - (info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_M9)) { + if ((info->ChipFamily == CHIP_FAMILY_R200) || + (info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280)) { req_minor = 5; - req_patch = 0; + req_patch = 0; } else { #if X_BYTE_ORDER == X_LITTLE_ENDIAN req_minor = 1; req_patch = 0; #else req_minor = 2; - req_patch = 1; + req_patch = 1; #endif } if (version->version_major != 1 || version->version_minor < req_minor || - (version->version_minor == req_minor && + (version->version_minor == req_minor && version->version_patchlevel < req_patch)) { /* Incompatible drm version */ xf86DrvMsg(pScreen->myNum, X_ERROR, @@ -1441,9 +1449,9 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) { void *scratch_ptr; int scratch_int; - + DRIGetDeviceInfo(pScreen, &info->fbHandle, - &scratch_int, &scratch_int, + &scratch_int, &scratch_int, &scratch_int, &scratch_int, &scratch_ptr); } @@ -1498,8 +1506,8 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) /* Initialize IRQ */ RADEONDRIIrqInit(info, pScreen); - /* Initialize kernel agp memory manager */ - RADEONDRIAgpHeapInit(info, pScreen); + /* Initialize kernel GART memory manager */ + RADEONDRIGartHeapInit(info, pScreen); /* Initialize and start the CP if required */ RADEONDRICPInit(pScrn); @@ -1535,10 +1543,10 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) pRADEONDRI->statusHandle = info->ringReadPtrHandle; pRADEONDRI->statusSize = info->ringReadMapSize; - pRADEONDRI->agpTexHandle = info->agpTexHandle; - pRADEONDRI->agpTexMapSize = info->agpTexMapSize; - pRADEONDRI->log2AGPTexGran = info->log2AGPTexGran; - pRADEONDRI->agpTexOffset = info->agpTexStart; + pRADEONDRI->gartTexHandle = info->gartTexHandle; + pRADEONDRI->gartTexMapSize = info->gartTexMapSize; + pRADEONDRI->log2GARTTexGran = info->log2GARTTexGran; + pRADEONDRI->gartTexOffset = info->gartTexStart; pRADEONDRI->sarea_priv_offset = sizeof(XF86DRISAREARec); @@ -1557,6 +1565,47 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) return TRUE; } +/** + * This function will attempt to get the Radeon hardware back into shape + * after a resume from disc. + * + * Charl P. Botha <http://cpbotha.net> + */ +void RADEONDRIResume(ScreenPtr pScreen) +{ + int _ret; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (info->drmMinor >= 9) { + xf86DrvMsg(pScreen->myNum, X_INFO, + "[RESUME] Attempting to re-init Radeon hardware.\n"); + } else { + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[RESUME] Cannot re-init Radeon hardware, DRM too old\n" + "(need 1.9.0 or newer)\n"); + return; + } + + if (!info->IsPCI) { + if (!RADEONSetAgpMode(info, pScreen)) + return; + + RADEONSetAgpBase(info); + } + + _ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_RESUME); + if (_ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s: CP resume %d\n", __FUNCTION__, _ret); + /* FIXME: return? */ + } + + RADEONEngineRestore(pScrn); + + RADEONDRICPInit(pScrn); +} + /* The screen is being closed, so clean up any state and free any * resources used by the DRI. */ @@ -1600,10 +1649,10 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) drmCommandWrite(info->drmFD, DRM_RADEON_CP_INIT, &drmInfo, sizeof(drmRadeonInit)); - /* De-allocate all AGP resources */ - if (info->agpTex) { - drmUnmap(info->agpTex, info->agpTexMapSize); - info->agpTex = NULL; + /* De-allocate all GART resources */ + if (info->gartTex) { + drmUnmap(info->gartTex, info->gartTexMapSize); + info->gartTex = NULL; } if (info->buf) { drmUnmap(info->buf, info->bufMapSize); @@ -1617,10 +1666,10 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) drmUnmap(info->ring, info->ringMapSize); info->ring = NULL; } - if (info->agpMemHandle) { + if (info->agpMemHandle != DRM_AGP_NO_HANDLE) { drmAgpUnbind(info->drmFD, info->agpMemHandle); drmAgpFree(info->drmFD, info->agpMemHandle); - info->agpMemHandle = 0; + info->agpMemHandle = DRM_AGP_NO_HANDLE; drmAgpRelease(info->drmFD); } if (info->pciMemHandle) { @@ -1849,10 +1898,10 @@ static void RADEONDRITransitionTo2d(ScreenPtr pScreen) } else { xf86DrvMsg(pScreen->myNum, X_WARNING, "[dri] RADEONDRITransitionTo2d: " - "kernel failed to unflip buffers.\n"); + "kernel failed to unflip buffers.\n"); } - xf86FreeOffscreenArea(info->depthTexArea); + xf86FreeOffscreenArea(info->depthTexArea); info->have3DWindows = 0; diff --git a/src/radeon_dri.h b/src/radeon_dri.h index abfcb4ef..0e06a73f 100644 --- a/src/radeon_dri.h +++ b/src/radeon_dri.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.h,v 1.4 2002/10/30 12:52:13 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.h,v 1.5 2003/09/28 20:15:55 alanh Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, * VA Linux Systems Inc., Fremont, California. @@ -45,10 +45,10 @@ #define RADEON_DEFAULT_CP_BM_MODE RADEON_CSQ_PRIBM_INDBM #define RADEON_DEFAULT_AGP_MODE 1 #define RADEON_DEFAULT_AGP_FAST_WRITE 0 -#define RADEON_DEFAULT_AGP_SIZE 8 /* MB (must be 2^n and > 4MB) */ +#define RADEON_DEFAULT_GART_SIZE 8 /* MB (must be 2^n and > 4MB) */ #define RADEON_DEFAULT_RING_SIZE 1 /* MB (must be page aligned) */ #define RADEON_DEFAULT_BUFFER_SIZE 2 /* MB (must be page aligned) */ -#define RADEON_DEFAULT_AGP_TEX_SIZE 1 /* MB (must be page aligned) */ +#define RADEON_DEFAULT_GART_TEX_SIZE 1 /* MB (must be page aligned) */ #define RADEON_DEFAULT_CP_TIMEOUT 10000 /* usecs */ @@ -92,11 +92,11 @@ typedef struct { drmHandle statusHandle; drmSize statusSize; - /* CP AGP Texture data */ - drmHandle agpTexHandle; - drmSize agpTexMapSize; - int log2AGPTexGran; - int agpTexOffset; + /* CP GART Texture data */ + drmHandle gartTexHandle; + drmSize gartTexMapSize; + int log2GARTTexGran; + int gartTexOffset; unsigned int sarea_priv_offset; #ifdef PER_CONTEXT_SAREA diff --git a/src/radeon_driver.c b/src/radeon_driver.c index ae584332..930ecba6 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v 1.91 2003/02/25 03:50:15 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v 1.116 2003/11/19 02:08:15 martin Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -71,19 +71,7 @@ #include "radeon_sarea.h" #endif -#define USE_FB /* not until overlays */ -#ifdef USE_FB #include "fb.h" -#else - - /* CFB support */ -#define PSZ 8 -#include "cfb.h" -#undef PSZ -#include "cfb16.h" -#include "cfb24.h" -#include "cfb32.h" -#endif /* colormap initialization */ #include "micmap.h" @@ -105,6 +93,9 @@ #ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) #endif +#ifndef MIN +#define MIN(a,b) ((a)>(b)?(b):(a)) +#endif /* Forward definitions for driver functions */ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen); @@ -115,6 +106,7 @@ static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); +static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn); typedef enum { OPTION_NOACCEL, @@ -123,11 +115,12 @@ typedef enum { OPTION_DAC_8BIT, #ifdef XF86DRI OPTION_IS_PCI, + OPTION_BUS_TYPE, OPTION_CP_PIO, OPTION_USEC_TIMEOUT, OPTION_AGP_MODE, OPTION_AGP_FW, - OPTION_AGP_SIZE, + OPTION_GART_SIZE, OPTION_RING_SIZE, OPTION_BUFFER_SIZE, OPTION_DEPTH_MOVE, @@ -136,12 +129,17 @@ typedef enum { #endif OPTION_PANEL_OFF, OPTION_DDC_MODE, - OPTION_CLONE_DISPLAY, + OPTION_MONITOR_LAYOUT, + OPTION_IGNORE_EDID, + OPTION_CRTC2_OVERLAY, OPTION_CLONE_MODE, OPTION_CLONE_HSYNC, OPTION_CLONE_VREFRESH, OPTION_FBDEV, - OPTION_VIDEO_KEY + OPTION_VIDEO_KEY, + OPTION_DISP_PRIORITY, + OPTION_PANEL_SIZE, + OPTION_MIN_DOTCLOCK } RADEONOpts; const OptionInfoRec RADEONOptions[] = { @@ -151,11 +149,13 @@ const OptionInfoRec RADEONOptions[] = { { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE }, #ifdef XF86DRI { OPTION_IS_PCI, "ForcePCIMode", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_BUS_TYPE, "BusType", OPTV_ANYSTR, {0}, FALSE }, { OPTION_CP_PIO, "CPPIOMode", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_USEC_TIMEOUT, "CPusecTimeout", OPTV_INTEGER, {0}, FALSE }, { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE }, { OPTION_AGP_FW, "AGPFastWrite", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE }, + { OPTION_GART_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE }, + { OPTION_GART_SIZE, "GARTSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_BUFFER_SIZE, "BufferSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_DEPTH_MOVE, "EnableDepthMoves", OPTV_BOOLEAN, {0}, FALSE }, @@ -164,21 +164,20 @@ const OptionInfoRec RADEONOptions[] = { #endif { OPTION_PANEL_OFF, "PanelOff", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DDC_MODE, "DDCMode", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_CLONE_DISPLAY, "CloneDisplay", OPTV_INTEGER, {0}, FALSE }, + { OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_IGNORE_EDID, "IgnoreEDID", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CRTC2_OVERLAY , "OverlayOnCRTC2", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_CLONE_MODE, "CloneMode", OPTV_ANYSTR, {0}, FALSE }, { OPTION_CLONE_HSYNC, "CloneHSync", OPTV_ANYSTR, {0}, FALSE }, { OPTION_CLONE_VREFRESH, "CloneVRefresh", OPTV_ANYSTR, {0}, FALSE }, { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {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 }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; -RADEONRAMRec RADEONRAM[] = { /* Memory Specifications - From Radeon Manual */ - { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SDRAM" }, - { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SDRAM" }, -}; - static const char *vgahwSymbols[] = { "vgaHWFreeHWRec", "vgaHWGetHWRec", @@ -226,21 +225,11 @@ static const char *ddcSymbols[] = { NULL }; -#ifdef USE_FB static const char *fbSymbols[] = { "fbScreenInit", "fbPictureInit", NULL }; -#else -static const char *cfbSymbols[] = { - "cfbScreenInit", - "cfb16ScreenInit", - "cfb24ScreenInit", - "cfb32ScreenInit", - NULL -}; -#endif static const char *xaaSymbols[] = { "XAACreateInfoRec", @@ -355,11 +344,7 @@ void RADEONLoaderRefSymLists(void) * refer to. */ xf86LoaderRefSymLists(vgahwSymbols, -#ifdef USE_FB fbSymbols, -#else - cfbSymbols, -#endif xaaSymbols, #if 0 xf8_32bppSymbols, @@ -392,7 +377,7 @@ static struct {1024, 768, 87}, {832, 624, 75}, {800, 600, 75}, - {800, 600, 72}, + {800, 600, 72}, {800, 600, 60}, {800, 600, 56}, {640, 480, 75}, @@ -403,6 +388,24 @@ static struct {720, 400, 70}, }; +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, 0x400f7/*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*/ +}; + extern int gRADEONEntityIndex; struct RADEONInt10Save { @@ -414,37 +417,29 @@ struct RADEONInt10Save { static Bool RADEONMapMMIO(ScrnInfoPtr pScrn); static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn); +static RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn) +{ + DevUnion *pPriv; + RADEONInfoPtr info = RADEONPTR(pScrn); + pPriv = xf86GetEntityPrivate(info->pEnt->index, + gRADEONEntityIndex); + return pPriv->ptr; +} + static void RADEONPreInt10Save(ScrnInfoPtr pScrn, void **pPtr) { RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO; - int mapped = 0; + unsigned char *RADEONMMIO = info->MMIO; CARD32 CardTmp; static struct RADEONInt10Save SaveStruct = { 0, 0, 0 }; - /* - * First make sure we have the pci and mmio info and that mmio is mapped - */ - if (!info->PciInfo) - info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); - if (!info->PciTag) - info->PciTag = pciTag(info->PciInfo->bus, info->PciInfo->device, - info->PciInfo->func); - if (!info->MMIOAddr) - info->MMIOAddr = info->PciInfo->memBase[2] & 0xffffff00; - if (!info->MMIO) { - RADEONMapMMIO(pScrn); - mapped = 1; - } - RADEONMMIO = info->MMIO; - /* Save the values and zap MEM_CNTL */ SaveStruct.MEM_CNTL = INREG(RADEON_MEM_CNTL); SaveStruct.MEMSIZE = INREG(RADEON_CONFIG_MEMSIZE); SaveStruct.MPP_TB_CONFIG = INREG(RADEON_MPP_TB_CONFIG); - /* + /* * Zap MEM_CNTL and set MPP_TB_CONFIG<31:24> to 4 */ OUTREG(RADEON_MEM_CNTL, 0); @@ -453,52 +448,40 @@ RADEONPreInt10Save(ScrnInfoPtr pScrn, void **pPtr) OUTREG(RADEON_MPP_TB_CONFIG, CardTmp); *pPtr = (void *)&SaveStruct; - - /* Unmap mmio space if we mapped it */ - if (mapped) - RADEONUnmapMMIO(pScrn); } static void RADEONPostInt10Check(ScrnInfoPtr pScrn, void *ptr) { RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO; + unsigned char *RADEONMMIO = info->MMIO; struct RADEONInt10Save *pSave = ptr; CARD32 CardTmp; - int mapped = 0; /* If we don't have a valid (non-zero) saved MEM_CNTL, get out now */ if (!pSave || !pSave->MEM_CNTL) return; - /* First make sure that mmio is mapped */ - if (!info->MMIO) { - RADEONMapMMIO(pScrn); - mapped = 1; - } - RADEONMMIO = info->MMIO; - /* * If either MEM_CNTL is currently zero or inconistent (configured for * two channels with the two channels configured differently), restore * the saved registers. */ CardTmp = INREG(RADEON_MEM_CNTL); - if (!CardTmp || - ((CardTmp & 1) && + if (!CardTmp || + ((CardTmp & 1) && (((CardTmp >> 8) & 0xff) != ((CardTmp >> 24) & 0xff)))) { /* Restore the saved registers */ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Restoring MEM_CNTL (%08x), setting to %08x\n", - CardTmp, pSave->MEM_CNTL); + "Restoring MEM_CNTL (%08lx), setting to %08lx\n", + (unsigned long)CardTmp, (unsigned long)pSave->MEM_CNTL); OUTREG(RADEON_MEM_CNTL, pSave->MEM_CNTL); CardTmp = INREG(RADEON_CONFIG_MEMSIZE); if (CardTmp != pSave->MEMSIZE) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Restoring CONFIG_MEMSIZE (%08x), setting to %08x\n", - CardTmp, pSave->MEMSIZE); + "Restoring CONFIG_MEMSIZE (%08lx), setting to %08lx\n", + (unsigned long)CardTmp, (unsigned long)pSave->MEMSIZE); OUTREG(RADEON_CONFIG_MEMSIZE, pSave->MEMSIZE); } } @@ -506,16 +489,13 @@ RADEONPostInt10Check(ScrnInfoPtr pScrn, void *ptr) CardTmp = INREG(RADEON_MPP_TB_CONFIG); if ((CardTmp & 0xff000000u) != (pSave->MPP_TB_CONFIG & 0xff000000u)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Restoring MPP_TB_CONFIG<31:24> (%02x), setting to %02x\n", - CardTmp >> 24, pSave->MPP_TB_CONFIG >> 24); + "Restoring MPP_TB_CONFIG<31:24> (%02lx), setting to %02lx\n", + (unsigned long)CardTmp >> 24, + (unsigned long)pSave->MPP_TB_CONFIG >> 24); CardTmp &= 0x00ffffffu; CardTmp |= (pSave->MPP_TB_CONFIG & 0xff000000u); OUTREG(RADEON_MPP_TB_CONFIG, CardTmp); } - - /* Unmap mmio space if we mapped it */ - if (mapped) - RADEONUnmapMMIO(pScrn); } /* Allocate our private RADEONInfoRec */ @@ -711,12 +691,8 @@ static void RADEONBlank(ScrnInfoPtr pScrn) case MT_CRT: case MT_DFP: 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)); + RADEON_CRTC_DISPLAY_DIS, + ~(RADEON_CRTC_DISPLAY_DIS)); break; case MT_NONE: @@ -725,20 +701,12 @@ static void RADEONBlank(ScrnInfoPtr pScrn) } if (info->Clone) 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)); + RADEON_CRTC2_DISP_DIS, + ~(RADEON_CRTC2_DISP_DIS)); } else { 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)); + RADEON_CRTC2_DISP_DIS, + ~(RADEON_CRTC2_DISP_DIS)); } } @@ -755,9 +723,7 @@ static void RADEONUnblank(ScrnInfoPtr pScrn) case MT_DFP: OUTREGP(RADEON_CRTC_EXT_CNTL, RADEON_CRTC_CRT_ON, - ~(RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS)); + ~(RADEON_CRTC_DISPLAY_DIS)); break; case MT_NONE: @@ -767,9 +733,7 @@ static void RADEONUnblank(ScrnInfoPtr pScrn) if (info->Clone) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, - ~(RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS)); + ~(RADEON_CRTC2_DISP_DIS)); } else { switch (info->DisplayType) { case MT_LCD: @@ -777,9 +741,7 @@ static void RADEONUnblank(ScrnInfoPtr pScrn) case MT_CRT: OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, - ~(RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS)); + ~(RADEON_CRTC2_DISP_DIS)); break; case MT_NONE: @@ -805,14 +767,338 @@ static int RADEONDiv(int n, int d) return (n + (d / 2)) / d; } -/* Read the Video BIOS block and the FP registers (if applicable) */ -static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) +static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, xf86MonPtr* MonInfo) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long tmp, i; - unsigned char *RADEONMMIO; - Bool BypassSecondary = FALSE; - int CloneDispOption; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned long DDCReg; + RADEONMonitorType MonType = MT_NONE; + 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; + } + + if (*MonInfo) { + if ((*MonInfo)->rawData[0x14] & 0x80) { + if (INREG(RADEON_LVDS_GEN_CNTL) & RADEON_LVDS_ON) MonType = MT_LCD; + else MonType = MT_DFP; + } 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 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_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); + + ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); + ulData = ulOrigDAC_CNTL; + ulData |= RADEON_DAC_CMP_EN; + ulData &= ~(RADEON_DAC_RANGE_CNTL_MASK + | RADEON_DAC_PDWN); + ulData |= 0x2; + OUTREG(RADEON_DAC_CNTL, ulData); + + usleep(1000); + + ulData = INREG(RADEON_DAC_CNTL); + bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; + + 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); + } 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 ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) + 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(1000); + + 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 void RADEONQueryConnectedDisplays(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + const char *s; + Bool ignore_edid = FALSE, ddc_crt2_used = FALSE; #define RADEON_BIOS8(v) (info->VBIOS[v]) #define RADEON_BIOS16(v) (info->VBIOS[v] | \ @@ -822,6 +1108,303 @@ static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) (info->VBIOS[(v) + 2] << 16) | \ (info->VBIOS[(v) + 3] << 24)) + pRADEONEnt->MonType1 = MT_NONE; + pRADEONEnt->MonType2 = MT_NONE; + pRADEONEnt->MonInfo1 = NULL; + pRADEONEnt->MonInfo2 = NULL; + pRADEONEnt->ReversedDAC = FALSE; + pRADEONEnt->ReversedTMDS = FALSE; + + /* IgnoreEDID option is different from NoDDC 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. + */ + 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. + */ + + /* current monitor mapping scheme: + * Two displays connected: + * Primary Port: + * CRTC1 -> FP/TMDS -> DVI port -> TMDS panel --> Primary or + * CRTC1 -> FP/LVDS -> Int. LCD -> LVDS panel --> Primary or + * CRTC1 -> TV DAC -> DVI port -> CRT monitor --> Primary + * + * Secondary Port + * CRTC2 -> CRT DAC -> VGA port -> CRT monitor --> Secondary or + * CRTC2 -> FP2/Ext. -> DVI port -> TMDS panel --> Secondary + * + * Only DVI (or Int. LDC) conneced: + * CRTC1 -> FP/TMDS -> DVI port -> TMDS panel --> Primary or + * CRTC1 -> FP/LVDS -> Int. LCD -> LVDS panel --> Primary or + * CRTC1 -> TV DAC -> DVI port -> CRT monitor --> Primary + * + * Only VGA (can be DVI on some dual-DVI boards) connected: + * CRTC1 -> CRT DAC -> VGA port -> CRT monitor --> Primary or + * CRTC1 -> FP2/Ext. -> DVI port -> TMDS panel --> Primary (not supported) + * + * Note, this is different from Windows scheme where + * if a digital panel is connected to DVI port, DVI will be the 1st port + * otherwise, VGA port will be treated as 1st port + * + * Here we always treat DVI port as primary if both ports are connected. + * When only one port is connected, it will be treated as + * primary regardless which port or what type of display is involved. + */ + + if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { + char s1[5], s2[5]; + int i = 0, second = 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++; + if (i == 4) break; + } + } while(*s++); + s2[i] = '\0'; + + if (strcmp(s1, "NONE") == 0) + pRADEONEnt->MonType1 = MT_NONE; + else if (strcmp(s1, "CRT") == 0) + pRADEONEnt->MonType1 = MT_CRT; + else if (strcmp(s1, "TMDS") == 0) + pRADEONEnt->MonType1 = MT_DFP; + else if (strcmp(s1, "LVDS") == 0) + pRADEONEnt->MonType1 = MT_LCD; + else + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for 1st port \n"); + if (strcmp(s2, "NONE") == 0) + pRADEONEnt->MonType2 = MT_NONE; + else if (strcmp(s2, "CRT") == 0) + pRADEONEnt->MonType2 = MT_CRT; + else if (strcmp(s2, "TMDS") == 0) + pRADEONEnt->MonType2 = MT_DFP; + else if (strcmp(s2, "LVDS") == 0) + pRADEONEnt->MonType2 = MT_LCD; + else + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for 2nd port \n"); + + if (!ignore_edid) { + if (pRADEONEnt->MonType1) /* assuming the first port using DDC_DVI */ + if(!RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1)) { + RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1); + ddc_crt2_used = TRUE; + } + if (pRADEONEnt->MonType2) { /* assuming the second port using DDC_VGA/DDC_CRT2 */ + if(!RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo2)) + if (!ddc_crt2_used) + RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo2); + } + } + + if (!pRADEONEnt->MonType1) { + if (pRADEONEnt->MonType2) { + pRADEONEnt->MonType1 = pRADEONEnt->MonType2; + pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; + } else { + pRADEONEnt->MonType1 = MT_CRT; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No valid monitor specified, force to CRT on 1st port\n"); + } + pRADEONEnt->MonType2 = MT_NONE; + pRADEONEnt->MonInfo2 = NULL; + } + } else { + /* Auto detection */ + int i; + CARD32 tmp; + + /* Old single head radeon cards */ + if(!info->HasCRTC2) { + if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1))); + else if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo1))); + else if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1))); + else if (pInt10) { + if (xf86LoadSubModule(pScrn, "vbe")) { + vbeInfoPtr pVbe; + pVbe = VBEInit(pInt10, info->pEnt->index); + if (pVbe) { + for (i = 0; i < 5; i++) { + pRADEONEnt->MonInfo1 = vbeDoEDID(pVbe, NULL); + } + if (pRADEONEnt->MonInfo1->rawData[0x14] & 0x80) + pRADEONEnt->MonType1 = MT_DFP; + else pRADEONEnt->MonType1 = MT_CRT; + } + } + } else + pRADEONEnt->MonType1 = MT_CRT; + + pRADEONEnt->HasSecondary = FALSE; + if (!ignore_edid) { + if (pRADEONEnt->MonInfo1) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); + xf86PrintEDID( pRADEONEnt->MonInfo1 ); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); + } + } + return; + } + + /* Normally the port uses DDC_DVI connected with TVDAC, + * But this is not true for OEM cards which have TVDAC and CRT DAC reversed. + * If that's the case, we need also reverse the port arrangement. + * BIOS settings are supposed report this correctly, work fine for all cards tested. + * But there may be some exceptions, in that case, user can reverse their monitor + * definition in config file to correct the problem. + */ + if (info->VBIOS && (tmp = RADEON_BIOS16(info->FPBIOSstart + 0x50))) { + for (i = 1; i < 4; i++) { + unsigned int tmp0; + if (!RADEON_BIOS8(tmp + i*2) && i > 1) break; + tmp0 = RADEON_BIOS16(tmp + i*2); + if ((!(tmp0 & 0x01)) && (((tmp0 >> 8) & 0xf) == DDC_DVI)) { + pRADEONEnt->ReversedDAC = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed DACs detected\n"); + } + if ((((tmp0 >> 8) & 0x0f) == DDC_DVI ) && ((tmp0 >> 4) & 0x1)) { + pRADEONEnt->ReversedTMDS = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed TMDS detected\n"); + } + } + } + + /* Primary Head (DVI or Laptop Int. panel)*/ + /* A ddc capable display connected on DVI port */ + if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1))); + else if((pRADEONEnt->MonType1 = + RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1))) { + ddc_crt2_used = TRUE; + } else if ((info->IsMobility) && + (info->VBIOS && (INREG(RADEON_BIOS_4_SCRATCH) & 4))) { + /* non-DDC laptop panel connected on primary */ + pRADEONEnt->MonType1 = MT_LCD; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Non-DDC laptop panel detected\n"); + } else { + /* CRT on DVI, TODO: not reliable, make it always return false for now*/ + pRADEONEnt->MonType1 = RADEONCrtIsPhysicallyConnected(pScrn, pRADEONEnt->ReversedDAC); + } + + /* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ + if((pRADEONEnt->MonType2 = + RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo2))); + else if(!ddc_crt2_used) + pRADEONEnt->MonType2 = + RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo2); + if (!pRADEONEnt->MonType2) + pRADEONEnt->MonType2 = RADEONCrtIsPhysicallyConnected(pScrn, !pRADEONEnt->ReversedDAC); + + if(pRADEONEnt->ReversedTMDS) { + /* always keep internal TMDS as primary head */ + if (pRADEONEnt->MonType1 == MT_DFP || + pRADEONEnt->MonType2 == MT_DFP) { + int tmp1 = pRADEONEnt->MonType1; + xf86MonPtr MonInfo = pRADEONEnt->MonInfo1; + pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; + pRADEONEnt->MonInfo2 = MonInfo; + pRADEONEnt->MonType1 = pRADEONEnt->MonType2; + pRADEONEnt->MonType2 = tmp1; + if ((pRADEONEnt->MonType1 == MT_CRT) || + (pRADEONEnt->MonType2 == MT_CRT)) { + pRADEONEnt->ReversedDAC ^= 1; + } + } + } + + /* no display detected on DVI port*/ + if (pRADEONEnt->MonType1 == MT_NONE) { + if (pRADEONEnt->MonType2 != MT_NONE) { + /* Only one detected on VGA, let it to be primary */ + pRADEONEnt->MonType1 = pRADEONEnt->MonType2; + pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; + pRADEONEnt->MonType2 = MT_NONE; + pRADEONEnt->MonInfo2 = NULL; + } else { + /* Non detected, Default to a CRT connected */ + pRADEONEnt->MonType1 = MT_CRT; + } + } + } + + if(s) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Displays Configured by MonitorLayout: \n\tMonitor1--Type %d, Monitor2--Type %d\n\n", + pRADEONEnt->MonType1, pRADEONEnt->MonType2); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Displays Detected: Monitor1--Type %d, Monitor2--Type %d\n\n", + pRADEONEnt->MonType1, pRADEONEnt->MonType2); + } + + if(ignore_edid) { + pRADEONEnt->MonInfo1 = NULL; + pRADEONEnt->MonInfo2 = NULL; + } + + if (!ignore_edid) { + if (pRADEONEnt->MonInfo1) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n"); + xf86PrintEDID( pRADEONEnt->MonInfo1 ); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n"); + } + if (pRADEONEnt->MonInfo2) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor2 EDID data ---------------------------\n"); + xf86PrintEDID( pRADEONEnt->MonInfo2 ); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor2 EDID data --------------------\n"); + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); + + info->OverlayOnCRTC2 = FALSE; + if (xf86ReturnOptValBool(info->Options, OPTION_CRTC2_OVERLAY, FALSE)) { + info->OverlayOnCRTC2 = TRUE; + } + + if (pRADEONEnt->MonType2 == MT_NONE) + pRADEONEnt->HasSecondary = FALSE; +} + + +/* Read the Video BIOS block and the FP registers (if applicable). */ +static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long tmp, i; + if (!(info->VBIOS = xalloc(RADEON_VBIOS_SIZE))) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot allocate space for hold Video BIOS!\n"); @@ -848,334 +1431,338 @@ static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { xfree(info->VBIOS); + info->FPBIOSstart = 0; info->VBIOS = NULL; info->BIOSAddr = 0x00000000; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Video BIOS not found!\n"); - return TRUE; - } - - info->FPBIOSstart = RADEON_BIOS16(0x48); + } else + info->FPBIOSstart = RADEON_BIOS16(0x48); info->OverlayOnCRTC2 = FALSE; - RADEONMapMMIO(pScrn); - RADEONMMIO = info->MMIO; + if (!info->IsSecondary) + RADEONQueryConnectedDisplays(pScrn, pInt10); - /* FIXME: using BIOS scratch registers to detect connected monitors - * may not be a reliable way.... should use EDID data. Also it only - * works with for VE/M6, no such registers in regular RADEON!!! - */ - - /* VE and M6 have both DVI and CRT ports (for M6 DVI port can be - * switch to DFP port). The DVI port can also be conneted to a CRT - * with an adapter. Here is the definition of ports for this - * driver: - * - * (1) If both port are connected, DVI port will be treated as the - * Primary port (first screen in XF86Config, uses CRTC1) and CRT - * port will be treated as the Secondary port (second screen in - * XF86Config, uses CRTC2) - * - * (2) If only one screen specified in XF86Config, it will be used - * for DVI port if a monitor is connected to DVI port, otherwise - * (only one monitor is connected the CRT port) it will be used for - * CRT port. - */ + { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - if (info->HasCRTC2) { - /* FIXME: this may not be reliable */ - tmp = INREG(RADEON_BIOS_4_SCRATCH); + info->Clone = FALSE; + info->CloneType = MT_NONE; - if (info->IsSecondary) { - /* Check Port2 (CRT port) -- for the existing boards (VE & - * M6), this port can only be connected to a CRT - */ - if (tmp & 0x02) info->DisplayType = MT_CRT; - else if (tmp & 0x800) info->DisplayType = MT_DFP; - else if (tmp & 0x400) info->DisplayType = MT_LCD; - else if (tmp & 0x1000) info->DisplayType = MT_CTV; - else if (tmp & 0x2000) info->DisplayType = MT_STV; - else info->DisplayType = MT_CRT; + if(info->HasCRTC2) { + if(info->IsSecondary) { + info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType2; + if(info->DisplayType == MT_NONE) return FALSE; + } else { + info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType1; + if(!pRADEONEnt->HasSecondary) { + info->CloneType = (RADEONMonitorType)pRADEONEnt->MonType2; + if (info->CloneType != MT_NONE) + info->Clone = TRUE; + } + } } else { - info->Clone = FALSE; - info->CloneType = MT_NONE; - - /* Check Primary (DVI/DFP port) */ - if (tmp & 0x08) info->DisplayType = MT_DFP; - else if (tmp & 0x04) info->DisplayType = MT_LCD; - else if (tmp & 0x0200) info->DisplayType = MT_CRT; - else if (tmp & 0x10) info->DisplayType = MT_CTV; - else if (tmp & 0x20) info->DisplayType = MT_STV; - else info->DisplayType = MT_NONE; - - if (info->DisplayType == MT_NONE) { - /* DVI port has no monitor connected, try CRT port. - * If something on CRT port, treat it as primary + info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType1; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Display == Type %d\n", + (info->IsSecondary ? "Secondary" : "Primary"), + info->DisplayType); + + if (info->Clone) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clone Display == Type %d\n", + info->CloneType); + + info->HBlank = 0; + info->HOverPlus = 0; + info->HSyncWidth = 0; + info->VBlank = 0; + info->VOverPlus = 0; + info->VSyncWidth = 0; + info->DotClock = 0; + info->UseBiosDividers = FALSE; + + if (info->DisplayType == MT_LCD && info->VBIOS && + !(xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { + tmp = RADEON_BIOS16(info->FPBIOSstart + 0x40); + if (!tmp) { + info->PanelPwrDly = 200; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No Panel Info Table found in BIOS!\n"); + } else { + char stmp[30]; + int tmp0; + + for (i = 0; i < 24; i++) + stmp[i] = RADEON_BIOS8(tmp+i+1); + stmp[24] = 0; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Panel ID string: %s\n", stmp); + + info->PanelXRes = RADEON_BIOS16(tmp+25); + info->PanelYRes = RADEON_BIOS16(tmp+27); + xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n", + info->PanelXRes, info->PanelYRes); + + info->PanelPwrDly = RADEON_BIOS16(tmp+44); + if (info->PanelPwrDly > 2000 || info->PanelPwrDly < 0) + info->PanelPwrDly = 2000; + + /* some panels only work well with certain divider combinations. */ - if (xf86IsEntityShared(pScrn->entityList[0])) { - DevUnion *pPriv; - RADEONEntPtr pRADEONEnt; - - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], - gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; - pRADEONEnt->BypassSecondary = TRUE; + info->RefDivider = RADEON_BIOS16(tmp+46); + info->PostDivider = RADEON_BIOS8(tmp+48); + info->FeedbackDivider = RADEON_BIOS16(tmp+49); + if ((info->RefDivider != 0) && + (info->FeedbackDivider > 3)) { + info->UseBiosDividers = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "BIOS provided dividers will be used.\n"); } - if (tmp & 0x02) info->DisplayType = MT_CRT; - else if (tmp & 0x800) info->DisplayType = MT_DFP; - else if (tmp & 0x400) info->DisplayType = MT_LCD; - else if (tmp & 0x1000) info->DisplayType = MT_CTV; - else if (tmp & 0x2000) info->DisplayType = MT_STV; - else { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No monitor detected!!!\n"); - return FALSE; + /* We don't use a while loop here just in case we have a corrupted BIOS image. + The max number of table entries is 23 at present, but may grow in future. + To ensure it works with future revisions we loop it to 32. + */ + 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) - + RADEON_BIOS16(tmp0+19)) * 8; + info->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_BIOS16(tmp0+26)); + info->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; + } } - BypassSecondary = TRUE; - } else { - if (tmp & 0x02) { - info->CloneType = MT_CRT; - info->Clone = TRUE; - } else if (tmp & 0x800) { - info->CloneType = MT_DFP; - info->Clone = TRUE; + + if (info->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 == 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->MonInfo1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Panel size is not correctly detected.\n" + "Please try to use PanelSize option for correct settings.\n"); + return FALSE; + } } } + } + } - /* FIXME: This option is too complicated. We need to - * find a better way to handle all cases. - * - * CloneDisplay options: - * 0 -- disable - * 1 -- auto-detect (default) - * 2 -- force on - * 3 -- auto-detect + 2nd head overlay. - * 4 -- force on + 2nd head overlay. - * others -- auto-detect - * - * Force on: it will force the clone mode on even no display - * is detected. With this option together with the proper - * CloneHSync and CloneVRefresh options, we can turn on the - * CRT ouput on the 2nd head regardless if a monitor is - * connected there. This way, we can plug in a CRT to the - * second head later after X server has started. - * - * 2nd head overlay: it will force the hardware overlay on - * CRTC2 (used by 2nd head). Since we only have one overlay, - * we have to decide which head to use it (the overlay space - * on the other head will be blank). 2nd head overlay is on - * automatically when PanelOff option is effective. - */ - if (xf86GetOptValInteger(info->Options, OPTION_CLONE_DISPLAY, - &(CloneDispOption))) { - char *s = NULL; + if (info->VBIOS) { + tmp = RADEON_BIOS16(info->FPBIOSstart + 0x30); + info->sclk = RADEON_BIOS16(tmp + 8) / 100.0; + info->mclk = RADEON_BIOS16(tmp + 10) / 100.0; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No valid info for SCLK/MCLK for display bandwidth calculation.\n"); + info->sclk = 200.00; + info->mclk = 200.00; + } - if (CloneDispOption < 0 || CloneDispOption > 4) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Illegal CloneDisplay Option set, " - "using default\n"); - CloneDispOption = 1; - } + return TRUE; +} - switch (CloneDispOption) { - case 0: s = "Disable"; break; - case 1: s = "Auto-detect"; break; - case 2: s = "Force On"; break; - case 3: s = "Auto-detect -- use 2nd head overlay"; break; - case 4: s = "Force On -- use 2nd head overlay"; break; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "CloneDisplay option: %s (%d)\n", - s, CloneDispOption); - } else { - /* Default to auto-detect */ - CloneDispOption = 1; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "CloneDisplay option not set -- " - "defaulting to auto-detect\n"); - } +static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONPLLPtr pll = &info->pll; + unsigned char *RADEONMMIO = info->MMIO; + unsigned char ppll_div_sel; + unsigned Nx, M; + unsigned xclk, tmp, ref_div; + int hTotal, vTotal, num, denom, m, n; + float hz, vclk, xtal; + long start_secs, start_usecs, stop_secs, stop_usecs, total_usecs; + int i; + + for(i=0; i<1000000; i++) + if (((INREG(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0) + break; - if (CloneDispOption == 0) { - info->Clone = FALSE; - } else if ((CloneDispOption == 2 || CloneDispOption == 4) - && !info->Clone) { - info->CloneType = MT_CRT; - info->Clone = TRUE; - } + xf86getsecs(&start_secs, &start_usecs); - /* This will be used to set OV0_SCALAR_CNTL */ - if (info->Clone && (CloneDispOption == 3 || CloneDispOption == 4)) - info->OverlayOnCRTC2 = TRUE; - } - } else { - /* Regular Radeon ASIC, only one CRTC, but it could be used for - * DFP with a DVI output, like AIW board - */ - tmp = INREG(RADEON_FP_GEN_CNTL); - if (tmp & RADEON_FP_EN_TMDS) info->DisplayType = MT_DFP; - else info->DisplayType = MT_CRT; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Display == Type %d\n", - (info->IsSecondary ? "Secondary" : "Primary"), - info->DisplayType); - - RADEONMMIO = NULL; - RADEONUnmapMMIO(pScrn); - - info->HBlank = 0; - info->HOverPlus = 0; - info->HSyncWidth = 0; - info->VBlank = 0; - info->VOverPlus = 0; - info->VSyncWidth = 0; - info->DotClock = 0; - - if (info->DisplayType == MT_LCD) { - tmp = RADEON_BIOS16(info->FPBIOSstart + 0x40); - if (!tmp) { - info->PanelPwrDly = 200; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No Panel Info Table found in BIOS!\n"); - } else { - char stmp[30]; - int tmp0; + for(i=0; i<1000000; i++) + if (((INREG(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) != 0) + break; - for (i = 0; i < 24; i++) - stmp[i] = RADEON_BIOS8(tmp+i+1); - stmp[24] = 0; + for(i=0; i<1000000; i++) + if (((INREG(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0) + break; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Panel ID string: %s\n", stmp); + xf86getsecs(&stop_secs, &stop_usecs); - info->PanelXRes = RADEON_BIOS16(tmp+25); - info->PanelYRes = RADEON_BIOS16(tmp+27); - xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n", - info->PanelXRes, info->PanelYRes); + total_usecs = abs(stop_usecs - start_usecs); + hz = 1000000/total_usecs; - info->PanelPwrDly = RADEON_BIOS16(tmp+44); - if (info->PanelPwrDly > 2000 || info->PanelPwrDly < 0) - info->PanelPwrDly = 2000; - for (i = 0; i < 20; 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) - - RADEON_BIOS16(tmp0+19)) * 8; - info->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_BIOS16(tmp0+26)); - info->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; - } - } - } - } else if ((info->DisplayType == MT_DFP) && info->HasCRTC2) { + hTotal = ((INREG(RADEON_CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8; + vTotal = ((INREG(RADEON_CRTC_V_TOTAL_DISP) & 0x3ff) + 1); + vclk = (float)(hTotal * (float)(vTotal * hz)); + + switch((INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x30000) >> 16) { + case 0: + default: + num = 1; + denom = 1; + break; + case 1: + n = ((INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) >> 16) & 0xff); + m = (INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) & 0xff); + num = 2*n; + denom = 2*m; + break; + case 2: + n = ((INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) >> 8) & 0xff); + m = (INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) & 0xff); + num = 2*n; + denom = 2*m; + break; + } + + OUTREG(RADEON_CLOCK_CNTL_INDEX, 1); + ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_DATA + 1) & 0x3; + + n = (INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel) & 0x7ff); + m = (INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x3ff); + + num *= n; + denom *= m; + + switch ((INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel) >> 16) & 0x7) { + case 1: + denom *= 2; + break; + case 2: + denom *= 4; + break; + case 3: + denom *= 8; + break; + case 4: + denom *= 3; + break; + case 6: + denom *= 6; + break; + case 7: + denom *= 12; + break; + } + + xtal = (int)(vclk *(float)denom/(float)num); + + if ((xtal > 26900000) && (xtal < 27100000)) + xtal = 2700; + else if ((xtal > 14200000) && (xtal < 14400000)) + xtal = 1432; + else if ((xtal > 29400000) && (xtal < 29600000)) + xtal = 2950; + else + return FALSE; + + tmp = INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV); + ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x3ff; + + Nx = (tmp & 0xff00) >> 8; + M = (tmp & 0xff); + xclk = RADEONDiv((2 * Nx * xtal), (2 * M)); + + /* we're done, hopefully these are sane values */ + pll->reference_div = ref_div; + pll->xclk = xclk; + pll->reference_freq = xtal; + + return TRUE; +} + +static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD32 tmp; + int i, n; + + for (i=0; i<4; i++) { + info->tmds_pll[i].value = 0; + info->tmds_pll[i].freq = 0; + } + + if (info->VBIOS) { tmp = RADEON_BIOS16(info->FPBIOSstart + 0x34); - if (tmp != 0) { - tmp = RADEON_BIOS16(tmp + 2); - if (tmp != 0) { - /* 18 bytes of EDID data should be here */ - info->DotClock = RADEON_BIOS16(tmp) * 10; - info->PanelXRes = - ((RADEON_BIOS8(tmp + 4) & 0xf0) << 4) + - RADEON_BIOS8(tmp + 2); - info->HBlank = - ((RADEON_BIOS8(tmp + 4) & 0x0f) << 8) + - RADEON_BIOS8(tmp + 3); - info->PanelYRes = - ((RADEON_BIOS8(tmp + 7) & 0xf0) << 4) + - RADEON_BIOS8(tmp + 5); - info->VBlank = - ((RADEON_BIOS8(tmp + 7) & 0x0f) << 8) + - RADEON_BIOS8(tmp + 6); - info->HOverPlus = - ((RADEON_BIOS8(tmp + 11) & 0xc0) << 2) + - RADEON_BIOS8(tmp + 8); - info->HSyncWidth = - ((RADEON_BIOS8(tmp + 11) & 0x30) << 4) + - RADEON_BIOS8(tmp + 9); - info->VOverPlus = - ((RADEON_BIOS8(tmp + 11) & 0x0c) << 2) + - ((RADEON_BIOS8(tmp + 10) & 0xf0) >> 4); - info->VSyncWidth = - ((RADEON_BIOS8(tmp + 11) & 0x03) << 4) + - (RADEON_BIOS8(tmp + 10) & 0x0f); - info->Flags = 0; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No DFP timing table detected\n"); + if (tmp) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DFP table revision: %d\n", RADEON_BIOS8(tmp)); + if (RADEON_BIOS8(tmp) == 3) { + 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); + } + return; } - } - RADEONTRACE(("DFP Info: ----------------------\n" - "pixel clock: %d KHz\n" - "panel size: %dx%d\n" - "H. Blanking: %d\n" - "H. Sync. Offset: %d\n" - "H. Sync. Width: %d\n" - "V. Blanking: %d\n" - "V. Sync. Offset: %d\n" - "V. Sync. Width: %d\n", - info->DotClock, - info->PanelXRes, info->PanelYRes, - info->HBlank, - info->HOverPlus, - info->HSyncWidth, - info->VBlank, info->VOverPlus, info->VSyncWidth)); - } - - /* Detect connector type from BIOS, used for I2C/DDC qeurying EDID, - * Only available for VE or newer cards */ - - /* DELL OEM card doesn't seem to follow the conviention for BIOS's - * DDC type, we have to make a special case. Following hard coded - * type works with both CRT+CRT and DVI+DVI cases - */ - if (info->IsDell && info->DellType == 2) { - if (info->IsSecondary) - info->DDCType = DDC_CRT2; - else - info->DDCType = DDC_DVI; - info->CloneDDCType = DDC_CRT2; - } else if ((tmp = RADEON_BIOS16(info->FPBIOSstart + 0x50))) { - for (i = 1; i < 4; i++) { - unsigned int tmp0; - if (!RADEON_BIOS8(tmp + i*2) && i > 1) break; - - /* Note: Secondary port (CRT port) actually uses primary DAC */ - tmp0 = RADEON_BIOS16(tmp + i*2); - if (tmp0 & 0x01) { - if (!info->IsSecondary && !BypassSecondary) - info->DDCType = (tmp0 & 0x0f00) >> 8; - } else { /* Primary DAC */ - if (info->Clone) - info->CloneDDCType = (tmp0 & 0x0f00) >> 8; - else if (info->IsSecondary || - BypassSecondary || - !info->HasCRTC2) { - info->DDCType = (tmp0 & 0x0f00) >> 8; + /* revision 4 has some problem as it appears in RV280, + comment it off for new, 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; } + */ } - } else { - /* Orignal radeon cards, set it to DDC_VGA, this will not work - * with AIW, it should be DDC_DVI, let it fall back to VBE calls - * for AIW - */ - info->DDCType = DDC_VGA; } - return TRUE; + 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; + } } /* Read PLL parameters from BIOS block. Default to typical values if @@ -1187,23 +1774,47 @@ static Bool RADEONGetPLLParameters(ScrnInfoPtr pScrn) RADEONPLLPtr pll = &info->pll; CARD16 bios_header; CARD16 pll_info_block; + double min_dotclock; if (!info->VBIOS) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Video BIOS not detected, using default PLL parameters!\n"); - /* These probably aren't going to work for - the card you are using. Specifically, - reference freq can be 29.50MHz, - 28.63MHz, or 14.32MHz. YMMV. */ - - /* These are somewhat sane defaults for Mac boards, we will need - * to find a good way of getting these from OpenFirmware - */ - pll->reference_freq = 2700; - pll->reference_div = 67; + pll->min_pll_freq = 12500; pll->max_pll_freq = 35000; - pll->xclk = 16615; + + + if (!RADEONProbePLLParameters(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Video BIOS not detected, using default PLL parameters!\n"); + + switch (info->Chipset) { + case PCI_CHIP_R200_QL: + case PCI_CHIP_R200_QN: + case PCI_CHIP_R200_QO: + case PCI_CHIP_R200_BB: + pll->reference_freq = 2700; + pll->reference_div = 12; + pll->xclk = 27500; + break; + case PCI_CHIP_RV250_Id: + case PCI_CHIP_RV250_Ie: + case PCI_CHIP_RV250_If: + case PCI_CHIP_RV250_Ig: + pll->reference_freq = 2700; + pll->reference_div = 12; + pll->xclk = 24975; + break; + case PCI_CHIP_RV200_QW: + pll->reference_freq = 2700; + pll->reference_div = 12; + pll->xclk = 23000; + break; + default: + pll->reference_freq = 2700; + pll->reference_div = 67; + pll->xclk = 16615; + break; + } + } } else { bios_header = RADEON_BIOS16(0x48); pll_info_block = RADEON_BIOS16(bios_header + 0x30); @@ -1217,13 +1828,25 @@ static Bool RADEONGetPLLParameters(ScrnInfoPtr pScrn) pll->xclk = RADEON_BIOS16(pll_info_block + 0x08); } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "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); + /* (Some?) Radeon BIOSes seem too lie about their minimum dot + * clocks. Allow users to override the detected minimum dot clock + * value (e.g., and allow it to be suitable for TV sets). + */ + if (xf86GetOptValFreq(info->Options, OPTION_MIN_DOTCLOCK, + OPTUNITS_MHZ, &min_dotclock)) { + if (min_dotclock < 12 || min_dotclock*100 >= pll->max_pll_freq) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Illegal minimum dotclock specified %.2f MHz " + "(option ignored)\n", + min_dotclock); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Forced minimum dotclock to %.2f MHz " + "(instead of detected %.2f MHz)\n", + min_dotclock, ((double)pll->min_pll_freq/1000)); + pll->min_pll_freq = min_dotclock * 1000; + } + } return TRUE; } @@ -1233,7 +1856,7 @@ static Bool RADEONPreInitVisual(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - if (!xf86SetDepthBpp(pScrn, 8, 8, 8, Support32bppFb)) + if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) return FALSE; switch (pScrn->depth) { @@ -1317,6 +1940,44 @@ static Bool RADEONPreInitWeight(ScrnInfoPtr pScrn) return TRUE; } +static void RADEONGetVRamType(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp; + + if (info->IsIGP || (info->ChipFamily >= CHIP_FAMILY_R300) || + (INREG(RADEON_MEM_SDRAM_MODE_REG) & (1<<30))) + info->IsDDR = TRUE; + else + info->IsDDR = FALSE; + + tmp = INREG(RADEON_MEM_CNTL); + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) { + tmp &= R300_MEM_NUM_CHANNELS_MASK; + switch (tmp) { + case 0: info->RamWidth = 64; break; + case 1: info->RamWidth = 128; break; + case 2: info->RamWidth = 256; break; + default: info->RamWidth = 128; break; + } + } else if ((info->ChipFamily == CHIP_FAMILY_RV100) || + (info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)){ + if (tmp & RV100_HALF_MODE) info->RamWidth = 32; + else info->RamWidth = 64; + } else { + if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) info->RamWidth = 128; + else info->RamWidth = 64; + } + + /* This may not be correct, as some cards can have half of channel disabled + * ToDo: identify these cases + */ +} + /* This is called by RADEONPreInit to handle config file overrides for * things like chipset and memory regions. Also determine memory size * and type. If memory type ever needs an override, put it in this @@ -1327,9 +1988,12 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); EntityInfoPtr pEnt = info->pEnt; GDevPtr dev = pEnt->device; - int offset = 0; /* RAM Type */ MessageType from; - unsigned char *RADEONMMIO; + unsigned char *RADEONMMIO = info->MMIO; +#ifdef XF86DRI + const char *s; + CARD32 agpCommand; +#endif /* Chipset */ from = X_PROBED; @@ -1360,56 +2024,81 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) info->Chipset); info->HasCRTC2 = TRUE; + info->IsMobility = FALSE; + info->IsIGP = FALSE; switch (info->Chipset) { case PCI_CHIP_RADEON_LY: case PCI_CHIP_RADEON_LZ: - info->ChipFamily = CHIP_FAMILY_M6; + info->IsMobility = TRUE; + info->ChipFamily = CHIP_FAMILY_RV100; break; case PCI_CHIP_RV100_QY: case PCI_CHIP_RV100_QZ: - info->ChipFamily = CHIP_FAMILY_VE; + info->ChipFamily = CHIP_FAMILY_RV100; + break; + + case PCI_CHIP_RS100_4336: + info->IsMobility = TRUE; + case PCI_CHIP_RS100_4136: + info->ChipFamily = CHIP_FAMILY_RS100; + info->IsIGP = TRUE; + break; + + case PCI_CHIP_RS200_4337: + info->IsMobility = TRUE; + case PCI_CHIP_RS200_4137: + info->ChipFamily = CHIP_FAMILY_RS200; + info->IsIGP = TRUE; + break; + + case PCI_CHIP_RS250_4437: + info->IsMobility = TRUE; + case PCI_CHIP_RS250_4237: + info->ChipFamily = CHIP_FAMILY_RS200; + info->IsIGP = TRUE; break; case PCI_CHIP_R200_BB: + case PCI_CHIP_R200_BC: case PCI_CHIP_R200_QH: - case PCI_CHIP_R200_QI: - case PCI_CHIP_R200_QJ: - case PCI_CHIP_R200_QK: case PCI_CHIP_R200_QL: case PCI_CHIP_R200_QM: - case PCI_CHIP_R200_QN: - case PCI_CHIP_R200_QO: - case PCI_CHIP_R200_Qh: - case PCI_CHIP_R200_Qi: - case PCI_CHIP_R200_Qj: - case PCI_CHIP_R200_Qk: - case PCI_CHIP_R200_Ql: info->ChipFamily = CHIP_FAMILY_R200; break; + case PCI_CHIP_RADEON_LW: + case PCI_CHIP_RADEON_LX: + info->IsMobility = TRUE; case PCI_CHIP_RV200_QW: /* RV200 desktop */ case PCI_CHIP_RV200_QX: info->ChipFamily = CHIP_FAMILY_RV200; break; - case PCI_CHIP_RADEON_LW: - case PCI_CHIP_RADEON_LX: - info->ChipFamily = CHIP_FAMILY_M7; - break; - - case PCI_CHIP_RV250_Id: - case PCI_CHIP_RV250_Ie: + case PCI_CHIP_RV250_Ld: + case PCI_CHIP_RV250_Lf: + case PCI_CHIP_RV250_Lg: + info->IsMobility = TRUE; case PCI_CHIP_RV250_If: case PCI_CHIP_RV250_Ig: info->ChipFamily = CHIP_FAMILY_RV250; break; - case PCI_CHIP_RV250_Ld: - case PCI_CHIP_RV250_Le: - case PCI_CHIP_RV250_Lf: - case PCI_CHIP_RV250_Lg: - info->ChipFamily = CHIP_FAMILY_M9; + case PCI_CHIP_RS300_5835: + info->IsMobility = TRUE; + case PCI_CHIP_RS300_5834: + info->ChipFamily = CHIP_FAMILY_RS300; + info->IsIGP = TRUE; + break; + + case PCI_CHIP_RV280_5C61: + case PCI_CHIP_RV280_5C63: + info->IsMobility = TRUE; + case PCI_CHIP_RV280_5960: + case PCI_CHIP_RV280_5961: + case PCI_CHIP_RV280_5962: + case PCI_CHIP_RV280_5964: + info->ChipFamily = CHIP_FAMILY_RV280; break; case PCI_CHIP_R300_AD: @@ -1423,47 +2112,47 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) info->ChipFamily = CHIP_FAMILY_R300; break; + case PCI_CHIP_RV350_NP: + case PCI_CHIP_RV350_NQ: + case PCI_CHIP_RV350_NR: + case PCI_CHIP_RV350_NS: + case PCI_CHIP_RV350_NT: + case PCI_CHIP_RV350_NV: + info->IsMobility = TRUE; + case PCI_CHIP_RV350_AP: + case PCI_CHIP_RV350_AQ: + case PCI_CHIP_RV360_AR: + case PCI_CHIP_RV350_AS: + case PCI_CHIP_RV350_AT: + case PCI_CHIP_RV350_AV: + info->ChipFamily = CHIP_FAMILY_RV350; + break; + + case PCI_CHIP_R350_AH: + case PCI_CHIP_R350_AI: + case PCI_CHIP_R350_AJ: + case PCI_CHIP_R350_AK: + case PCI_CHIP_R350_NH: + case PCI_CHIP_R350_NI: + case PCI_CHIP_R350_NK: + case PCI_CHIP_R360_NJ: + info->ChipFamily = CHIP_FAMILY_R350; + break; + default: /* Original Radeon/7200 */ info->ChipFamily = CHIP_FAMILY_RADEON; info->HasCRTC2 = FALSE; } - /* Here is the special case for DELL's VE card. - * It needs some special handlings for it's 2nd head to work. - */ - info->IsDell = FALSE; - if (info->ChipFamily == CHIP_FAMILY_VE && - info->PciInfo->subsysVendor == PCI_VENDOR_ATI && - info->PciInfo->subsysCard & (1 << 12)) { /* DELL's signature */ - if (info->PciInfo->subsysCard & 0xb00) { - info->IsDell = TRUE; - info->DellType = 2; /* DVI+DVI config, this seems to be the - * only known type for now, can be - * connected to both DVI+DVI and VGA+VGA - * dongles. - */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "DELL OEM Card detected with %s (type %d)\n", - (info->DellType == 2) ? "DVI+DVI / VGA+VGA" : "VGA+VGA", - info->DellType); - } else { - info->DellType = 0; /* Unknown */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Unknown type of DELL's Card (SSCID %x), " - "treated as normal type\n", - info->PciInfo->subsysCard); - } - } - /* Framebuffer */ from = X_PROBED; - info->LinearAddr = info->PciInfo->memBase[0] & 0xfc000000; + info->LinearAddr = info->PciInfo->memBase[0] & 0xfe000000; pScrn->memPhysBase = info->LinearAddr; if (dev->MemBase) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Linear address override, using 0x%08x instead of 0x%08x\n", + "Linear address override, using 0x%08lx instead of 0x%08lx\n", dev->MemBase, info->LinearAddr); info->LinearAddr = dev->MemBase; @@ -1476,29 +2165,12 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%08lx\n", info->LinearAddr); - /* MMIO registers */ - from = X_PROBED; - info->MMIOAddr = info->PciInfo->memBase[2] & 0xffffff00; - if (dev->IOBase) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "MMIO address override, using 0x%08x instead of 0x%08x\n", - dev->IOBase, - info->MMIOAddr); - info->MMIOAddr = dev->IOBase; - from = X_CONFIG; - } else if (!info->MMIOAddr) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n"); - return FALSE; - } - xf86DrvMsg(pScrn->scrnIndex, from, - "MMIO registers at 0x%08lx\n", info->MMIOAddr); - /* BIOS */ from = X_PROBED; info->BIOSAddr = info->PciInfo->biosBase & 0xfffe0000; if (dev->BiosBase) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS address override, using 0x%08x instead of 0x%08x\n", + "BIOS address override, using 0x%08lx instead of 0x%08lx\n", dev->BiosBase, info->BIOSAddr); info->BIOSAddr = dev->BiosBase; @@ -1509,13 +2181,36 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) "BIOS at 0x%08lx\n", info->BIOSAddr); } - RADEONMapMMIO(pScrn); - RADEONMMIO = info->MMIO; - /* Read registers used to determine options */ from = X_PROBED; if (info->FBDev) pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024; + else if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200) || + (info->ChipFamily == CHIP_FAMILY_RS300)) { + CARD32 tom = INREG(RADEON_NB_TOM); + pScrn->videoRam = (((tom >> 16) - + (tom & 0xffff) + 1) << 6); + OUTREG(RADEON_MC_FB_LOCATION, tom); + OUTREG(RADEON_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); + OUTREG(RADEON_DISPLAY2_BASE_ADDR, (tom & 0xffff) << 16); + OUTREG(RADEON_OV0_BASE_ADDR, (tom & 0xffff) << 16); + + /* This is supposed to fix the crtc2 noise problem. + */ + OUTREG(RADEON_GRPH2_BUFFER_CNTL, + INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000); + + 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. + */ + OUTREGP(RADEON_CRTC_MORE_CNTL, RADEON_CRTC_H_CUTOFF_ACTIVE_EN, + ~RADEON_CRTC_H_CUTOFF_ACTIVE_EN); + } + + } else pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024; @@ -1525,12 +2220,9 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) if (info->IsSecondary) { /* FIXME: For now, split FB into two equal sections. This should * be able to be adjusted by user with a config option. */ - DevUnion *pPriv; - RADEONEntPtr pRADEONEnt; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONInfoPtr info1; - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; pScrn->videoRam /= 2; pRADEONEnt->pPrimaryScrn->videoRam = pScrn->videoRam; @@ -1548,16 +2240,8 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) info->MemCntl = INREG(RADEON_SDRAM_MODE_REG); info->BusCntl = INREG(RADEON_BUS_CNTL); - RADEONMMIO = NULL; - RADEONUnmapMMIO(pScrn); - /* RAM */ - switch (info->MemCntl >> 30) { - case 0: offset = 0; break; /* 64-bit SDR SDRAM */ - case 1: offset = 1; break; /* 64-bit DDR SDRAM */ - default: offset = 0; - } - info->ram = &RADEONRAM[offset]; + RADEONGetVRamType(pScrn); if (dev->videoRam) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -1570,62 +2254,53 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) pScrn->videoRam &= ~1023; info->FbMapSize = pScrn->videoRam * 1024; xf86DrvMsg(pScrn->scrnIndex, from, - "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name); + "VideoRAM: %d kByte (%d bit %s SDRAM)\n", pScrn->videoRam, info->RamWidth, info->IsDDR?"DDR":"SDR"); #ifdef XF86DRI /* AGP/PCI */ - if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) { - info->IsPCI = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI-only mode\n"); + + /* There are signatures in BIOS and PCI-SSID for a PCI card, but + * they are not very reliable. Following detection method works for + * all cards tested so far. Note, checking AGP_ENABLE bit after + * drmAgpEnable call can also give the correct result. However, + * calling drmAgpEnable on a PCI card can cause some strange lockup + * when the server restarts next time. + */ + + agpCommand = pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG); + pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, + agpCommand | RADEON_AGP_ENABLE); + if (pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG) + & RADEON_AGP_ENABLE) { + info->IsPCI = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AGP card detected\n"); } else { - switch (info->Chipset) { -#if 0 - case PCI_CHIP_RADEON_XX: info->IsPCI = TRUE; break; -#endif - case PCI_CHIP_RV100_QY: - case PCI_CHIP_RV100_QZ: - case PCI_CHIP_RADEON_LW: - case PCI_CHIP_RADEON_LX: - case PCI_CHIP_RADEON_LY: - case PCI_CHIP_RADEON_LZ: - case PCI_CHIP_RADEON_QD: - case PCI_CHIP_RADEON_QE: - case PCI_CHIP_RADEON_QF: - case PCI_CHIP_RADEON_QG: - case PCI_CHIP_R200_BB: - case PCI_CHIP_R200_QH: - case PCI_CHIP_R200_QI: - case PCI_CHIP_R200_QJ: - case PCI_CHIP_R200_QK: - case PCI_CHIP_R200_QL: - case PCI_CHIP_R200_QM: - case PCI_CHIP_R200_QN: - case PCI_CHIP_R200_QO: - case PCI_CHIP_R200_Qh: - case PCI_CHIP_R200_Qi: - case PCI_CHIP_R200_Qj: - case PCI_CHIP_R200_Qk: - case PCI_CHIP_R200_Ql: - case PCI_CHIP_RV200_QW: - case PCI_CHIP_RV200_QX: - case PCI_CHIP_RV250_Id: - case PCI_CHIP_RV250_Ie: - case PCI_CHIP_RV250_If: - case PCI_CHIP_RV250_Ig: - case PCI_CHIP_RV250_Ld: - case PCI_CHIP_RV250_Le: - case PCI_CHIP_RV250_Lf: - case PCI_CHIP_RV250_Lg: - case PCI_CHIP_R300_AD: - case PCI_CHIP_R300_AE: - case PCI_CHIP_R300_AF: - case PCI_CHIP_R300_AG: - case PCI_CHIP_R300_ND: - case PCI_CHIP_R300_NE: - case PCI_CHIP_R300_NF: - case PCI_CHIP_R300_NG: - default: info->IsPCI = FALSE; break; + info->IsPCI = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PCI card detected\n"); + } + pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, agpCommand); + + if ((s = xf86GetOptValString(info->Options, OPTION_BUS_TYPE))) { + if (strcmp(s, "AGP") == 0) { + info->IsPCI = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into AGP mode\n"); + } else if (strcmp(s, "PCI") == 0) { + info->IsPCI = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n"); + } else if (strcmp(s, "PCIE") == 0) { + info->IsPCI = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "PCI Express not supported yet, using PCI mode\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Invalid BusType option, using detected type\n"); } + } else if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) { + info->IsPCI = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "ForcePCIMode is deprecated -- " + "use BusType option instead\n"); } #endif @@ -1657,6 +2332,9 @@ static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) 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); } static Bool RADEONI2cInit(ScrnInfoPtr pScrn) @@ -1672,23 +2350,6 @@ static Bool RADEONI2cInit(ScrnInfoPtr pScrn) info->pI2CBus->I2CGetBits = RADEONI2CGetBits; info->pI2CBus->AcknTimeout = 5; - switch (info->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: - return FALSE; - } - if (!xf86I2CBusInit(info->pI2CBus)) return FALSE; return TRUE; } @@ -1718,113 +2379,6 @@ static void RADEONPreInitDDC(ScrnInfoPtr pScrn) } } -static xf86MonPtr RADEONDoDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - xf86MonPtr MonInfo = NULL; - unsigned char *RADEONMMIO; - int i; - - /* We'll use DDC2, BIOS EDID can only detect the monitor connected - * to one port. For VE, BIOS EDID detects the monitor connected to - * DVI port by default. If no monitor their, it will try CRT port - */ - - /* Read and output monitor info using DDC2 over I2C bus */ - if (info->pI2CBus && info->ddc2) { - int j; - - if (!RADEONMapMMIO(pScrn)) return NULL; - RADEONMMIO = info->MMIO; - 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 < 50; 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; - } - - RADEONUnmapMMIO(pScrn); - } - - if (!MonInfo && pInt10 && (info->DDCReg == RADEON_GPIO_VGA_DDC)) { - if (xf86LoadSubModule(pScrn, "vbe")) { - vbeInfoPtr pVbe; - pVbe = VBEInit(pInt10, info->pEnt->index); - if (pVbe) { - for (i = 0; i < 5; i++) { - MonInfo = vbeDoEDID(pVbe, NULL); - info->ddc_bios = TRUE; - if (MonInfo) - break; - } - } else - info->ddc_bios = FALSE; - } - } - - if (MonInfo) { - if (info->ddc2) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I2C EDID Info:\n"); - else if (info->ddc_bios) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS EDID Info:\n"); - else return NULL; - - xf86PrintEDID(MonInfo); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of DDC Monitor info\n\n"); - - xf86SetDDCproperties(pScrn, MonInfo); - return MonInfo; - } - else return NULL; -} /* BIOS may not have right panel size, we search through all supported * DDC modes looking for the maximum panel size. @@ -1910,7 +2464,7 @@ static void RADEONSortModes(DisplayModePtr *new, DisplayModePtr *first, p = *last; while (p) { - if ((((*new)->HDisplay < p->HDisplay) && + if ((((*new)->HDisplay < p->HDisplay) && ((*new)->VDisplay < p->VDisplay)) || (((*new)->HDisplay == p->HDisplay) && ((*new)->VDisplay == p->VDisplay) && @@ -1929,7 +2483,7 @@ static void RADEONSortModes(DisplayModePtr *new, DisplayModePtr *first, p->prev = *new; *first = *new; break; - } + } p = p->prev; } @@ -1955,7 +2509,7 @@ static void RADEONSetPitch (ScrnInfoPtr pScrn) pScrn->displayWidth = dummy; } -/* When no mode provided in config file, this will add all modes supported in +/* 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) @@ -2065,7 +2619,7 @@ static DisplayModePtr RADEONDDCModes(ScrnInfoPtr pScrn) strcpy(new->name, p->name); new->status = MODE_OK; new->type = M_T_DEFAULT; - + count++; xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -2103,11 +2657,11 @@ static int RADEONValidateDDCModes(ScrnInfoPtr pScrn, char **ppModeName, pScrn->virtualX = pScrn->display->virtualX; pScrn->virtualY = pScrn->display->virtualY; - if (pScrn->monitor->DDC) { + if (pScrn->monitor->DDC && !info->UseBiosDividers) { int maxVirtX = pScrn->virtualX; int maxVirtY = pScrn->virtualY; - if (DisplayType != MT_CRT) { + if ((DisplayType != MT_CRT) && !info->IsSecondary) { /* 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 @@ -2193,7 +2747,7 @@ static int RADEONValidateDDCModes(ScrnInfoPtr pScrn, char **ppModeName, } } - /* + /* * Add remaining DDC modes if they're smaller than the user * specified modes */ @@ -2295,8 +2849,7 @@ static DisplayModePtr RADEONFPNativeMode(ScrnInfoPtr pScrn) return new; } -/* XFree86's xf86ValidateModes routine doesn't work well with DFPs, so - * here is our own validation routine. +/* FP mode initialization routine for using on-chip RMX to scale */ static int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) { @@ -2304,6 +2857,7 @@ static int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) DisplayModePtr last = NULL; DisplayModePtr new = NULL; DisplayModePtr first = NULL; + DisplayModePtr p, tmp; int count = 0; int i, width, height; @@ -2314,7 +2868,7 @@ static int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) * don't have any DDC info. */ for (i = 0; ppModeName[i] != NULL; i++) { - /* FIXME: Use HDisplay and VDisplay instead of mode string */ + if (sscanf(ppModeName[i], "%dx%d", &width, &height) != 2) continue; /* Note: We allow all non-standard modes as long as they do not @@ -2346,7 +2900,7 @@ static int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) 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->VSyncEnd = new->VSyncStart + info->VSyncWidth; new->Clock = info->DotClock; new->Flags |= RADEON_USE_RMX; @@ -2374,6 +2928,44 @@ static int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) 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)) { + tmp = first; + while (tmp) { + if ((p->HDisplay == tmp->HDisplay) && (p->VDisplay == tmp->VDisplay)) break; + tmp = tmp->next; + } + if (!tmp) { + new = xnfcalloc(1, sizeof(DisplayModeRec)); + new->name = xnfalloc(strlen(p->name) + 1); + strcpy(new->name, p->name); + new->HDisplay = p->HDisplay; + new->VDisplay = p->VDisplay; + + /* 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->Flags |= RADEON_USE_RMX; + + new->type |= M_T_DEFAULT; + + new->next = NULL; + new->prev = last; + + last->next = new; + last = new; + } + } + } + /* Close the doubly-linked mode list, if we found any usable modes */ if (last) { last->next = first; @@ -2497,9 +3089,10 @@ static int RADEONValidateCloneModes(ScrnInfoPtr pScrn) int tmp_vdisplay = 0; int i, save_n_hsync, save_n_vrefresh; range save_hsync, save_vrefresh; - char *s; - char **clone_mode_names = NULL; + char *s; + char **clone_mode_names = NULL; Bool ddc_mode = info->ddc_mode; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); /* Save all infomations that will be changed by clone mode validateion */ save_mode = pScrn->modes; @@ -2524,8 +3117,8 @@ static int RADEONValidateCloneModes(ScrnInfoPtr pScrn) clockRanges->minClock = info->pll.min_pll_freq; clockRanges->maxClock = info->pll.max_pll_freq * 10; clockRanges->clockIndex = -1; - clockRanges->interlaceAllowed = FALSE; - clockRanges->doubleScanAllowed = FALSE; + clockRanges->interlaceAllowed = (info->CloneType == MT_CRT); + clockRanges->doubleScanAllowed = (info->CloneType == MT_CRT); /* Only take one clone mode from config file for now, rest of clone * modes will copy from primary head. @@ -2536,14 +3129,19 @@ static int RADEONValidateCloneModes(ScrnInfoPtr pScrn) else count++; clone_mode_names[0] = xnfalloc(strlen(s)+1); sprintf(clone_mode_names[0], "%dx%d", tmp_hdisplay, tmp_vdisplay); - xf86DrvMsg(0, X_INFO, "Clone mode %s in config file is used\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clone mode %s in config file is used\n", clone_mode_names[0]); } } - if (pScrn->display->virtualX < tmp_hdisplay) - pScrn->display->virtualX = tmp_hdisplay; - if (pScrn->display->virtualY < tmp_vdisplay) - pScrn->display->virtualY = tmp_vdisplay; + for (i = 0; i < count; i++) { + if (sscanf(clone_mode_names[i], "%dx%d", + &tmp_hdisplay, &tmp_vdisplay) == 2) { + if (pScrn->display->virtualX < tmp_hdisplay) + pScrn->display->virtualX = tmp_hdisplay; + if (pScrn->display->virtualY < tmp_vdisplay) + pScrn->display->virtualY = tmp_vdisplay; + } + } save_hsync = pScrn->monitor->hsync[0]; save_vrefresh = pScrn->monitor->vrefresh[0]; @@ -2576,48 +3174,25 @@ static int RADEONValidateCloneModes(ScrnInfoPtr pScrn) } } - if ((pScrn->monitor->nVrefresh == 0) || (pScrn->monitor->nHsync == 0) || - (info->CloneType != MT_CRT) || info->ddc_mode) { - unsigned int save_ddc_reg; - save_ddc_reg = info->DDCReg; - switch (info->CloneDDCType) { - 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 = 0; break; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "DDC detection (type %d) for clone modes\n", - info->CloneDDCType); - - /* When primary head has an invalid DDC type, I2C is not - * initialized, so we do it here. - */ - if (!info->ddc2) info->ddc2 = xf86I2CBusInit(info->pI2CBus); - - pScrn->monitor->DDC = RADEONDoDDC(pScrn, NULL); - if (pScrn->monitor->DDC) { - if (info->CloneType == MT_CRT) { - if (pScrn->monitor->nHsync == 0) - RADEONSetSyncRangeFromEdid(pScrn, 1); - if (pScrn->monitor->nVrefresh == 0) - RADEONSetSyncRangeFromEdid(pScrn, 0); - } - } else if (info->ddc_mode) { - ddc_mode = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No DDC data available for clone mode, " - "DDCMode option is dismissed\n"); - } - info->DDCReg = save_ddc_reg; + pScrn->monitor->DDC = pRADEONEnt->MonInfo2; + if (pScrn->monitor->DDC) { + if ((pScrn->monitor->nVrefresh == 0) || (pScrn->monitor->nHsync == 0)) { + if (pScrn->monitor->nHsync == 0) + RADEONSetSyncRangeFromEdid(pScrn, 1); + if (pScrn->monitor->nVrefresh == 0) + RADEONSetSyncRangeFromEdid(pScrn, 0); + } + } else if (info->ddc_mode) { + ddc_mode = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No DDC data available for clone mode, " + "DDCMode option is dismissed\n"); } if (info->CloneType == MT_CRT && !ddc_mode) { modesFound = - xf86ValidateModes(pScrn, pScrn->monitor->Modes, - clone_mode_names, + xf86ValidateModes(pScrn, pScrn->monitor->Modes, + clone_mode_names, clockRanges, NULL, /* linePitches */ 8 * 64, /* minPitch */ @@ -2627,51 +3202,84 @@ static int RADEONValidateCloneModes(ScrnInfoPtr pScrn) 2048, /* maxHeight */ pScrn->display->virtualX, pScrn->display->virtualY, - info->FbMapSize, + info->FbMapSize, LOOKUP_BEST_REFRESH); } else { /* Try to add DDC modes */ - info->IsSecondary = TRUE; /* Fake it */ + info->IsSecondary = TRUE; /*fake secondary head*/ modesFound = RADEONValidateDDCModes(pScrn, clone_mode_names, info->CloneType); - info->IsSecondary = FALSE; /* Restore it!!! */ + info->IsSecondary = FALSE; /* If that fails and we're connect to a flat panel, then try to * add the flat panel modes */ - if (modesFound < 1 && info->DisplayType != MT_CRT) - modesFound = RADEONValidateFPModes(pScrn, clone_mode_names); + if (modesFound < 1 && info->CloneType != MT_CRT) { + modesFound = + xf86ValidateModes(pScrn, pScrn->monitor->Modes, + clone_mode_names, + clockRanges, + NULL, /* linePitches */ + 8 * 64, /* minPitch */ + 8 * 1024, /* maxPitch */ + 64 * pScrn->bitsPerPixel, /* pitchInc */ + 128, /* minHeight */ + 2048, /* maxHeight */ + pScrn->display->virtualX, + pScrn->display->virtualY, + info->FbMapSize, + LOOKUP_BEST_REFRESH); + } } if (modesFound > 0) { + int valid = 0; + save_mode = pScrn->modes; xf86SetCrtcForModes(pScrn, 0); xf86PrintModes(pScrn); for (i = 0; i < modesFound; i++) { + while (pScrn->modes->status != MODE_OK) { pScrn->modes = pScrn->modes->next; } if (!pScrn->modes) break; - clone_mode = xnfcalloc (1, sizeof (DisplayModeRec)); - if (!clone_mode || !pScrn->modes) break; - memcpy(clone_mode, pScrn->modes, sizeof(DisplayModeRec)); - clone_mode->name = xnfalloc(strlen(pScrn->modes->name) + 1); - strcpy(clone_mode->name, pScrn->modes->name); + if (pScrn->modes->Clock != 0.0) { - if (i == 0) { - info->CloneModes = clone_mode; - info->CurCloneMode = clone_mode; - } else { - clone_mode->prev = tmp_mode; - clone_mode->prev->next = clone_mode; - } + clone_mode = xnfcalloc (1, sizeof (DisplayModeRec)); + if (!clone_mode) break; + memcpy(clone_mode, pScrn->modes, sizeof(DisplayModeRec)); + clone_mode->name = xnfalloc(strlen(pScrn->modes->name) + 1); + strcpy(clone_mode->name, pScrn->modes->name); + + if (!info->CurCloneMode) { + info->CloneModes = clone_mode; + info->CurCloneMode = clone_mode; + clone_mode->prev = NULL; + } else { + clone_mode->prev = tmp_mode; + clone_mode->prev->next = clone_mode; + } + valid++; - tmp_mode = clone_mode; - clone_mode->next = NULL; + tmp_mode = clone_mode; + clone_mode->next = NULL; + } pScrn->modes = pScrn->modes->next; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid Clone Mode: %s\n", clone_mode->name); } + + /* no longer needed, free it */ + pScrn->modes = save_mode; + while (pScrn->modes) + xf86DeleteMode(&pScrn->modes, pScrn->modes); + pScrn->modes = NULL; + + /* modepool is no longer needed, free it */ + while (pScrn->modePool) + xf86DeleteMode(&pScrn->modePool, pScrn->modePool); + pScrn->modePool = NULL; + + modesFound = valid; } /* Clone_mode_names list is no longer needed, free it. */ @@ -2686,7 +3294,6 @@ static int RADEONValidateCloneModes(ScrnInfoPtr pScrn) } /* We need to restore all changed info for the primary head */ - pScrn->modes = save_mode; pScrn->monitor->hsync[0] = save_hsync; pScrn->monitor->vrefresh[0] = save_vrefresh; @@ -2703,10 +3310,6 @@ static int RADEONValidateCloneModes(ScrnInfoPtr pScrn) xfree(CRtmp); } - /* modePool is no longer needed, free it */ - while (pScrn->modePool) - xf86DeleteMode(&pScrn->modePool, pScrn->modePool); - pScrn->modePool = NULL; return modesFound; } @@ -2719,10 +3322,8 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) RADEONInfoPtr info = RADEONPTR(pScrn); ClockRangePtr clockRanges; int modesFound; - char *mod = NULL; -#ifndef USE_FB - const char *Sym = NULL; -#endif + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + char *s; /* This option has two purposes: * @@ -2754,6 +3355,10 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) info->ddc_mode = xf86ReturnOptValBool(info->Options, OPTION_DDC_MODE, FALSE); + /* don't use RMX if we have a dual-tdms panels */ + if (pRADEONEnt->MonType2 == MT_DFP) + info->ddc_mode = TRUE; + /* Here is a hack for cloning first display on the second head. If * we don't do this, when both heads are connected, the same CRTC * will be used to drive them according to the capability of the @@ -2767,11 +3372,6 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) */ if (info->HasCRTC2) { if (info->Clone) { - DevUnion *pPriv; - RADEONEntPtr pRADEONEnt; - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], - gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; /* If we have 2 screens from the config file, we don't need * to do clone thing, let each screen handles one head. @@ -2795,34 +3395,90 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) } xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Validating modes on %s head (DDCType: %d) ---------\n", - info->IsSecondary ? "Secondary" : "Primary", - info->DDCType); + "Validating modes on %s head ---------\n", + info->IsSecondary ? "Secondary" : "Primary"); + + if (info->IsSecondary) + pScrn->monitor->DDC = pRADEONEnt->MonInfo2; + else + pScrn->monitor->DDC = pRADEONEnt->MonInfo1; - pScrn->monitor->DDC = RADEONDoDDC(pScrn, pInt10); if (!pScrn->monitor->DDC && info->ddc_mode) { info->ddc_mode = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DDC data available, DDCMode option is dismissed\n"); } - 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); + 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); + } + } } + 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; @@ -2836,6 +3492,7 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) * 'stretched' from their native mode. */ if (info->DisplayType == MT_CRT && !info->ddc_mode) { + modesFound = xf86ValidateModes(pScrn, pScrn->monitor->Modes, @@ -2865,6 +3522,7 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) 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 @@ -2881,8 +3539,54 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) /* If that fails and we're connect to a flat panel, then try to * add the flat panel modes */ - if (modesFound < 1 && info->DisplayType != MT_CRT) - modesFound = RADEONValidateFPModes(pScrn, pScrn->display->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 */ + 64 * pScrn->bitsPerPixel, /* pitchInc */ + 128, /* minHeight */ + 2048, /* 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) { @@ -2897,11 +3601,6 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) } return FALSE; } - - /* Setup the screen's clockRanges for the VidMode extension */ - pScrn->clockRanges = xnfcalloc(sizeof(*(pScrn->clockRanges)), 1); - memcpy(pScrn->clockRanges, clockRanges, sizeof(*clockRanges)); - pScrn->clockRanges->strategy = LOOKUP_BEST_REFRESH; } xf86SetCrtcForModes(pScrn, 0); @@ -2915,9 +3614,9 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) if ((clone_mode->HDisplay > pScrn->virtualX) || (clone_mode->VDisplay > pScrn->virtualY)) { pScrn->virtualX = - pScrn->display->virtualX = clone_mode->HDisplay; + pScrn->display->virtualX = clone_mode->HDisplay; pScrn->virtualY = - pScrn->display->virtualY = clone_mode->VDisplay; + pScrn->display->virtualY = clone_mode->VDisplay; RADEONSetPitch(pScrn); } if (!clone_mode->next) break; @@ -2932,23 +3631,9 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) xf86SetDpi(pScrn, 0, 0); /* Get ScreenInit function */ -#ifdef USE_FB - mod = "fb"; -#else - switch (pScrn->bitsPerPixel) { - case 8: mod = "cfb"; Sym = "cfbScreenInit"; break; - case 16: mod = "cfb16"; Sym = "cfb16ScreenInit"; break; - case 32: mod = "cfb32"; Sym = "cfb32ScreenInit"; break; - } -#endif - - if (mod && !xf86LoadSubModule(pScrn, mod)) return FALSE; + if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; -#ifdef USE_FB xf86LoaderReqSymLists(fbSymbols, NULL); -#else - xf86LoaderReqSymbols(Sym, NULL); -#endif info->CurrentLayout.displayWidth = pScrn->displayWidth; info->CurrentLayout.mode = pScrn->currentMode; @@ -3024,10 +3709,10 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) } info->agpMode = RADEON_DEFAULT_AGP_MODE; - info->agpSize = RADEON_DEFAULT_AGP_SIZE; + info->gartSize = RADEON_DEFAULT_GART_SIZE; info->ringSize = RADEON_DEFAULT_RING_SIZE; info->bufSize = RADEON_DEFAULT_BUFFER_SIZE; - info->agpTexSize = RADEON_DEFAULT_AGP_TEX_SIZE; + info->gartTexSize = RADEON_DEFAULT_GART_TEX_SIZE; info->agpFastWrite = RADEON_DEFAULT_AGP_FAST_WRITE; info->CPusecTimeout = RADEON_DEFAULT_CP_TIMEOUT; @@ -3050,67 +3735,67 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling AGP Fast Write\n"); } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AGP Fast Write disabled by default\n"); } + } - if (xf86GetOptValInteger(info->Options, - OPTION_AGP_SIZE, (int *)&(info->agpSize))) { - switch (info->agpSize) { - case 4: - case 8: - case 16: - case 32: - case 64: - case 128: - case 256: - break; - - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Illegal AGP size: %d MB\n", info->agpSize); - return FALSE; - } - } + if (xf86GetOptValInteger(info->Options, + OPTION_GART_SIZE, (int *)&(info->gartSize))) { + switch (info->gartSize) { + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + case 256: + break; - if (xf86GetOptValInteger(info->Options, - OPTION_RING_SIZE, &(info->ringSize))) { - if (info->ringSize < 1 || info->ringSize >= (int)info->agpSize) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Illegal ring buffer size: %d MB\n", - info->ringSize); - return FALSE; - } + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Illegal GART size: %d MB\n", info->gartSize); + return FALSE; } + } - if (xf86GetOptValInteger(info->Options, - OPTION_BUFFER_SIZE, &(info->bufSize))) { - if (info->bufSize < 1 || info->bufSize >= (int)info->agpSize) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Illegal vertex/indirect buffers size: %d MB\n", - info->bufSize); - return FALSE; - } - if (info->bufSize > 2) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Illegal vertex/indirect buffers size: %d MB\n", - info->bufSize); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Clamping vertex/indirect buffers size to 2 MB\n"); - info->bufSize = 2; - } + if (xf86GetOptValInteger(info->Options, + OPTION_RING_SIZE, &(info->ringSize))) { + if (info->ringSize < 1 || info->ringSize >= (int)info->gartSize) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Illegal ring buffer size: %d MB\n", + info->ringSize); + return FALSE; } + } - if (info->ringSize + info->bufSize + info->agpTexSize > - (int)info->agpSize) { + if (xf86GetOptValInteger(info->Options, + OPTION_BUFFER_SIZE, &(info->bufSize))) { + if (info->bufSize < 1 || info->bufSize >= (int)info->gartSize) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Buffers are too big for requested AGP space\n"); + "Illegal vertex/indirect buffers size: %d MB\n", + info->bufSize); return FALSE; } + if (info->bufSize > 2) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Illegal vertex/indirect buffers size: %d MB\n", + info->bufSize); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Clamping vertex/indirect buffers size to 2 MB\n"); + info->bufSize = 2; + } + } - info->agpTexSize = info->agpSize - (info->ringSize + info->bufSize); + if (info->ringSize + info->bufSize + info->gartTexSize > + (int)info->gartSize) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Buffers are too big for requested GART space\n"); + return FALSE; } + info->gartTexSize = info->gartSize - (info->ringSize + info->bufSize); + if (xf86GetOptValInteger(info->Options, OPTION_USEC_TIMEOUT, &(info->CPusecTimeout))) { /* This option checked by the RADEON DRM kernel module */ @@ -3129,7 +3814,7 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) * for dedicated 3d rendering boxes */ info->noBackBuffer = xf86ReturnOptValBool(info->Options, - OPTION_NO_BACKBUFFER, + OPTION_NO_BACKBUFFER, FALSE); if (info->noBackBuffer) { @@ -3170,7 +3855,8 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) RADEONInfoPtr info; xf86Int10InfoPtr pInt10 = NULL; void *int10_save = NULL; - + const char *s; + RADEONTRACE(("RADEONPreInit\n")); if (pScrn->numEntities != 1) return FALSE; @@ -3182,14 +3868,34 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) info->CurCloneMode = NULL; info->CloneModes = NULL; info->IsSwitching = FALSE; + info->MMIO = NULL; - info->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + info->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); if (info->pEnt->location.type != BUS_PCI) goto fail; info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); info->PciTag = pciTag(info->PciInfo->bus, info->PciInfo->device, info->PciInfo->func); + info->MMIOAddr = info->PciInfo->memBase[2] & 0xffffff00; + if (info->pEnt->device->IOBase) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "MMIO address override, using 0x%08lx instead of 0x%08lx\n", + info->pEnt->device->IOBase, + info->MMIOAddr); + info->MMIOAddr = info->pEnt->device->IOBase; + } else if (!info->MMIOAddr) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n"); + goto fail1; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MMIO registers at 0x%08lx\n", info->MMIOAddr); + + if(!RADEONMapMMIO(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Memory map the MMIO region failed\n"); + goto fail1; + } #if !defined(__alpha__) if (xf86GetPciDomain(info->PciTag) || @@ -3200,39 +3906,29 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) * going to run it again - so make sure to "fix up" the card * so that (1) we can read the BIOS ROM and (2) the BIOS will * get the memory config right. - */ + */ RADEONPreInt10Save(pScrn, &int10_save); #endif - if (xf86IsEntityShared(pScrn->entityList[0])) { - if (xf86IsPrimInitDone(pScrn->entityList[0])) { - DevUnion *pPriv; - RADEONEntPtr pRADEONEnt; + if (xf86IsEntityShared(info->pEnt->index)) { + if (xf86IsPrimInitDone(info->pEnt->index)) { + + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); info->IsSecondary = TRUE; - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], - gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; - if (pRADEONEnt->BypassSecondary) { - pRADEONEnt->HasSecondary = FALSE; + if (!pRADEONEnt->HasSecondary) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Only one monitor detected, Second screen " "will NOT be created\n"); - return FALSE; + goto fail2; } pRADEONEnt->pSecondaryScrn = pScrn; } else { - DevUnion *pPriv; - RADEONEntPtr pRADEONEnt; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - xf86SetPrimInitDone(pScrn->entityList[0]); - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], - gRADEONEntityIndex); + xf86SetPrimInitDone(info->pEnt->index); - pRADEONEnt = pPriv->ptr; pRADEONEnt->pPrimaryScrn = pScrn; - pRADEONEnt->IsDRIEnabled = FALSE; - pRADEONEnt->BypassSecondary = FALSE; pRADEONEnt->RestorePrimary = FALSE; pRADEONEnt->IsSecondaryRestored = FALSE; } @@ -3241,6 +3937,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) if (flags & PROBE_DETECT) { RADEONProbeDDC(pScrn, info->pEnt->index); RADEONPostInt10Check(pScrn, int10_save); + if(info->MMIO) RADEONUnmapMMIO(pScrn); return TRUE; } @@ -3248,7 +3945,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) xf86LoaderReqSymLists(vgahwSymbols, NULL); if (!vgaHWGetHWRec(pScrn)) { RADEONFreeRec(pScrn); - return FALSE; + goto fail2; } vgaHWGetIOBase(VGAHWPTR(pScrn)); @@ -3291,6 +3988,18 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) info->videoKey = 0x1E; } + info->DispPriority = 1; + if ((s = xf86GetOptValString(info->Options, OPTION_DISP_PRIORITY))) { + if (strcmp(s, "AUTO") == 0) { + info->DispPriority = 1; + } else if (strcmp(s, "BIOS") == 0) { + info->DispPriority = 0; + } else if (strcmp(s, "HIGH") == 0) { + info->DispPriority = 2; + } else + info->DispPriority = 1; + } + if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) { /* check for Linux framebuffer device */ @@ -3321,17 +4030,13 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) if (!RADEONPreInitConfig(pScrn)) goto fail; -#if !defined(__powerpc__) + RADEONPreInitDDC(pScrn); + if (!RADEONGetBIOSParameters(pScrn, pInt10)) goto fail; -#else - /* Force type to CRT since we currently can't read BIOS to tell us - * what kind of heads we have. - */ - info->DisplayType = MT_CRT; -#endif - RADEONPreInitDDC(pScrn); + if (info->DisplayType == MT_DFP) + RADEONGetTMDSInfo(pScrn); if (!RADEONGetPLLParameters(pScrn)) goto fail; @@ -3357,6 +4062,9 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) if (pInt10) xf86FreeInt10(pInt10); + if(info->MMIO) RADEONUnmapMMIO(pScrn); + info->MMIO = NULL; + xf86DrvMsg(pScrn->scrnIndex, X_NOTICE, "For information on using the multimedia capabilities\n of this" " adapter, please see http://gatos.sf.net.\n"); @@ -3365,7 +4073,10 @@ 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); @@ -3377,7 +4088,13 @@ fail: xf86FreeInt10(pInt10); vgaHWFreeHWRec(pScrn); + + fail2: + if(info->MMIO) RADEONUnmapMMIO(pScrn); + info->MMIO = NULL; + fail1: RADEONFreeRec(pScrn); + return FALSE; } @@ -3480,7 +4197,7 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, 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. @@ -3591,8 +4308,8 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #ifdef XF86DRI /* Setup DRI after visuals have been - established, but before cfbScreenInit is - called. cfbScreenInit will eventually + established, but before fbScreenInit is + called. fbScreenInit will eventually call the driver's InitGLXVisuals call back. */ { @@ -3615,7 +4332,16 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) (pScrn->displayWidth * pScrn->virtualY * info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024); info->directRenderingEnabled = FALSE; - } else if (info->ChipFamily >= CHIP_FAMILY_R300) { + } else if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200) || + (info->ChipFamily == CHIP_FAMILY_RS300)) { + info->directRenderingEnabled = FALSE; + xf86DrvMsg(scrnIndex, X_WARNING, + "Direct rendering not yet supported on " + "IGP320/330/340/350, 7000, 9000 integrated chips\n"); + } else if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) { info->directRenderingEnabled = FALSE; xf86DrvMsg(scrnIndex, X_WARNING, "Direct rendering not yet supported on " @@ -3625,9 +4351,9 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) info->directRenderingEnabled = FALSE; else { /* Xinerama has sync problem with DRI, disable it for now */ - if (xf86IsEntityShared(pScrn->entityList[0])) { + if (xf86IsEntityShared(info->pEnt->index)) { info->directRenderingEnabled = FALSE; - xf86DrvMsg(scrnIndex, X_WARNING, + xf86DrvMsg(scrnIndex, X_WARNING, "Direct Rendering Disabled -- " "Dual-head configuration is not working with " "DRI at present.\n" @@ -3637,53 +4363,16 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) info->directRenderingEnabled = RADEONDRIScreenInit(pScreen); } - - if (xf86IsEntityShared(pScrn->entityList[0])) { - DevUnion *pPriv; - RADEONEntPtr pRADEONEnt; - - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], - gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; - pRADEONEnt->IsDRIEnabled = info->directRenderingEnabled; - } } } } #endif -#ifdef USE_FB if (!fbScreenInit(pScreen, info->FB, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel)) return FALSE; -#else - switch (pScrn->bitsPerPixel) { - case 8: - if (!cfbScreenInit(pScreen, info->FB, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth)) - return FALSE; - break; - case 16: - if (!cfb16ScreenInit(pScreen, info->FB, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth)) - return FALSE; - break; - case 32: - if (!cfb32ScreenInit(pScreen, info->FB, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth)) - return FALSE; - break; - default: - xf86DrvMsg(scrnIndex, X_ERROR, - "Invalid bpp (%d)\n", pScrn->bitsPerPixel); - return FALSE; - } -#endif xf86SetBlackWhitePixels(pScreen); @@ -3703,10 +4392,8 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } } -#ifdef USE_FB /* Must be after RGB order fixed */ fbPictureInit (pScreen, 0, 0); -#endif #ifdef RENDER if (PictureGetSubpixelOrder (pScreen) == SubPixelUnknown) @@ -3754,13 +4441,13 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d MB AGP aperture\n", info->agpSize); + "Using %d MB GART aperture\n", info->gartSize); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %d MB for the ring buffer\n", info->ringSize); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %d MB for vertex/indirect buffers\n", info->bufSize); xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %d MB for AGP textures\n", info->agpTexSize); + "Using %d MB for GART textures\n", info->gartTexSize); /* Try for front, back, depth, and three framebuffers worth of * pixmap cache. Should be enough for a fullscreen background @@ -3777,7 +4464,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) info->textureSize = info->FbMapSize - 4 * bufferSize - depthSize; } if (info->textureSize < (int)info->FbMapSize / 2) { - info->textureSize = info->FbMapSize - 3 * bufferSize - depthSize; + info->textureSize = info->FbMapSize - 3 * bufferSize - depthSize; } /* If there's still no space for textures, try without pixmap cache */ if (info->textureSize < 0) { @@ -4008,7 +4695,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) int width, height; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using hardware cursor (scanline %d)\n", + "Using hardware cursor (scanline %ld)\n", info->cursor_start / pScrn->displayWidth / info->CurrentLayout.pixel_bytes); if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, @@ -4038,9 +4725,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) | CMAP_RELOAD_ON_MODE_SWITCH)) return FALSE; /* DPMS setup */ -#ifdef DPMSExtension xf86DPMSInit(pScreen, RADEONDisplayPowerManagementSet, 0); -#endif RADEONInitVideo(pScreen); @@ -4058,12 +4743,16 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #ifdef XF86DRI /* DRI finalization */ if (info->directRenderingEnabled) { - /* Now that mi, cfb, drm and others have + /* Now that mi, fb, drm and others have done their thing, complete the DRI setup. */ info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen); } if (info->directRenderingEnabled) { + if ((info->DispPriority == 1) && (!info->IsPCI)) { + /* we need to re-calculate bandwidth because of AGPMode difference. */ + RADEONInitDispBandwidth(pScrn); + } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering disabled\n"); @@ -4103,13 +4792,11 @@ static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, if (info->HasCRTC2 && !info->IsSwitching && info->ChipFamily != CHIP_FAMILY_R200 && - info->ChipFamily != CHIP_FAMILY_R300) { - DevUnion *pPriv; - RADEONEntPtr pRADEONEnt; + info->ChipFamily != CHIP_FAMILY_R300 && + info->ChipFamily != CHIP_FAMILY_R350 && + info->ChipFamily != CHIP_FAMILY_RV350) { CARD32 tmp; - - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); if (pRADEONEnt->HasSecondary || info->Clone) { tmp = INREG(RADEON_DAC_CNTL2); @@ -4171,6 +4858,8 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, OUTREG(RADEON_CRTC_OFFSET, restore->crtc_offset); OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); 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); } /* Write CRTC2 registers */ @@ -4188,18 +4877,14 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); - if (info->ChipFamily == CHIP_FAMILY_R200 || - info->ChipFamily == CHIP_FAMILY_R300) { + OUTREG(RADEON_TV_DAC_CNTL, 0x00280203); + if ((info->ChipFamily == CHIP_FAMILY_R200) || + (info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) { OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); } else { OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); - if (info->IsDell) { - /* Workaround for DELL card. BIOS doesn't initialize - * TV_DAC_CNTL to a correct value which causes too high - * contrast for the second CRT (using TV_DAC). - */ - OUTREG(RADEON_TV_DAC_CNTL, 0x00280203); - } } OUTREG(RADEON_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); @@ -4209,13 +4894,14 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset); OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch); + OUTREG(RADEON_DISP2_MERGE_CNTL, restore->disp2_merge_cntl); - if (info->DisplayType == MT_DFP || info->CloneType == MT_DFP) { + if ((info->DisplayType == MT_DFP && info->IsSecondary) || + info->CloneType == MT_DFP) { OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp2_h_sync_strt_wid); OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp2_v_sync_strt_wid); OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); } - #if 0 /* Hack for restoring text mode -- fixed elsewhere */ usleep(100000); @@ -4234,11 +4920,31 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) OUTREG(RADEON_FP_H_SYNC_STRT_WID, restore->fp_h_sync_strt_wid); OUTREG(RADEON_FP_V_SYNC_STRT_WID, restore->fp_v_sync_strt_wid); 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); - if (info->DisplayType == MT_LCD) { + /* old AIW Radeon has some BIOS initialization problem + * with display buffer underflow, only occurs to DFP + */ + if (!info->HasCRTC2) + OUTREG(RADEON_GRPH_BUFFER_CNTL, + INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000); + + if (info->DisplayType != MT_DFP) { + unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch); + + 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 + */ + if (!(restore->lvds_gen_cntl & RADEON_LVDS_ON)) { + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); + } + } + tmp = INREG(RADEON_LVDS_GEN_CNTL); if ((tmp & (RADEON_LVDS_ON | RADEON_LVDS_BLON)) == (restore->lvds_gen_cntl & (RADEON_LVDS_ON | RADEON_LVDS_BLON))) { @@ -4254,6 +4960,12 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) OUTREG(RADEON_LVDS_GEN_CNTL, restore->lvds_gen_cntl); } } + + if (info->IsMobility || info->IsIGP) { + if (!(restore->lvds_gen_cntl & RADEON_LVDS_ON)) { + OUTPLL(RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + } + } } } @@ -4316,6 +5028,18 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + if (info->IsMobility) { + /* A temporal workaround for the occational blanking on certain laptop panels. + This appears to related to the PLL divider registers (fail to lock?). + It occurs even when all dividers are the same with their old settings. + In this case we really don't need to fiddle with PLL registers. + By doing this we can avoid the blanking problem with some panels. + */ + if ((restore->ppll_ref_div == (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) && + (restore->ppll_div_3 == (INPLL(pScrn, RADEON_PPLL_DIV_3) & (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) + return; + } + OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, RADEON_VCLK_SRC_SEL_CPUCLK, ~(RADEON_VCLK_SRC_SEL_MASK)); @@ -4333,7 +5057,9 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, RADEON_PLL_DIV_SEL, ~(RADEON_PLL_DIV_SEL)); - if (info->ChipFamily == CHIP_FAMILY_R300) { + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) { if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { /* When restoring console mode, use saved PPLL_REF_DIV * setting. @@ -4344,7 +5070,7 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, } else { /* R300 uses ref_div_acc field as real ref divider */ OUTPLLP(pScrn, RADEON_PPLL_REF_DIV, - (restore->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), + (restore->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), ~R300_PPLL_REF_DIV_ACC_MASK); } } else { @@ -4373,6 +5099,11 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, | RADEON_PPLL_ATOMIC_UPDATE_EN | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); + xf86DrvMsg(0, X_INFO, "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); + RADEONTRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", restore->ppll_ref_div, restore->ppll_div_3, @@ -4481,26 +5212,19 @@ static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore) /* Write out state to define a new video mode */ static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) { - RADEONInfoPtr info = RADEONPTR(pScrn); - DevUnion *pPriv; - RADEONEntPtr pRADEONEnt; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); static RADEONSaveRec restore0; /* For Non-dual head card, we don't have private field in the Entity */ if (!info->HasCRTC2) { RADEONRestoreCommonRegisters(pScrn, restore); RADEONRestoreCrtcRegisters(pScrn, restore); - if ((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) { - RADEONRestoreFPRegisters(pScrn, restore); - } + RADEONRestoreFPRegisters(pScrn, restore); RADEONRestorePLLRegisters(pScrn, restore); return; } - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; - RADEONTRACE(("RADEONRestoreMode(%p)\n", restore)); /* When changing mode with Dual-head card, care must be taken for @@ -4513,7 +5237,7 @@ static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) * we may get a blank screen. */ if (info->IsSecondary) { - if (!pRADEONEnt->RestorePrimary) + if (!pRADEONEnt->RestorePrimary && !info->IsSwitching) RADEONRestoreCommonRegisters(pScrn, restore); RADEONRestoreCrtc2Registers(pScrn, restore); RADEONRestorePLL2Registers(pScrn, restore); @@ -4523,15 +5247,10 @@ static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) pRADEONEnt->IsSecondaryRestored = TRUE; if (pRADEONEnt->RestorePrimary) { - RADEONInfoPtr info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn); pRADEONEnt->RestorePrimary = FALSE; RADEONRestoreCrtcRegisters(pScrn, &restore0); - if ((info0->DisplayType == MT_DFP) || - (info0->DisplayType == MT_LCD)) { - RADEONRestoreFPRegisters(pScrn, &restore0); - } - + RADEONRestoreFPRegisters(pScrn, &restore0); RADEONRestorePLLRegisters(pScrn, &restore0); pRADEONEnt->IsSecondaryRestored = FALSE; } @@ -4549,10 +5268,7 @@ static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) pRADEONEnt->IsSecondaryRestored = FALSE; RADEONRestoreCrtcRegisters(pScrn, restore); - if ((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) { - RADEONRestoreFPRegisters(pScrn, restore); - } + RADEONRestoreFPRegisters(pScrn, restore); RADEONRestorePLLRegisters(pScrn, restore); } else { memcpy(&restore0, restore, sizeof(restore0)); @@ -4583,6 +5299,8 @@ static void RADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->cap1_trig_cntl = INREG(RADEON_CAP1_TRIG_CNTL); save->bus_cntl = INREG(RADEON_BUS_CNTL); save->surface_cntl = INREG(RADEON_SURFACE_CNTL); + save->grph_buffer_cntl = INREG(RADEON_GRPH_BUFFER_CNTL); + save->grph2_buffer_cntl = INREG(RADEON_GRPH2_BUFFER_CNTL); } /* Read miscellaneous registers which might be destroyed by an fbdevHW call */ @@ -4623,6 +5341,8 @@ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->crtc_offset = INREG(RADEON_CRTC_OFFSET); save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); save->crtc_pitch = INREG(RADEON_CRTC_PITCH); + save->disp_merge_cntl = INREG(RADEON_DISP_MERGE_CNTL); + save->crtc_more_cntl = INREG(RADEON_CRTC_MORE_CNTL); } /* Read flat panel registers */ @@ -4641,6 +5361,13 @@ static void RADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->lvds_gen_cntl = INREG(RADEON_LVDS_GEN_CNTL); save->lvds_pll_cntl = INREG(RADEON_LVDS_PLL_CNTL); save->tmds_pll_cntl = INREG(RADEON_TMDS_PLL_CNTL); + save->tmds_transmitter_cntl= INREG(RADEON_TMDS_TRANSMITTER_CNTL); + save->bios_5_scratch = INREG(RADEON_BIOS_5_SCRATCH); + + if (info->ChipFamily == CHIP_FAMILY_RV280) { + /* bit 22 of TMDS_PLL_CNTL is read-back inverted */ + save->tmds_pll_cntl ^= (1 << 22); + } } /* Read CRTC2 registers */ @@ -4665,7 +5392,7 @@ static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) save->fp2_h_sync_strt_wid = INREG (RADEON_FP_H2_SYNC_STRT_WID); save->fp2_v_sync_strt_wid = INREG (RADEON_FP_V2_SYNC_STRT_WID); save->fp2_gen_cntl = INREG (RADEON_FP2_GEN_CNTL); - + save->disp2_merge_cntl = INREG(RADEON_DISP2_MERGE_CNTL); } /* Read PLL registers */ @@ -4735,11 +5462,7 @@ static void RADEONSaveMode(ScrnInfoPtr pScrn, RADEONSavePtr save) RADEONSavePLLRegisters(pScrn, save); RADEONSaveCommonRegisters(pScrn, save); RADEONSaveCrtcRegisters(pScrn, save); - - if ((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) { - RADEONSaveFPRegisters(pScrn, save); - } + RADEONSaveFPRegisters(pScrn, save); if (info->Clone) { RADEONSaveCrtc2Registers(pScrn, save); @@ -4774,7 +5497,7 @@ static void RADEONSave(ScrnInfoPtr pScrn) */ vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */ #else - vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL); /* Save mode + vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); /* Save mode * & fonts & cmap */ #endif @@ -4813,12 +5536,14 @@ static void RADEONRestore(ScrnInfoPtr pScrn) if (info->R300CGWorkaround) R300CGWorkaround(pScrn); OUTREG(RADEON_RBBM_SOFT_RESET, restore->rbbm_soft_reset); OUTREG(RADEON_DP_DATATYPE, restore->dp_datatype); + OUTREG(RADEON_GRPH_BUFFER_CNTL, restore->grph_buffer_cntl); + OUTREG(RADEON_GRPH2_BUFFER_CNTL, restore->grph2_buffer_cntl); #if 0 /* M6 card has trouble restoring text mode for its CRT. * This is fixed elsewhere and will be removed in the future. */ - if ((xf86IsEntityShared(pScrn->entityList[0]) || info->Clone) + if ((xf86IsEntityShared(info->pEnt->index) || info->Clone) && info->IsM6) OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); #endif @@ -4846,15 +5571,10 @@ static void RADEONRestore(ScrnInfoPtr pScrn) #endif vgaHWLock(hwp); } else { - DevUnion *pPriv; - RADEONEntPtr pRADEONEnt; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); ScrnInfoPtr pScrn0; vgaHWPtr hwp0; - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], - gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; - pScrn0 = pRADEONEnt->pPrimaryScrn; hwp0 = VGAHWPTR(pScrn0); vgaHWUnlock(hwp0); @@ -4890,6 +5610,322 @@ static void RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; } +/* Calculate display buffer watermark to prevent buffer underflow */ +static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONInfoPtr info2 = NULL; + + DisplayModePtr mode1, mode2; + + CARD32 temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0; + float mem_tcas; + int k1, c; + CARD32 MemTrcdExtMemCntl[4] = {1, 2, 3, 4}; + CARD32 MemTrpExtMemCntl[4] = {1, 2, 3, 4}; + CARD32 MemTrasExtMemCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + CARD32 MemTrcdMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + CARD32 MemTrpMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + CARD32 MemTrasMemTimingCntl[16] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + float MemTcas[8] = {0, 1, 2, 3, 0, 1.5, 2.5, 0}; + float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7}; + float MemTrbs[8] = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5}; + + float mem_bw, peak_disp_bw; + float min_mem_eff = 0.8; + float sclk_eff, sclk_delay; + float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk; + float disp_latency, disp_latency_overhead, disp_drain_rate, disp_drain_rate2; + float pix_clk, pix_clk2; /* in MHz */ + int cur_size = 16; /* in octawords */ + int critical_point, critical_point2; + int stop_req, max_stop_req; + float read_return_rate, time_disp1_drop_priority; + + if (pRADEONEnt->pSecondaryScrn) { + if (info->IsSecondary) return; + info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); + } else if (info->Clone) info2 = info; + + /* + * Determine if there is enough bandwidth for current display mode + */ + mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1); + + mode1 = info->CurrentLayout.mode; + if (info->Clone) + mode2 = info->CurCloneMode; + else if ((pRADEONEnt->HasSecondary) && info2) + mode2 = info2->CurrentLayout.mode; + else + mode2 = NULL; + + pix_clk = mode1->Clock/1000.0; + if (mode2) + pix_clk2 = mode2->Clock/1000.0; + else + pix_clk2 = 0; + + peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes); + if (info2) + peak_disp_bw += (pix_clk2 * info2->CurrentLayout.pixel_bytes); + + if (peak_disp_bw >= mem_bw * min_mem_eff) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "You may not have enough display bandwidth for current mode\n" + "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); + } + + /* CRTC1 + Set GRPH_BUFFER_CNTL register using h/w defined optimal values. + GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] + */ + stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16; + + /* setup Max GRPH_STOP_REQ default value */ + if ((info->ChipFamily == CHIP_FAMILY_RV100) || + (info->ChipFamily == CHIP_FAMILY_RV200) || + (info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280) || + (info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200) || + (info->ChipFamily == CHIP_FAMILY_RS300)) + max_stop_req = 0x5c; + else + max_stop_req = 0x7c; + if (stop_req > max_stop_req) + stop_req = max_stop_req; + + /* Get values from the EXT_MEM_CNTL register...converting its contents. */ + temp = INREG(RADEON_MEM_TIMING_CNTL); + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + mem_trcd = MemTrcdExtMemCntl[(temp & 0x0c) >> 2]; + mem_trp = MemTrpExtMemCntl[ (temp & 0x03) >> 0]; + mem_tras = MemTrasExtMemCntl[(temp & 0x70) >> 4]; + } else { /* RV200 and later */ + mem_trcd = MemTrcdMemTimingCntl[(temp & 0x07) >> 0]; + mem_trp = MemTrpMemTimingCntl[ (temp & 0x700) >> 8]; + mem_tras = MemTrasMemTimingCntl[(temp & 0xf000) >> 12]; + } + + /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ + temp = INREG(RADEON_MEM_SDRAM_MODE_REG); + data = (temp & (7<<20)) >> 20; + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + mem_tcas = MemTcas [data]; + } else { + mem_tcas = MemTcas2 [data]; + } + + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) { + + /* on the R300, Tcas is included in Trbs. + */ + temp = INREG(RADEON_MEM_CNTL); + data = (R300_MEM_NUM_CHANNELS_MASK & temp); + if (data == 2) { + if (R300_MEM_USE_CD_CH_ONLY & temp) { + temp = INREG(R300_MC_IND_INDEX); + temp &= ~R300_MC_IND_ADDR_MASK; + temp |= R300_MC_READ_CNTL_CD_mcind; + OUTREG(R300_MC_IND_INDEX, temp); + temp = INREG(R300_MC_IND_DATA); + data = (R300_MEM_RBS_POSITION_C_MASK & temp); + } else { + temp = INREG(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + } else { + temp = INREG(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + + mem_trbs = MemTrbs[data]; + mem_tcas += mem_trbs; + } + + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + /* DDR64 SCLK_EFF = SCLK for analysis */ + sclk_eff = info->sclk; + } else { +#ifdef XF86DRI + if (info->directRenderingEnabled) + sclk_eff = info->sclk - (info->agpMode * 50.0 / 3.0); + else +#endif + sclk_eff = info->sclk; + } + + /* Find the memory controller latency for the display client. + */ + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) { + /*not enough for R350 ???*/ + /* + if (!mode2) sclk_delay = 150; + else { + if (info->RamWidth == 256) sclk_delay = 87; + else sclk_delay = 97; + } + */ + sclk_delay = 250; + } else { + if ((info->ChipFamily == CHIP_FAMILY_RV100) || + info->IsIGP) { + if (info->IsDDR) sclk_delay = 41; + else sclk_delay = 33; + } else { + if (info->RamWidth == 128) sclk_delay = 57; + else sclk_delay = 41; + } + } + + mc_latency_sclk = sclk_delay / sclk_eff; + + if (info->IsDDR) { + if (info->RamWidth == 32) { + k1 = 40; + c = 3; + } else { + k1 = 20; + c = 1; + } + } else { + k1 = 40; + c = 3; + } + mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) / + info->mclk) + (4.0 / sclk_eff); + + /* + HW cursor time assuming worst case of full size colour cursor. + */ + cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk; + cur_latency_sclk = cur_size / sclk_eff; + + /* + Find the total latency for the display data. + */ + disp_latency_overhead = 8.0 / info->sclk; + mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk; + mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk; + disp_latency = MAX(mc_latency_mclk, mc_latency_sclk); + + /* + 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); + else + disp_drain_rate2 = 0; + + /* + Find the critical point of the display buffer. + */ + critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5); + + /* ???? */ + /* + temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT; + if (critical_point < temp) critical_point = temp; + */ + if (info->DispPriority == 2) { + if (mode2) { + /*??some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ + if (info->ChipFamily == CHIP_FAMILY_R300) + critical_point += 0x10; + else + critical_point = 0; + } + else + critical_point = 0; + } + + /* + The critical point should never be above max_stop_req-4. Setting + GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. + */ + if (max_stop_req - critical_point < 4) critical_point = 0; + + temp = info->SavedReg.grph_buffer_cntl; + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((info->ChipFamily == CHIP_FAMILY_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + /* + Write the result into the register. + */ + 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", + info->SavedReg.grph_buffer_cntl, INREG(RADEON_GRPH_BUFFER_CNTL))); + + if (mode2) { + stop_req = mode2->HDisplay * info2->CurrentLayout.pixel_bytes / 16; + + if (stop_req > max_stop_req) stop_req = max_stop_req; + + temp = info->SavedReg.grph2_buffer_cntl; + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((info->ChipFamily == CHIP_FAMILY_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) + critical_point2 = 0; + else { + read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128)); + time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate); + + critical_point2 = (CARD32)((disp_latency + time_disp1_drop_priority + + disp_latency) * disp_drain_rate2 + 0.5); + + if (info->DispPriority == 2) { + if (info->ChipFamily == CHIP_FAMILY_R300) + critical_point2 += 0x10; + else + critical_point2 = 0; + } + + if (max_stop_req - critical_point2 < 4) critical_point2 = 0; + + } + + 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", + info->SavedReg.grph2_buffer_cntl, INREG(RADEON_GRPH2_BUFFER_CNTL))); + } +} + /* Define CRTC registers for requested video mode */ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, DisplayModePtr mode, RADEONInfoPtr info) @@ -4901,24 +5937,22 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, int hsync_wid; int hsync_fudge; int vsync_wid; - int bytpp; int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; int hsync_fudge_fp[] = { 0x02, 0x02, 0x00, 0x00, 0x05, 0x05 }; switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; bytpp = 0; break; - case 8: format = 2; bytpp = 1; break; - case 15: format = 3; bytpp = 2; break; /* 555 */ - case 16: format = 4; bytpp = 2; break; /* 565 */ - case 24: format = 5; bytpp = 3; break; /* RGB */ - case 32: format = 6; bytpp = 4; break; /* xRGB */ + 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; } - RADEONTRACE(("Format = %d (%d bytes per pixel)\n", format, bytpp)); if ((info->DisplayType == MT_DFP) || (info->DisplayType == MT_LCD)) { @@ -5015,7 +6049,19 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, (pScrn->bitsPerPixel * 8)); save->crtc_pitch |= save->crtc_pitch << 16; + /* Some versions of BIOS setup CRTC_MORE_CNTL for a DFP, if we + have a CRT here, it should be cleared to avoild a blank screen. + */ + if (info->DisplayType == MT_CRT) + save->crtc_more_cntl = (info->SavedReg.crtc_more_cntl & + ~(RADEON_CRTC_H_CUTOFF_ACTIVE_EN | + RADEON_CRTC_V_CUTOFF_ACTIVE_EN)); + else + save->crtc_more_cntl = info->SavedReg.crtc_more_cntl; + 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 switch (pScrn->bitsPerPixel) { @@ -5040,29 +6086,28 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, DisplayModePtr mode, RADEONInfoPtr info) { unsigned char *RADEONMMIO = info->MMIO; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); int format; int hsync_start; int hsync_wid; int hsync_fudge; int vsync_wid; - int bytpp; int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; bytpp = 0; break; - case 8: format = 2; bytpp = 1; break; - case 15: format = 3; bytpp = 2; break; /* 555 */ - case 16: format = 4; bytpp = 2; break; /* 565 */ - case 24: format = 5; bytpp = 3; break; /* RGB */ - case 32: format = 6; bytpp = 4; break; /* xRGB */ + 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; } - RADEONTRACE(("Format = %d (%d bytes per pixel)\n", format, bytpp)); hsync_fudge = hsync_fudge_default[format-1]; @@ -5082,27 +6127,45 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, /* Turn CRT on in case the first head is a DFP */ save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; save->dac2_cntl = info->SavedReg.dac2_cntl; + /* always let TVDAC drive CRT2, we don't support tvout yet */ + save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + save->disp_output_cntl = info->SavedReg.disp_output_cntl; if (info->ChipFamily == CHIP_FAMILY_R200 || - info->ChipFamily == CHIP_FAMILY_R300) { - save->disp_output_cntl = - ((info->SavedReg.disp_output_cntl - & ~(CARD32)RADEON_DISP_DAC_SOURCE_MASK) - | RADEON_DISP_DAC_SOURCE_CRTC2); + info->ChipFamily == CHIP_FAMILY_R300 || + info->ChipFamily == CHIP_FAMILY_R350 || + info->ChipFamily == CHIP_FAMILY_RV350) { + save->disp_output_cntl &= ~(RADEON_DISP_DAC_SOURCE_MASK | + RADEON_DISP_DAC2_SOURCE_MASK); + if (pRADEONEnt->MonType1 != MT_CRT) { + save->disp_output_cntl |= (RADEON_DISP_DAC_SOURCE_CRTC2 | + RADEON_DISP_DAC2_SOURCE_CRTC2); + } else { + if (pRADEONEnt->ReversedDAC) { + save->disp_output_cntl |= RADEON_DISP_DAC2_SOURCE_CRTC2; + } else { + save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; + } + } } else { save->disp_hw_debug = info->SavedReg.disp_hw_debug; - if (info->IsDell && info->DellType == 2) { - if (info->DisplayType == MT_CRT || info->CloneType == MT_CRT) { - /* Turn on 2nd CRT */ + /* Turn on 2nd CRT */ + if (pRADEONEnt->MonType1 != MT_CRT) { + /* This is for some sample boards with the VGA port + connected to the TVDAC, but BIOS doesn't reflect this. + Here we configure both DACs to use CRTC2. + Not sure if this happens in any retail board. + */ + save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; + save->dac2_cntl |= RADEON_DAC2_DAC_CLK_SEL; + } else { + if (pRADEONEnt->ReversedDAC) { + save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; - save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; - save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; - - /* This will make 2nd CRT stay on in console */ - info->SavedReg.dac2_cntl = save->dac2_cntl; - info->SavedReg.disp_hw_debug |= RADEON_CRT2_DISP1_SEL; - info->SavedReg.crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; + } else { + save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + save->dac2_cntl |= RADEON_DAC2_DAC_CLK_SEL; } - } else save->dac2_cntl |= RADEON_DAC2_DAC_CLK_SEL; + } } save->crtc2_h_total_disp = @@ -5149,32 +6212,40 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8)); save->crtc2_pitch |= save->crtc2_pitch << 16; + save->disp2_merge_cntl = info->SavedReg.disp2_merge_cntl; + save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); - if (info->DisplayType == MT_DFP || info->CloneType == MT_DFP) { + if ((info->DisplayType == MT_DFP && info->IsSecondary) || + info->CloneType == MT_DFP) { save->crtc2_gen_cntl = (RADEON_CRTC2_EN | (format << 8)); save->fp2_h_sync_strt_wid = save->crtc2_h_sync_strt_wid; save->fp2_v_sync_strt_wid = save->crtc2_v_sync_strt_wid; - save->fp2_gen_cntl = (RADEON_FP2_SEL_CRTC2 | - RADEON_FP2_PANEL_FORMAT | + save->fp2_gen_cntl = (RADEON_FP2_PANEL_FORMAT | RADEON_FP2_ON); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + save->fp2_gen_cntl |= RADEON_FP2_DV0_EN; + } - if (pScrn->rgbBits == 8) + if (info->ChipFamily == CHIP_FAMILY_R200 || + info->ChipFamily == CHIP_FAMILY_R300 || + info->ChipFamily == CHIP_FAMILY_R350 || + info->ChipFamily == CHIP_FAMILY_RV350) { + save->fp2_gen_cntl &= ~RADEON_FP2_SOURCE_SEL_MASK; + save->fp2_gen_cntl |= RADEON_FP2_SOURCE_SEL_CRTC2; + } else { + save->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_MASK; + save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; + } + + if (pScrn->rgbBits == 8) save->fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format */ else save->fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format */ /* FIXME: When there are two DFPs, the 2nd DFP is driven by the * external TMDS transmitter. It may have a problem at - * high dot clock for certain panels. Since we don't - * know how to control the external TMDS transmitter, not - * much we can do here. + * high dot clock for certain panels. */ -#if 0 - if (save->dot_clock_freq > 15000) - save->tmds_pll_cntl = 0xA3F; - else if(save->tmds_pll_cntl != 0xA3F) - save->tmds_pll_cntl = info->SavedReg.tmds_pll_cntl; -#endif /* If BIOS has not turned it on, we'll keep it on so that we'll * have a valid VGA screen even after X quits or VT is switched @@ -5199,6 +6270,31 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, int yres = mode->VDisplay; float Hratio, Vratio; + /* If the FP registers have been initialized before for a panel, + * but the primary port is a CRT, we need to reinitialize + * FP registers in order for CRT to work properly + */ + + if ((info->DisplayType != MT_DFP) && (info->DisplayType != MT_LCD)) { + save->fp_crtc_h_total_disp = orig->fp_crtc_h_total_disp; + save->fp_crtc_v_total_disp = orig->fp_crtc_v_total_disp; + save->fp_gen_cntl = 0; + save->fp_h_sync_strt_wid = orig->fp_h_sync_strt_wid; + save->fp_horz_stretch = 0; + save->fp_v_sync_strt_wid = orig->fp_v_sync_strt_wid; + save->fp_vert_stretch = 0; + save->lvds_gen_cntl = orig->lvds_gen_cntl; + save->lvds_pll_cntl = orig->lvds_pll_cntl; + save->tmds_pll_cntl = orig->tmds_pll_cntl; + save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; + + save->lvds_gen_cntl |= ( RADEON_LVDS_DISPLAY_DIS | (1 << 23)); + save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON | RADEON_LVDS_ON); + save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + + return; + } + if (info->PanelXRes == 0 || info->PanelYRes == 0) { Hratio = 1.0; Vratio = 1.0; @@ -5213,7 +6309,7 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { save->fp_horz_stretch = orig->fp_horz_stretch; save->fp_horz_stretch &= ~(RADEON_HORZ_STRETCH_BLEND | - RADEON_HORZ_STRETCH_ENABLE); + RADEON_HORZ_STRETCH_ENABLE); save->fp_horz_stretch &= ~(RADEON_HORZ_AUTO_RATIO | RADEON_HORZ_PANEL_SIZE); save->fp_horz_stretch |= ((xres/8-1)<<16); @@ -5268,7 +6364,7 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, save->fp_gen_cntl |= (RADEON_FP_CRTC_DONT_SHADOW_VPAR | RADEON_FP_CRTC_DONT_SHADOW_HEND ); - if (pScrn->rgbBits == 8) + 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 */ @@ -5276,14 +6372,6 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, save->lvds_gen_cntl = orig->lvds_gen_cntl; save->lvds_pll_cntl = orig->lvds_pll_cntl; - /* This is needed for some panel at high resolution (>=1600x1200) - */ - if ((save->dot_clock_freq > 15000) && - (info->ChipFamily != CHIP_FAMILY_R300)) - save->tmds_pll_cntl = 0xA3F; - else - save->tmds_pll_cntl = orig->tmds_pll_cntl; - info->PanelOff = FALSE; /* This option is used to force the ONLY DEVICE in XFConfig to use * CRT port, instead of default DVI port. @@ -5292,23 +6380,69 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, info->PanelOff = TRUE; } + save->tmds_pll_cntl = orig->tmds_pll_cntl; + save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; if (info->PanelOff && info->Clone) { info->OverlayOnCRTC2 = TRUE; if (info->DisplayType == MT_LCD) { /* Turning off LVDS_ON seems to make panel white blooming. * For now we just turn off display data ??? */ - 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_BLON | RADEON_LVDS_ON); } else if (info->DisplayType == MT_DFP) save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); } else { if (info->DisplayType == MT_LCD) { + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + /* BIOS will use this setting to reset displays upon lid close/open. + * Here we let BIOS controls LCD, but the driver will control the external CRT. + */ + if (info->Clone || pRADEONEnt->HasSecondary) + save->bios_5_scratch = 0x01020201; + else + save->bios_5_scratch = orig->bios_5_scratch; + save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - } else if (info->DisplayType == MT_DFP) + + } else if (info->DisplayType == MT_DFP) { + int i; + CARD32 tmp = orig->tmds_pll_cntl & 0xfffff; + for (i=0; i<4; i++) { + if (info->tmds_pll[i].freq == 0) break; + if (save->dot_clock_freq < info->tmds_pll[i].freq) { + tmp = info->tmds_pll[i].value ; + break; + } + } + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350) || + (info->ChipFamily == CHIP_FAMILY_RV280)) { + if (tmp & 0xfff00000) + save->tmds_pll_cntl = tmp; + else + save->tmds_pll_cntl = (orig->tmds_pll_cntl & 0xfff00000) | tmp; + } else save->tmds_pll_cntl = tmp; + + RADEONTRACE(("TMDS_PLL from %x to %x\n", + orig->tmds_pll_cntl, + save->tmds_pll_cntl)); + + save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLRST); + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350) || + (info->ChipFamily == CHIP_FAMILY_R200) || !info->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 |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); + } } save->fp_crtc_h_total_disp = save->crtc_h_total_disp; @@ -5348,10 +6482,16 @@ static void RADEONInitPLLRegisters(RADEONSavePtr save, RADEONPLLPtr pll, 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, @@ -5403,6 +6543,11 @@ static void RADEONInitPLL2Registers(RADEONSavePtr save, RADEONPLLPtr pll, && 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, @@ -5499,7 +6644,13 @@ static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode, return FALSE; dot_clock = mode->Clock/1000.0; if (dot_clock) { - RADEONInitPLLRegisters(save, &info->pll, dot_clock); + if (info->UseBiosDividers) { + save->ppll_ref_div = info->RefDivider; + save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); + save->htotal_cntl = 0; + } + else + RADEONInitPLLRegisters(save, &info->pll, dot_clock); } else { save->ppll_ref_div = info->SavedReg.ppll_ref_div; save->ppll_div_3 = info->SavedReg.ppll_div_3; @@ -5515,10 +6666,7 @@ static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode, /* if (!info->PaletteSavedOnVT) RADEONInitPalette(save); */ } - if (((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD))) { - RADEONInitFPRegisters(pScrn, &info->SavedReg, save, mode, info); - } + RADEONInitFPRegisters(pScrn, &info->SavedReg, save, mode, info); RADEONTRACE(("RADEONInit returns %p\n", save)); return TRUE; @@ -5537,6 +6685,10 @@ static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) RADEONUnblank(pScrn); info->CurrentLayout.mode = mode; + + if (info->DispPriority) + RADEONInitDispBandwidth(pScrn); + return TRUE; } @@ -5582,7 +6734,7 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) if (info->Clone && info->CloneModes) { DisplayModePtr clone_mode = info->CloneModes; - /* Try to match a mode on primary head + /* Try to match a mode on primary head * FIXME: This may not be good if both heads don't have * exactly the same list of mode. */ @@ -5647,14 +6799,29 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) return ret; } +#ifdef X_XF86MiscPassMessage +Bool RADEONHandleMessage(int scrnIndex, const char* msgtype, + const char* msgval, char** retmsg) +{ + ErrorF("RADEONHandleMessage(%d, \"%s\", \"%s\", retmsg)\n", scrnIndex, + msgtype, msgval); + *retmsg = ""; + return 0; +} +#endif + /* Used to disallow modes that are not supported by the hardware */ -int RADEONValidMode(int scrnIndex, DisplayModePtr mode, - Bool verbose, int flag) +ModeStatus RADEONValidMode(int scrnIndex, DisplayModePtr mode, + Bool verbose, int flag) { - /* Searching for native mode timing table embedded in BIOS image. - * Not working yet. Currently we calculate from FP registers + /* There are problems with double scan mode at high clocks + * They're likely related PLL and display buffer settings. + * Disable these modes for now. */ - + if (mode->Flags & V_DBLSCAN) { + if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768)) + return MODE_CLOCK_RANGE; + } return MODE_OK; } @@ -5689,15 +6856,15 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) #ifdef XF86DRI if (info->directRenderingEnabled) { - pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); - - if (pSAREAPriv->pfCurrentPage == 1) { - Base += info->backOffset; - } + pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); if (clone || info->IsSecondary) { pSAREAPriv->crtc2_base = Base; } + + if (pSAREAPriv->pfCurrentPage == 1) { + Base += info->backOffset; + } } #endif @@ -5746,6 +6913,17 @@ Bool RADEONEnterVT(int scrnIndex, int flags) } else if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; +#ifdef XF86DRI + if (info->directRenderingEnabled) { + /* get the Radeon back into shape after resume */ + RADEONDRIResume(pScrn->pScreen); + } +#endif + /* this will get XVideo going again, but only if XVideo was initialised + during server startup (hence the info->adaptor if). */ + if (info->adaptor) + RADEONResetVideo(pScrn); + if (info->accelOn) RADEONEngineRestore(pScrn); @@ -5814,8 +6992,8 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) if (pScrn->vtSema) { RADEONRestore(pScrn); - RADEONUnmapMem(pScrn); } + RADEONUnmapMem(pScrn); if (info->accel) XAADestroyInfoRec(info->accel); info->accel = NULL; @@ -5829,13 +7007,9 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) if (info->DGAModes) xfree(info->DGAModes); info->DGAModes = NULL; - if (info->CloneModes) - while (info->CloneModes) - xf86DeleteMode(&info->CloneModes, info->CloneModes); - pScrn->vtSema = FALSE; - xf86ClearPrimInitDone(pScrn->entityList[0]); + xf86ClearPrimInitDone(info->pEnt->index); pScreen->BlockHandler = info->BlockHandler; pScreen->CloseScreen = info->CloseScreen; @@ -5936,6 +7110,74 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, } break; } + + if (PowerManagementMode == DPMSModeOn) { + if (info->IsSecondary) { + if (info->DisplayType == MT_DFP) { + 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_DV0_EN, ~RADEON_FP2_DV0_EN); + } + } + } else { + if ((info->Clone) && (info->CloneType == MT_DFP)) { + 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_DV0_EN, ~RADEON_FP2_DV0_EN); + } + } + if (info->DisplayType == MT_DFP) { + OUTREGP (RADEON_FP_GEN_CNTL, (RADEON_FP_FPON | RADEON_FP_TMDS_EN), + ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); + } else if (info->DisplayType == 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); + } + } + } else if ((PowerManagementMode == DPMSModeOff) || + (PowerManagementMode == DPMSModeSuspend) || + (PowerManagementMode == DPMSModeStandby)) { + if (info->IsSecondary) { + if (info->DisplayType == MT_DFP) { + 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_DV0_EN); + } + } + } else { + if ((info->Clone) && (info->CloneType == MT_DFP)) { + 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_DV0_EN); + } + } + if (info->DisplayType == MT_DFP) { + OUTREGP (RADEON_FP_GEN_CNTL, 0, ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); + } else if (info->DisplayType == 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 + 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(RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + } + } + } + } } #ifdef XF86DRI diff --git a/src/radeon_macros.h b/src/radeon_macros.h index a2719331..5beaee8f 100644 --- a/src/radeon_macros.h +++ b/src/radeon_macros.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h,v 1.1 2002/12/16 16:19:14 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h,v 1.3 2003/07/08 16:55:35 tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -85,10 +85,10 @@ do { \ #define OUTPLLP(pScrn, addr, val, mask) \ do { \ - CARD32 tmp = INPLL(pScrn, addr); \ - tmp &= (mask); \ - tmp |= (val); \ - OUTPLL(addr, tmp); \ + CARD32 tmp_ = INPLL(pScrn, addr); \ + tmp_ &= (mask); \ + tmp_ |= (val); \ + OUTPLL(addr, tmp_); \ } while (0) #define OUTPAL_START(idx) \ diff --git a/src/radeon_probe.c b/src/radeon_probe.c index bcf80c18..38c2fbe3 100644 --- a/src/radeon_probe.c +++ b/src/radeon_probe.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c,v 1.24 2003/02/07 20:41:15 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c,v 1.31 2003/11/10 18:41:23 tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -45,6 +45,8 @@ #include "xf86.h" #include "xf86_ansic.h" +#define _XF86MISC_SERVER_ +#include "xf86misc.h" #include "xf86Resources.h" #ifdef XFree86LOADER @@ -61,15 +63,22 @@ static xf86EnterVTProc *const volatile EnterVTProc = RADEONEnterVT; static xf86LeaveVTProc *const volatile LeaveVTProc = RADEONLeaveVT; static xf86FreeScreenProc *const volatile FreeScreenProc = RADEONFreeScreen; static xf86ValidModeProc *const volatile ValidModeProc = RADEONValidMode; +#ifdef X_XF86MiscPassMessage +static xf86HandleMessageProc *const volatile HandleMessageProc + = RADEONHandleMessage; +#endif -#define RADEONPreInit PreInitProc -#define RADEONScreenInit ScreenInitProc -#define RADEONSwitchMode SwitchModeProc -#define RADEONAdjustFrame AdjustFrameProc -#define RADEONEnterVT EnterVTProc -#define RADEONLeaveVT LeaveVTProc -#define RADEONFreeScreen FreeScreenProc -#define RADEONValidMode ValidModeProc +#define RADEONPreInit PreInitProc +#define RADEONScreenInit ScreenInitProc +#define RADEONSwitchMode SwitchModeProc +#define RADEONAdjustFrame AdjustFrameProc +#define RADEONEnterVT EnterVTProc +#define RADEONLeaveVT LeaveVTProc +#define RADEONFreeScreen FreeScreenProc +#define RADEONValidMode ValidModeProc +#ifdef X_XF86MiscPassMessage +# define RADEONHandleMessage HandleMessageProc +#endif #endif @@ -78,44 +87,66 @@ SymTabRec RADEONChipsets[] = { { PCI_CHIP_RADEON_QE, "ATI Radeon QE (AGP)" }, { PCI_CHIP_RADEON_QF, "ATI Radeon QF (AGP)" }, { PCI_CHIP_RADEON_QG, "ATI Radeon QG (AGP)" }, - { PCI_CHIP_RV100_QY, "ATI Radeon VE/7000 QY (AGP)" }, - { PCI_CHIP_RV100_QZ, "ATI Radeon VE/7000 QZ (AGP)" }, + { PCI_CHIP_RV100_QY, "ATI Radeon VE/7000 QY (AGP/PCI)" }, + { PCI_CHIP_RV100_QZ, "ATI Radeon VE/7000 QZ (AGP/PCI)" }, { PCI_CHIP_RADEON_LW, "ATI Radeon Mobility M7 LW (AGP)" }, { PCI_CHIP_RADEON_LX, "ATI Mobility FireGL 7800 M7 LX (AGP)" }, { PCI_CHIP_RADEON_LY, "ATI Radeon Mobility M6 LY (AGP)" }, { PCI_CHIP_RADEON_LZ, "ATI Radeon Mobility M6 LZ (AGP)" }, + { PCI_CHIP_RS100_4136, "ATI Radeon IGP320 (A3) 4136" }, + { PCI_CHIP_RS100_4336, "ATI Radeon IGP320M (U1) 4336" }, + { PCI_CHIP_RS200_4137, "ATI Radeon IGP330/340/350 (A4) 4137" }, + { PCI_CHIP_RS200_4337, "ATI Radeon IGP330M/340M/350M (U2) 4337" }, + { PCI_CHIP_RS250_4237, "ATI Radeon 7000 IGP (A4+) 4237" }, + { PCI_CHIP_RS250_4437, "ATI Radeon Mobility 7000 IGP 4437" }, { PCI_CHIP_R200_QH, "ATI FireGL 8700/8800 QH (AGP)" }, - { PCI_CHIP_R200_QI, "ATI Radeon 8500 QI (AGP)" }, - { PCI_CHIP_R200_QJ, "ATI Radeon 8500 QJ (AGP)" }, - { PCI_CHIP_R200_QK, "ATI Radeon 8500 QK (AGP)" }, { PCI_CHIP_R200_QL, "ATI Radeon 8500 QL (AGP)" }, { PCI_CHIP_R200_QM, "ATI Radeon 9100 QM (AGP)" }, - { PCI_CHIP_R200_QN, "ATI Radeon 8500 QN (AGP)" }, - { PCI_CHIP_R200_QO, "ATI Radeon 8500 QO (AGP)" }, - { PCI_CHIP_R200_Qh, "ATI Radeon 8500 Qh (AGP)" }, - { PCI_CHIP_R200_Qi, "ATI Radeon 8500 Qi (AGP)" }, - { PCI_CHIP_R200_Qj, "ATI Radeon 8500 Qj (AGP)" }, - { PCI_CHIP_R200_Qk, "ATI Radeon 8500 Qk (AGP)" }, - { PCI_CHIP_R200_Ql, "ATI Radeon 8500 Ql (AGP)" }, - { PCI_CHIP_R200_BB, "ATI Radeon 8500 BB (AGP)" }, - { PCI_CHIP_RV200_QW, "ATI Radeon 7500 QW (AGP)" }, - { PCI_CHIP_RV200_QX, "ATI Radeon 7500 QX (AGP)" }, - { PCI_CHIP_RV250_Id, "ATI Radeon 9000 Id (AGP)" }, - { PCI_CHIP_RV250_Ie, "ATI Radeon 9000 Ie (AGP)" }, - { PCI_CHIP_RV250_If, "ATI Radeon 9000 If (AGP)" }, - { PCI_CHIP_RV250_Ig, "ATI Radeon 9000 Ig (AGP)" }, - { PCI_CHIP_RV250_Ld, "ATI Radeon Mobility M9 Ld (AGP)" }, - { PCI_CHIP_RV250_Le, "ATI Radeon Mobility M9 Le (AGP)" }, - { PCI_CHIP_RV250_Lf, "ATI Radeon Mobility M9 Lf (AGP)" }, - { PCI_CHIP_RV250_Lg, "ATI Radeon Mobility M9 Lg (AGP)" }, + { PCI_CHIP_R200_BB, "ATI Radeon 8500 AIW BB (AGP)" }, + { PCI_CHIP_R200_BC, "ATI Radeon 8500 AIW BC (AGP)" }, + { PCI_CHIP_RV200_QW, "ATI Radeon 7500 QW (AGP/PCI)" }, + { PCI_CHIP_RV200_QX, "ATI Radeon 7500 QX (AGP/PCI)" }, + { PCI_CHIP_RV250_If, "ATI Radeon 9000/PRO If (AGP/PCI)" }, + { PCI_CHIP_RV250_Ig, "ATI Radeon 9000 Ig (AGP/PCI)" }, + { PCI_CHIP_RV250_Ld, "ATI FireGL Mobility 9000 (M9) Ld (AGP)" }, + { PCI_CHIP_RV250_Lf, "ATI Radeon Mobility 9000 (M9) Lf (AGP)" }, + { PCI_CHIP_RV250_Lg, "ATI Radeon Mobility 9000 (M9) Lg (AGP)" }, + { PCI_CHIP_RS300_5834, "ATI Radeon 9100 IGP (A5) 5834" }, + { PCI_CHIP_RS300_5835, "ATI Radeon Mobility 9100 IGP (U3) 5835" }, + { PCI_CHIP_RV280_5960, "ATI Radeon 9200PRO 5960 (AGP)" }, + { PCI_CHIP_RV280_5961, "ATI Radeon 9200 5961 (AGP)" }, + { PCI_CHIP_RV280_5962, "ATI Radeon 9200 5962 (AGP)" }, + { PCI_CHIP_RV280_5964, "ATI Radeon 9200SE 5964 (AGP)" }, + { PCI_CHIP_RV280_5C61, "ATI Radeon Mobility 9200 (M9+) 5C61 (AGP)" }, + { PCI_CHIP_RV280_5C63, "ATI Radeon Mobility 9200 (M9+) 5C63 (AGP)" }, { PCI_CHIP_R300_AD, "ATI Radeon 9500 AD (AGP)" }, { PCI_CHIP_R300_AE, "ATI Radeon 9500 AE (AGP)" }, - { PCI_CHIP_R300_AF, "ATI Radeon 9500 AF (AGP)" }, - { PCI_CHIP_R300_AG, "ATI FireGL Z1/X1 AG (AGP)" }, + { PCI_CHIP_R300_AF, "ATI Radeon 9600TX AF (AGP)" }, + { PCI_CHIP_R300_AG, "ATI FireGL Z1 AG (AGP)" }, { PCI_CHIP_R300_ND, "ATI Radeon 9700 Pro ND (AGP)" }, { PCI_CHIP_R300_NE, "ATI Radeon 9700/9500Pro NE (AGP)" }, { PCI_CHIP_R300_NF, "ATI Radeon 9700 NF (AGP)" }, { PCI_CHIP_R300_NG, "ATI FireGL X1 NG (AGP)" }, + { PCI_CHIP_RV350_AP, "ATI Radeon 9600 AP (AGP)" }, + { PCI_CHIP_RV350_AQ, "ATI Radeon 9600SE AQ (AGP)" }, + { PCI_CHIP_RV360_AR, "ATI Radeon 9600XT AR (AGP)" }, + { PCI_CHIP_RV350_AS, "ATI Radeon 9600 AS (AGP)" }, + { PCI_CHIP_RV350_AT, "ATI FireGL T2 AT (AGP)" }, + { PCI_CHIP_RV350_AV, "ATI FireGL RV360 AV (AGP)" }, + { PCI_CHIP_RV350_NP, "ATI Radeon Mobility 9600 (M10) NP (AGP)" }, + { PCI_CHIP_RV350_NQ, "ATI Radeon Mobility 9600 (M10) NQ (AGP)" }, + { PCI_CHIP_RV350_NR, "ATI Radeon Mobility 9600 (M11) NR (AGP)" }, + { PCI_CHIP_RV350_NS, "ATI Radeon Mobility 9600 (M10) NS (AGP)" }, + { PCI_CHIP_RV350_NT, "ATI FireGL Mobility T2 (M10) NT (AGP)" }, + { PCI_CHIP_RV350_NV, "ATI FireGL Mobility T2 (M11) NV (AGP)" }, + { PCI_CHIP_R350_AH, "ATI Radeon 9800SE AH (AGP)" }, + { PCI_CHIP_R350_AI, "ATI Radeon 9800 AI (AGP)" }, + { PCI_CHIP_R350_AJ, "ATI Radeon 9800 AJ (AGP)" }, + { PCI_CHIP_R350_AK, "ATI FireGL X2 AK (AGP)" }, + { PCI_CHIP_R350_NH, "ATI Radeon 9800PRO NH (AGP)" }, + { PCI_CHIP_R350_NI, "ATI Radeon 9800 NI (AGP)" }, + { PCI_CHIP_R350_NK, "ATI FireGL X2 NK (AGP)" }, + { PCI_CHIP_R360_NJ, "ATI Radeon 9800XT NJ (AGP)" }, { -1, NULL } }; @@ -130,30 +161,32 @@ PciChipsets RADEONPciChipsets[] = { { PCI_CHIP_RADEON_LX, PCI_CHIP_RADEON_LX, RES_SHARED_VGA }, { PCI_CHIP_RADEON_LY, PCI_CHIP_RADEON_LY, RES_SHARED_VGA }, { PCI_CHIP_RADEON_LZ, PCI_CHIP_RADEON_LZ, RES_SHARED_VGA }, + { PCI_CHIP_RS100_4136, PCI_CHIP_RS100_4136, RES_SHARED_VGA }, + { PCI_CHIP_RS100_4336, PCI_CHIP_RS100_4336, RES_SHARED_VGA }, + { PCI_CHIP_RS200_4137, PCI_CHIP_RS200_4137, RES_SHARED_VGA }, + { PCI_CHIP_RS200_4337, PCI_CHIP_RS200_4337, RES_SHARED_VGA }, + { PCI_CHIP_RS250_4237, PCI_CHIP_RS250_4237, RES_SHARED_VGA }, + { PCI_CHIP_RS250_4437, PCI_CHIP_RS250_4437, RES_SHARED_VGA }, { PCI_CHIP_R200_QH, PCI_CHIP_R200_QH, RES_SHARED_VGA }, - { PCI_CHIP_R200_QI, PCI_CHIP_R200_QI, RES_SHARED_VGA }, - { PCI_CHIP_R200_QJ, PCI_CHIP_R200_QJ, RES_SHARED_VGA }, - { PCI_CHIP_R200_QK, PCI_CHIP_R200_QK, RES_SHARED_VGA }, { PCI_CHIP_R200_QL, PCI_CHIP_R200_QL, RES_SHARED_VGA }, { PCI_CHIP_R200_QM, PCI_CHIP_R200_QM, RES_SHARED_VGA }, - { PCI_CHIP_R200_QN, PCI_CHIP_R200_QN, RES_SHARED_VGA }, - { PCI_CHIP_R200_QO, PCI_CHIP_R200_QO, RES_SHARED_VGA }, - { PCI_CHIP_R200_Qh, PCI_CHIP_R200_Qh, RES_SHARED_VGA }, - { PCI_CHIP_R200_Qi, PCI_CHIP_R200_Qi, RES_SHARED_VGA }, - { PCI_CHIP_R200_Qj, PCI_CHIP_R200_Qj, RES_SHARED_VGA }, - { PCI_CHIP_R200_Qk, PCI_CHIP_R200_Qk, RES_SHARED_VGA }, - { PCI_CHIP_R200_Ql, PCI_CHIP_R200_Ql, RES_SHARED_VGA }, { PCI_CHIP_R200_BB, PCI_CHIP_R200_BB, RES_SHARED_VGA }, + { PCI_CHIP_R200_BC, PCI_CHIP_R200_BC, RES_SHARED_VGA }, { PCI_CHIP_RV200_QW, PCI_CHIP_RV200_QW, RES_SHARED_VGA }, { PCI_CHIP_RV200_QX, PCI_CHIP_RV200_QX, RES_SHARED_VGA }, - { PCI_CHIP_RV250_Id, PCI_CHIP_RV250_Id, RES_SHARED_VGA }, - { PCI_CHIP_RV250_Ie, PCI_CHIP_RV250_Ie, RES_SHARED_VGA }, { PCI_CHIP_RV250_If, PCI_CHIP_RV250_If, RES_SHARED_VGA }, { PCI_CHIP_RV250_Ig, PCI_CHIP_RV250_Ig, RES_SHARED_VGA }, { PCI_CHIP_RV250_Ld, PCI_CHIP_RV250_Ld, RES_SHARED_VGA }, - { PCI_CHIP_RV250_Le, PCI_CHIP_RV250_Le, RES_SHARED_VGA }, { PCI_CHIP_RV250_Lf, PCI_CHIP_RV250_Lf, RES_SHARED_VGA }, { PCI_CHIP_RV250_Lg, PCI_CHIP_RV250_Lg, RES_SHARED_VGA }, + { PCI_CHIP_RS300_5834, PCI_CHIP_RS300_5834, RES_SHARED_VGA }, + { PCI_CHIP_RS300_5835, PCI_CHIP_RS300_5835, RES_SHARED_VGA }, + { PCI_CHIP_RV280_5960, PCI_CHIP_RV280_5960, RES_SHARED_VGA }, + { PCI_CHIP_RV280_5961, PCI_CHIP_RV280_5961, RES_SHARED_VGA }, + { PCI_CHIP_RV280_5962, PCI_CHIP_RV280_5962, RES_SHARED_VGA }, + { PCI_CHIP_RV280_5964, PCI_CHIP_RV280_5964, RES_SHARED_VGA }, + { PCI_CHIP_RV280_5C61, PCI_CHIP_RV280_5C61, RES_SHARED_VGA }, + { PCI_CHIP_RV280_5C63, PCI_CHIP_RV280_5C63, RES_SHARED_VGA }, { PCI_CHIP_R300_AD, PCI_CHIP_R300_AD, RES_SHARED_VGA }, { PCI_CHIP_R300_AE, PCI_CHIP_R300_AE, RES_SHARED_VGA }, { PCI_CHIP_R300_AF, PCI_CHIP_R300_AF, RES_SHARED_VGA }, @@ -162,6 +195,26 @@ PciChipsets RADEONPciChipsets[] = { { PCI_CHIP_R300_NE, PCI_CHIP_R300_NE, RES_SHARED_VGA }, { PCI_CHIP_R300_NF, PCI_CHIP_R300_NF, RES_SHARED_VGA }, { PCI_CHIP_R300_NG, PCI_CHIP_R300_NG, RES_SHARED_VGA }, + { PCI_CHIP_RV350_AP, PCI_CHIP_RV350_AP, RES_SHARED_VGA }, + { PCI_CHIP_RV350_AQ, PCI_CHIP_RV350_AQ, RES_SHARED_VGA }, + { PCI_CHIP_RV360_AR, PCI_CHIP_RV360_AR, RES_SHARED_VGA }, + { PCI_CHIP_RV350_AS, PCI_CHIP_RV350_AS, RES_SHARED_VGA }, + { PCI_CHIP_RV350_AT, PCI_CHIP_RV350_AT, RES_SHARED_VGA }, + { PCI_CHIP_RV350_AV, PCI_CHIP_RV350_AV, RES_SHARED_VGA }, + { PCI_CHIP_RV350_NP, PCI_CHIP_RV350_NP, RES_SHARED_VGA }, + { PCI_CHIP_RV350_NQ, PCI_CHIP_RV350_NQ, RES_SHARED_VGA }, + { PCI_CHIP_RV350_NR, PCI_CHIP_RV350_NR, RES_SHARED_VGA }, + { PCI_CHIP_RV350_NS, PCI_CHIP_RV350_NS, RES_SHARED_VGA }, + { PCI_CHIP_RV350_NT, PCI_CHIP_RV350_NT, RES_SHARED_VGA }, + { PCI_CHIP_RV350_NV, PCI_CHIP_RV350_NV, RES_SHARED_VGA }, + { PCI_CHIP_R350_AH, PCI_CHIP_R350_AH, RES_SHARED_VGA }, + { PCI_CHIP_R350_AI, PCI_CHIP_R350_AI, RES_SHARED_VGA }, + { PCI_CHIP_R350_AJ, PCI_CHIP_R350_AJ, RES_SHARED_VGA }, + { PCI_CHIP_R350_AK, PCI_CHIP_R350_AK, RES_SHARED_VGA }, + { PCI_CHIP_R350_NH, PCI_CHIP_R350_NH, RES_SHARED_VGA }, + { PCI_CHIP_R350_NI, PCI_CHIP_R350_NI, RES_SHARED_VGA }, + { PCI_CHIP_R350_NK, PCI_CHIP_R350_NK, RES_SHARED_VGA }, + { PCI_CHIP_R360_NJ, PCI_CHIP_R360_NJ, RES_SHARED_VGA }, { -1, -1, RES_UNDEFINED } }; @@ -249,7 +302,7 @@ RADEONProbe(DriverPtr drv, int flags) for (i = 0; i < numUsed; i++) { ScrnInfoPtr pScrn = NULL; EntityInfoPtr pEnt; - + pEnt = xf86GetEntityInfo(usedChips[i]); if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], RADEONPciChipsets, 0, 0, 0, 0, 0))) { @@ -271,6 +324,9 @@ RADEONProbe(DriverPtr drv, int flags) 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; @@ -281,46 +337,37 @@ RADEONProbe(DriverPtr drv, int flags) pEnt = xf86GetEntityInfo(usedChips[i]); - /* All Radeon chips except the original ones support - * Dual-Head, mark the entity as sharable. - */ - if (pEnt->chipset != PCI_CHIP_RADEON_QD && - pEnt->chipset != PCI_CHIP_RADEON_QE && - pEnt->chipset != PCI_CHIP_RADEON_QF && - pEnt->chipset != PCI_CHIP_RADEON_QG) { - static int instance = 0; + /* create a RADEONEntity for all chips, even with + old single head Radeon, need to use pRADEONEnt + for new monitor detection routines + */ + { DevUnion *pPriv; + RADEONEntPtr pRADEONEnt; xf86SetEntitySharable(usedChips[i]); - xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], - instance); - if (gRADEONEntityIndex < 0) { + if (gRADEONEntityIndex == -1) gRADEONEntityIndex = xf86AllocateEntityPrivateIndex(); - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], - gRADEONEntityIndex); - - if (!pPriv->ptr) { - RADEONEntPtr pRADEONEnt; - - pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1); - pRADEONEnt = pPriv->ptr; - pRADEONEnt->IsDRIEnabled = FALSE; - pRADEONEnt->BypassSecondary = FALSE; - pRADEONEnt->HasSecondary = FALSE; - pRADEONEnt->IsSecondaryRestored = FALSE; - } - } - instance++; - if (instance == 2) { - RADEONEntPtr pRADEONEnt; - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], - gRADEONEntityIndex); - pRADEONEnt = pPriv->ptr; + pPriv = xf86GetEntityPrivate(pEnt->index, + gRADEONEntityIndex); + + if (!pPriv->ptr) { + int j; + int instance = xf86GetNumEntityInstances(pEnt->index); + + for (j = 0; j < instance; j++) + xf86SetEntityInstanceForScreen(pScrn, pEnt->index, j); + + pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1); + pRADEONEnt = pPriv->ptr; + pRADEONEnt->HasSecondary = FALSE; + pRADEONEnt->IsSecondaryRestored = FALSE; + } else { + pRADEONEnt = pPriv->ptr; pRADEONEnt->HasSecondary = TRUE; } - } xfree(pEnt); } diff --git a/src/radeon_probe.h b/src/radeon_probe.h index 34e5e860..85d43cc0 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.h,v 1.8 2002/04/24 16:20:40 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.h,v 1.14 2003/11/10 18:41:23 tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -40,13 +40,14 @@ #include "atiproto.h" #include "xf86str.h" +#include "xf86DDC.h" + +#define _XF86MISC_SERVER_ +#include "xf86misc.h" typedef struct { - Bool IsDRIEnabled; - Bool HasSecondary; - Bool BypassSecondary; /* * The next two are used to make sure CRTC2 is restored before CRTC_EXT, @@ -57,6 +58,13 @@ typedef struct ScrnInfoPtr pSecondaryScrn; ScrnInfoPtr pPrimaryScrn; + + int MonType1; + int MonType2; + xf86MonPtr MonInfo1; + xf86MonPtr MonInfo2; + Bool ReversedDAC; /* TVDAC used as primary dac */ + Bool ReversedTMDS; /* DDC_DVI is used for external TMDS */ } RADEONEntRec, *RADEONEntPtr; /* radeon_probe.c */ @@ -79,6 +87,11 @@ extern Bool RADEONScreenInit FunctionPrototype((int, ScreenPtr, int, char **)); extern Bool RADEONSwitchMode FunctionPrototype((int, DisplayModePtr, int)); +#ifdef X_XF86MiscPassMessage +extern Bool RADEONHandleMessage + FunctionPrototype((int, const char*, const char*, + char**)); +#endif extern void RADEONAdjustFrame FunctionPrototype((int, int, int, int)); extern Bool RADEONEnterVT @@ -87,7 +100,7 @@ extern void RADEONLeaveVT FunctionPrototype((int, int)); extern void RADEONFreeScreen FunctionPrototype((int, int)); -extern int RADEONValidMode +extern ModeStatus RADEONValidMode FunctionPrototype((int, DisplayModePtr, Bool, int)); diff --git a/src/radeon_reg.h b/src/radeon_reg.h index a5c44f8d..1d73e214 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.25.2.1 2003/03/07 12:13:59 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.31 2003/11/10 18:41:23 tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -66,6 +66,8 @@ # define RADEON_AGP_APER_SIZE_4MB (0x3f << 0) # define RADEON_AGP_APER_SIZE_MASK (0x3f << 0) #define RADEON_AGP_COMMAND 0x0f60 /* PCI */ +#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config*/ +# define RADEON_AGP_ENABLE (1<<8) #define RADEON_AGP_PLL_CNTL 0x000b /* PLL */ #define RADEON_AGP_STATUS 0x0f5c /* PCI */ # define RADEON_AGP_1X_MODE 0x01 @@ -232,6 +234,28 @@ # define RADEON_CONSTANT_COLOR_ZERO 0x00000000 #define RADEON_CRC_CMDFIFO_ADDR 0x0740 #define RADEON_CRC_CMDFIFO_DOUT 0x0744 +#define RADEON_GRPH_BUFFER_CNTL 0x02f0 +# define RADEON_GRPH_START_REQ_MASK (0x7f) +# define RADEON_GRPH_START_REQ_SHIFT 0 +# define RADEON_GRPH_STOP_REQ_MASK (0x7f<<8) +# define RADEON_GRPH_STOP_REQ_SHIFT 8 +# define RADEON_GRPH_CRITICAL_POINT_MASK (0x7f<<16) +# define RADEON_GRPH_CRITICAL_POINT_SHIFT 16 +# define RADEON_GRPH_CRITICAL_CNTL (1<<28) +# define RADEON_GRPH_BUFFER_SIZE (1<<29) +# define RADEON_GRPH_CRITICAL_AT_SOF (1<<30) +# define RADEON_GRPH_STOP_CNTL (1<<31) +#define RADEON_GRPH2_BUFFER_CNTL 0x03f0 +# define RADEON_GRPH2_START_REQ_MASK (0x7f) +# define RADEON_GRPH2_START_REQ_SHIFT 0 +# define RADEON_GRPH2_STOP_REQ_MASK (0x7f<<8) +# define RADEON_GRPH2_STOP_REQ_SHIFT 8 +# define RADEON_GRPH2_CRITICAL_POINT_MASK (0x7f<<16) +# define RADEON_GRPH2_CRITICAL_POINT_SHIFT 16 +# define RADEON_GRPH2_CRITICAL_CNTL (1<<28) +# define RADEON_GRPH2_BUFFER_SIZE (1<<29) +# define RADEON_GRPH2_CRITICAL_AT_SOF (1<<30) +# define RADEON_GRPH2_STOP_CNTL (1<<31) #define RADEON_CRTC_CRNT_FRAME 0x0214 #define RADEON_CRTC_EXT_CNTL 0x0054 # define RADEON_CRTC_VGA_XOVERSCAN (1 << 0) @@ -272,6 +296,9 @@ # define RADEON_CRTC2_CSYNC_EN (1 << 27) # 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_GUI_TRIG_VLINE 0x0218 #define RADEON_CRTC_H_SYNC_STRT_WID 0x0204 # define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0) @@ -356,7 +383,10 @@ #define RADEON_DAC_CNTL 0x0058 # define RADEON_DAC_RANGE_CNTL (3 << 0) +# define RADEON_DAC_RANGE_CNTL_MASK 0x03 # define RADEON_DAC_BLANKING (1 << 2) +# define RADEON_DAC_CMP_EN (1 << 3) +# define RADEON_DAC_CMP_OUTPUT (1 << 7) # define RADEON_DAC_8BIT_EN (1 << 8) # define RADEON_DAC_VGA_ADR_EN (1 << 13) # define RADEON_DAC_PDWN (1 << 15) @@ -365,6 +395,12 @@ # 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_DAC_EXT_CNTL 0x0280 +# 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_MASK 0x0003ff00 +# define RADEON_DAC_FORCE_DATA_SHIFT 8 #define RADEON_TV_DAC_CNTL 0x088c # define RADEON_TV_DAC_STD_MASK 0x0300 # define RADEON_TV_DAC_RDACPD (1 << 24) @@ -374,7 +410,9 @@ # define RADEON_CRT2_DISP1_SEL (1 << 5) #define RADEON_DISP_OUTPUT_CNTL 0x0d64 # define RADEON_DISP_DAC_SOURCE_MASK 0x03 +# define RADEON_DISP_DAC2_SOURCE_MASK 0x0c # define RADEON_DISP_DAC_SOURCE_CRTC2 0x01 +# define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04 #define RADEON_DAC_CRC_SIG 0x02cc #define RADEON_DAC_DATA 0x03c9 /* VGA */ #define RADEON_DAC_MASK 0x03c6 /* VGA */ @@ -392,6 +430,23 @@ #define RADEON_DEVICE_ID 0x0f02 /* PCI */ #define RADEON_DISP_MISC_CNTL 0x0d00 # define RADEON_SOFT_RESET_GRPH_PP (1 << 0) +#define RADEON_DISP_MERGE_CNTL 0x0d60 +# define RADEON_DISP_ALPHA_MODE_MASK 0x03 +# 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_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_DISP_LIN_TRANS_GRPH_A 0x0d80 +#define RADEON_DISP_LIN_TRANS_GRPH_B 0x0d84 +#define RADEON_DISP_LIN_TRANS_GRPH_C 0x0d88 +#define RADEON_DISP_LIN_TRANS_GRPH_D 0x0d8c +#define RADEON_DISP_LIN_TRANS_GRPH_E 0x0d90 +#define RADEON_DISP_LIN_TRANS_GRPH_F 0x0d98 #define RADEON_DP_BRUSH_BKGD_CLR 0x1478 #define RADEON_DP_BRUSH_FRGD_CLR 0x147c #define RADEON_DP_CNTL 0x16c0 @@ -582,7 +637,10 @@ # define RADEON_FP2_BLANK_EN (1 << 1) # define RADEON_FP2_ON (1 << 2) # define RADEON_FP2_PANEL_FORMAT (1 << 3) -# define RADEON_FP2_SEL_CRTC2 (1 << 13) +# define RADEON_FP2_SOURCE_SEL_MASK (3 << 10) +# define RADEON_FP2_SOURCE_SEL_CRTC2 (1 << 10) +# define RADEON_FP2_SRC_SEL_MASK (3 << 13) +# define RADEON_FP2_SRC_SEL_CRTC2 (1 << 13) # define RADEON_FP2_FP_POL (1 << 16) # define RADEON_FP2_LP_POL (1 << 17) # define RADEON_FP2_SCK_POL (1 << 18) @@ -590,6 +648,8 @@ # define RADEON_FP2_PAD_FLOP_EN (1 << 22) # define RADEON_FP2_CRC_EN (1 << 23) # define RADEON_FP2_CRC_READ_EN (1 << 24) +# define RADEON_FP2_DV0_EN (1 << 25) +# define RADEON_FP2_DV0_RATE_SEL_SDR (1 << 26) #define RADEON_FP_H_SYNC_STRT_WID 0x02c4 #define RADEON_FP_H2_SYNC_STRT_WID 0x03c4 #define RADEON_FP_HORZ_STRETCH 0x028c @@ -697,6 +757,10 @@ #define RADEON_MAX_LATENCY 0x0f3f /* PCI */ #define RADEON_MC_AGP_LOCATION 0x014c #define RADEON_MC_FB_LOCATION 0x0148 +#define RADEON_DISPLAY_BASE_ADDR 0x23c +#define RADEON_DISPLAY2_BASE_ADDR 0x33c +#define RADEON_OV0_BASE_ADDR 0x43c +#define RADEON_NB_TOM 0x15c #define RADEON_MCLK_CNTL 0x0012 /* PLL */ # define RADEON_FORCEON_MCLKA (1 << 16) # define RADEON_FORCEON_MCLKB (1 << 17) @@ -711,6 +775,12 @@ #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 R300_MEM_NUM_CHANNELS_MASK 0x03 +# 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 @@ -723,7 +793,13 @@ #define RADEON_MPLL_CNTL 0x000e /* PLL */ #define RADEON_MPP_TB_CONFIG 0x01c0 /* ? */ #define RADEON_MPP_GP_CONFIG 0x01c8 /* ? */ - +#define R300_MC_IND_INDEX 0x01f8 +# define R300_MC_IND_ADDR_MASK 0x3f +#define R300_MC_IND_DATA 0x01fc +#define R300_MC_READ_CNTL_AB 0x017c +# define R300_MEM_RBS_POSITION_A_MASK 0x03 +#define R300_MC_READ_CNTL_CD_mcind 0x24 +# define R300_MEM_RBS_POSITION_C_MASK 0x03 #define RADEON_N_VIF_COUNT 0x0248 @@ -891,6 +967,11 @@ # define RADEON_PIX2CLK_SRC_SEL_PSCANCLK 0x01 # define RADEON_PIX2CLK_SRC_SEL_BYTECLK 0x02 # define RADEON_PIX2CLK_SRC_SEL_P2PLLCLK 0x03 +# define RADEON_PIX2CLK_ALWAYS_ONb (1<<6) +# define RADEON_PIX2CLK_DAC_ALWAYS_ONb (1<<7) +# define RADEON_PIXCLK_TV_SRC_SEL (1 << 8) +# define RADEON_PIXCLK_LVDS_ALWAYS_ONb (1 << 14) +# define RADEON_PIXCLK_TMDS_ALWAYS_ONb (1 << 15) #define RADEON_PLANE_3D_MASK_C 0x1d44 #define RADEON_PLL_TEST_CNTL 0x0013 /* PLL */ #define RADEON_PMI_CAP_ID 0x0f5c /* PCI */ @@ -1013,6 +1094,9 @@ #define RADEON_TEST_DEBUG_MUX 0x0124 #define RADEON_TEST_DEBUG_OUT 0x012c #define RADEON_TMDS_PLL_CNTL 0x02a8 +#define RADEON_TMDS_TRANSMITTER_CNTL 0x02a4 +# define RADEON_TMDS_TRANSMITTER_PLLEN 1 +# define RADEON_TMDS_TRANSMITTER_PLLRST 2 #define RADEON_TRAIL_BRES_DEC 0x1614 #define RADEON_TRAIL_BRES_ERR 0x160c #define RADEON_TRAIL_BRES_INC 0x1610 @@ -1025,6 +1109,9 @@ # define RADEON_VCLK_SRC_SEL_PSCANCLK 0x01 # define RADEON_VCLK_SRC_SEL_BYTECLK 0x02 # define RADEON_VCLK_SRC_SEL_PPLLCLK 0x03 +# define RADEON_PIXCLK_ALWAYS_ONb (1<<6) +# define RADEON_PIXCLK_DAC_ALWAYS_ONb (1<<7) + #define RADEON_VENDOR_ID 0x0f00 /* PCI */ #define RADEON_VGA_DDA_CONFIG 0x02e8 #define RADEON_VGA_DDA_ON_OFF 0x02ec @@ -1140,6 +1227,10 @@ # define RADEON_LOD_BIAS_SHIFT 8 # define RADEON_MAX_MIP_LEVEL_MASK (0x0f << 16) # define RADEON_MAX_MIP_LEVEL_SHIFT 16 +# define RADEON_YUV_TO_RGB (1 << 20) +# define RADEON_YUV_TEMPERATURE_COOL (0 << 21) +# define RADEON_YUV_TEMPERATURE_HOT (1 << 21) +# define RADEON_YUV_TEMPERATURE_MASK (1 << 21) # define RADEON_WRAPEN_S (1 << 22) # define RADEON_CLAMP_S_WRAP (0 << 23) # define RADEON_CLAMP_S_MIRROR (1 << 23) @@ -1147,6 +1238,8 @@ # define RADEON_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) # define RADEON_CLAMP_S_CLAMP_BORDER (4 << 23) # define RADEON_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) +# define RADEON_CLAMP_S_CLAMP_GL (6 << 23) +# define RADEON_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) # define RADEON_CLAMP_S_MASK (7 << 23) # define RADEON_WRAPEN_T (1 << 26) # define RADEON_CLAMP_T_WRAP (0 << 27) @@ -1155,6 +1248,8 @@ # define RADEON_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) # define RADEON_CLAMP_T_CLAMP_BORDER (4 << 27) # define RADEON_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) +# define RADEON_CLAMP_T_CLAMP_GL (6 << 27) +# define RADEON_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) # define RADEON_CLAMP_T_MASK (7 << 27) # define RADEON_BORDER_MODE_OGL (0 << 31) # define RADEON_BORDER_MODE_D3D (1 << 31) @@ -1170,6 +1265,11 @@ # define RADEON_TXFORMAT_ARGB8888 (6 << 0) # define RADEON_TXFORMAT_RGBA8888 (7 << 0) # define RADEON_TXFORMAT_Y8 (8 << 0) +# define RADEON_TXFORMAT_VYUY422 (10 << 0) +# define RADEON_TXFORMAT_YVYU422 (11 << 0) +# define RADEON_TXFORMAT_DXT1 (12 << 0) +# define RADEON_TXFORMAT_DXT23 (14 << 0) +# define RADEON_TXFORMAT_DXT45 (15 << 0) # define RADEON_TXFORMAT_FORMAT_MASK (31 << 0) # define RADEON_TXFORMAT_FORMAT_SHIFT 0 # define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5) @@ -1257,6 +1357,10 @@ # define RADEON_SIGNED_RGB_SHIFT 30 # define RADEON_SIGNED_ALPHA_MASK (1 << 31) # define RADEON_SIGNED_ALPHA_SHIFT 31 +#define RADEON_PP_TEX_PITCH_0 0x1d08 /* NPOT */ +#define RADEON_PP_TEX_PITCH_1 0x1d10 /* NPOT */ +#define RADEON_PP_TEX_PITCH_2 0x1d18 /* NPOT */ +/* note: bits 13-5: 32 byte aligned stride of texture map */ #define RADEON_PP_TXCBLEND_0 0x1c60 #define RADEON_PP_TXCBLEND_1 0x1c78 @@ -1861,12 +1965,11 @@ #define RADEON_AIC_CNTL 0x01d0 # define RADEON_PCIGART_TRANSLATE_EN (1 << 0) +#define RADEON_AIC_LO_ADDR 0x01dc /* Constants */ -#define RADEON_AGP_TEX_OFFSET 0x02000000 - #define RADEON_LAST_FRAME_REG RADEON_GUI_SCRATCH_REG0 #define RADEON_LAST_CLEAR_REG RADEON_GUI_SCRATCH_REG2 @@ -1995,4 +2098,16 @@ #define RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR 51 #define RADEON_SS_SHININESS 60 +#define RADEON_TV_MASTER_CNTL 0x0800 +# define RADEON_TVCLK_ALWAYS_ONb (1 << 30) +#define RADEON_TV_DAC_CNTL 0x088c +# define RADEON_TV_DAC_CMPOUT (1 << 5) +#define RADEON_TV_PRE_DAC_MUX_CNTL 0x0888 +# define RADEON_Y_RED_EN (1 << 0) +# define RADEON_C_GRN_EN (1 << 1) +# define RADEON_CMP_BLU_EN (1 << 2) +# define RADEON_RED_MX_FORCE_DAC_DATA (6 << 4) +# define RADEON_GRN_MX_FORCE_DAC_DATA (6 << 8) +# define RADEON_BLU_MX_FORCE_DAC_DATA (6 << 12) +# define RADEON_TV_FORCE_DAC_DATA_SHIFT 16 #endif diff --git a/src/radeon_sarea.h b/src/radeon_sarea.h index 788c6f69..cd0a9824 100644 --- a/src/radeon_sarea.h +++ b/src/radeon_sarea.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h,v 1.5 2002/10/30 12:52:14 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h,v 1.6 2003/09/28 20:15:57 alanh Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, * VA Linux Systems Inc., Fremont, California. @@ -92,11 +92,11 @@ /* Keep these small for testing */ #define RADEON_NR_SAREA_CLIPRECTS 12 -/* There are 2 heaps (local/AGP). Each region within a heap is a +/* There are 2 heaps (local/GART). Each region within a heap is a * minimum of 64k, and there are at most 64 of them per heap. */ #define RADEON_CARD_HEAP 0 -#define RADEON_AGP_HEAP 1 +#define RADEON_GART_HEAP 1 #define RADEON_NR_TEX_HEAPS 2 #define RADEON_NR_TEX_REGIONS 64 #define RADEON_LOG_TEX_GRANULARITY 16 @@ -185,12 +185,6 @@ typedef struct { } radeon_texture_regs_t; typedef struct { - unsigned char next, prev; /* indices to form a circular LRU */ - unsigned char in_use; /* owned by a client, or free? */ - int age; /* tracked by clients to update local LRU's */ -} radeon_tex_region_t; - -typedef struct { /* The channel for communication of state information to the kernel * on firing a vertex buffer. */ @@ -224,9 +218,9 @@ typedef struct { * else's - simply eject them all in LRU order. */ /* Last elt is sentinal */ - radeon_tex_region_t texList[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1]; + drmTextureRegion texList[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1]; /* last time texture was uploaded */ - int texAge[RADEON_NR_TEX_HEAPS]; + unsigned int texAge[RADEON_NR_TEX_HEAPS]; int ctxOwner; /* last context to upload state */ int pfAllowPageFlip; /* set by the 2d driver, read by the client */ diff --git a/src/radeon_version.h b/src/radeon_version.h index a1170d38..4fa1027c 100644 --- a/src/radeon_version.h +++ b/src/radeon_version.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_version.h,v 1.8 2003/01/01 19:16:35 tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_version.h,v 1.10 2003/09/28 20:15:57 alanh Exp $ */ /* * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -38,7 +38,6 @@ #define RADEON_NAME "RADEON" #define RADEON_DRIVER_NAME "radeon" #define R200_DRIVER_NAME "r200" -#define RV250_DRIVER_NAME "r200" #define RADEON_VERSION_MAJOR 4 #define RADEON_VERSION_MINOR 0 diff --git a/src/radeon_video.c b/src/radeon_video.c index 44ee2e68..07c836b3 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c,v 1.24 2003/02/19 01:19:43 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c,v 1.31 2003/11/10 18:41:23 tsi Exp $ */ #include "radeon.h" #include "radeon_macros.h" @@ -22,10 +22,6 @@ extern int gRADEONEntityIndex; -#ifndef XvExtension -void RADEONInitVideo(ScreenPtr pScreen) {} -#else - static void RADEONInitOffscreenImages(ScreenPtr); static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr); @@ -40,9 +36,6 @@ static int RADEONPutImage(ScrnInfoPtr, short, short, short, short, short, static int RADEONQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *); - -static void RADEONResetVideo(ScrnInfoPtr); - static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) @@ -60,7 +53,7 @@ typedef struct { int red_intensity; int green_intensity; int blue_intensity; - int ecp_div; + int ecp_div; Bool doubleBuffer; unsigned char currentBuffer; @@ -79,16 +72,12 @@ typedef struct { void RADEONInitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - RADEONInfoPtr info = RADEONPTR(pScrn); XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; XF86VideoAdaptorPtr newAdaptor = NULL; int num_adaptors; - if(info->accel && info->accel->FillSolidRects) - { - newAdaptor = RADEONSetupImageVideo(pScreen); - RADEONInitOffscreenImages(pScreen); - } + newAdaptor = RADEONSetupImageVideo(pScreen); + RADEONInitOffscreenImages(pScreen); num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); if(newAdaptor) { @@ -184,7 +173,7 @@ REF_TRANSFORM trans[2] = /* Gamma curve definition */ -typedef struct +typedef struct { unsigned int gammaReg; unsigned int gammaSlope; @@ -192,7 +181,7 @@ typedef struct } GAMMA_SETTINGS; /* Recommended gamma curve parameters */ -GAMMA_SETTINGS def_gamma[18] = +GAMMA_SETTINGS def_gamma[18] = { {RADEON_OV0_GAMMA_000_00F, 0x100, 0x0000}, {RADEON_OV0_GAMMA_010_01F, 0x100, 0x0020}, @@ -233,10 +222,10 @@ GAMMA_SETTINGS def_gamma[18] = static void RADEONSetTransform (ScrnInfoPtr pScrn, float bright, float cont, - float sat, + float sat, float hue, - float red_intensity, - float green_intensity, + float red_intensity, + float green_intensity, float blue_intensity, CARD32 ref) { @@ -260,7 +249,7 @@ static void RADEONSetTransform (ScrnInfoPtr pScrn, CARD32 dwOvGCb, dwOvGCr; CARD32 dwOvBCb, dwOvBCr; - if (ref >= 2) + if (ref >= 2) return; OvHueSin = sin(hue); @@ -298,23 +287,23 @@ static void RADEONSetTransform (ScrnInfoPtr pScrn, OvBCr = CAdjBCr; OvROff = RedAdj + CAdjOff - OvLuma * Loff - (OvRCb + OvRCr) * Coff; - OvGOff = GreenAdj + CAdjOff - + OvGOff = GreenAdj + CAdjOff - OvLuma * Loff - (OvGCb + OvGCr) * Coff; - OvBOff = BlueAdj + CAdjOff - + OvBOff = BlueAdj + CAdjOff - OvLuma * Loff - (OvBCb + OvBCr) * Coff; #if 0 /* default constants */ OvROff = -888.5; OvGOff = 545; OvBOff = -1104; -#endif +#endif dwOvROff = ((INT32)(OvROff * 2.0)) & 0x1fff; dwOvGOff = ((INT32)(OvGOff * 2.0)) & 0x1fff; dwOvBOff = ((INT32)(OvBOff * 2.0)) & 0x1fff; /* * Whatever docs say about R200 having 3.8 format instead of 3.11 - * as in Radeon is a lie - * Or more precisely the location of bit fields is a lie + * as in Radeon is a lie + * Or more precisely the location of bit fields is a lie */ if(1 || info->ChipFamily < CHIP_FAMILY_R200) { @@ -380,7 +369,7 @@ static void RADEONSetColorKey(ScrnInfoPtr pScrn, CARD32 colorKey) OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_LOW, min); } -static void +void RADEONResetVideo(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -401,9 +390,12 @@ RADEONResetVideo(ScrnInfoPtr pScrn) OUTREG(RADEON_FCP_CNTL, RADEON_FCP0_SRC_GND); OUTREG(RADEON_CAP0_TRIG_CNTL, 0); RADEONSetColorKey(pScrn, pPriv->colorKey); - - if (info->ChipFamily == CHIP_FAMILY_R200 || - info->ChipFamily == CHIP_FAMILY_R300) { + + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350) || + (info->ChipFamily == CHIP_FAMILY_R200) || + (info->ChipFamily == CHIP_FAMILY_RADEON)) { int i; OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a20000); @@ -470,11 +462,11 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) pPriv->autopaint_colorkey = TRUE; /* - * Unlike older Mach64 chips, RADEON has only two ECP settings: + * Unlike older Mach64 chips, RADEON has only two ECP settings: * 0 for PIXCLK < 175Mhz, and 1 (divide by 2) - * for higher clocks, sure makes life nicer + * for higher clocks, sure makes life nicer */ - if(info->ModeReg.dot_clock_freq < 17500) + if(info->ModeReg.dot_clock_freq < 17500) pPriv->ecp_div = 0; else pPriv->ecp_div = 1; @@ -482,10 +474,18 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) #if 0 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dotclock is %g Mhz, setting ecp_div to %d\n", info->ModeReg.dot_clock_freq/100.0, pPriv->ecp_div); #endif - - OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & + + OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (pPriv->ecp_div << 8)); + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200) || + (info->ChipFamily == CHIP_FAMILY_RS300)) { + /* Force the overlay clock on for integrated chips + */ + OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) | (1<<18))); + } + info->adaptor = adapt; return adapt; @@ -525,8 +525,8 @@ RADEONSetupImageVideo(ScreenPtr pScreen) adapt->QueryImageAttributes = RADEONQueryImageAttributes; pPriv = (RADEONPortPrivPtr)(adapt->pPortPrivates[0].ptr); - REGION_INIT(pScreen, &(pPriv->clip), NullBox, 0); - + REGION_NULL(pScreen, &(pPriv->clip)); + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); xvSaturation = MAKE_ATOM("XV_SATURATION"); xvColor = MAKE_ATOM("XV_COLOR"); @@ -540,133 +540,12 @@ RADEONSetupImageVideo(ScreenPtr pScreen) xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); - + RADEONResetVideo(pScrn); return adapt; } -/* I really should stick this in miregion */ -static Bool -RegionsEqual(RegionPtr A, RegionPtr B) -{ - int *dataA, *dataB; - int num; - - num = REGION_NUM_RECTS(A); - if(num != REGION_NUM_RECTS(B)) - return FALSE; - - if((A->extents.x1 != B->extents.x1) || - (A->extents.x2 != B->extents.x2) || - (A->extents.y1 != B->extents.y1) || - (A->extents.y2 != B->extents.y2)) - return FALSE; - - dataA = (pointer)REGION_RECTS(A); - dataB = (pointer)REGION_RECTS(B); - - while(num--) { - if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) - return FALSE; - dataA += 2; - dataB += 2; - } - - return TRUE; -} - - -/* RADEONClipVideo - - - Takes the dst box in standard X BoxRec form (top and left - edges inclusive, bottom and right exclusive). The new dst - box is returned. The source boundaries are given (xa, ya - inclusive, xb, yb exclusive) and returned are the new source - boundaries in 16.16 fixed point. -*/ - -#define DummyScreen screenInfo.screens[0] - -static Bool -RADEONClipVideo( - BoxPtr dst, - INT32 *xa, - INT32 *xb, - INT32 *ya, - INT32 *yb, - RegionPtr reg, - INT32 width, - INT32 height -){ - INT32 vscale, hscale, delta; - BoxPtr extents = REGION_EXTENTS(DummyScreen, reg); - int diff; - - hscale = ((*xb - *xa) << 16) / (dst->x2 - dst->x1); - vscale = ((*yb - *ya) << 16) / (dst->y2 - dst->y1); - - *xa <<= 16; *xb <<= 16; - *ya <<= 16; *yb <<= 16; - - diff = extents->x1 - dst->x1; - if(diff > 0) { - dst->x1 = extents->x1; - *xa += diff * hscale; - } - diff = dst->x2 - extents->x2; - if(diff > 0) { - dst->x2 = extents->x2; - *xb -= diff * hscale; - } - diff = extents->y1 - dst->y1; - if(diff > 0) { - dst->y1 = extents->y1; - *ya += diff * vscale; - } - diff = dst->y2 - extents->y2; - if(diff > 0) { - dst->y2 = extents->y2; - *yb -= diff * vscale; - } - - if(*xa < 0) { - diff = (- *xa + hscale - 1)/ hscale; - dst->x1 += diff; - *xa += diff * hscale; - } - delta = *xb - (width << 16); - if(delta > 0) { - diff = (delta + hscale - 1)/ hscale; - dst->x2 -= diff; - *xb -= diff * hscale; - } - if(*xa >= *xb) return FALSE; - - if(*ya < 0) { - diff = (- *ya + vscale - 1)/ vscale; - dst->y1 += diff; - *ya += diff * vscale; - } - delta = *yb - (height << 16); - if(delta > 0) { - diff = (delta + vscale - 1)/ vscale; - dst->y2 -= diff; - *yb -= diff * vscale; - } - if(*ya >= *yb) return FALSE; - - if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) || - (dst->y1 != extents->y1) || (dst->y2 != extents->y2)) - { - RegionRec clipReg; - REGION_INIT(DummyScreen, &clipReg, dst, 1); - REGION_INTERSECT(DummyScreen, reg, reg, &clipReg); - REGION_UNINIT(DummyScreen, &clipReg); - } - return TRUE; -} - static void RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) { @@ -680,8 +559,6 @@ RADEONStopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) if(pPriv->videoStatus & CLIENT_VIDEO_ON) { RADEONWaitForFifo(pScrn, 2); OUTREG(RADEON_OV0_SCALE_CNTL, 0); - if (info->cursor_start) - xf86ForceHWCursor (pScrn->pScreen, FALSE); } if(info->videoLinear) { xf86FreeOffscreenLinear(info->videoLinear); @@ -715,11 +592,11 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, #define RTFHue(a) (((a)*3.1416)/1000.0) #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v)) - if(attribute == xvAutopaintColorkey) + if(attribute == xvAutopaintColorkey) { pPriv->autopaint_colorkey = ClipValue (value, 0, 1); } - else if(attribute == xvSetDefaults) + else if(attribute == xvSetDefaults) { pPriv->autopaint_colorkey = TRUE; pPriv->brightness = 0; @@ -731,69 +608,69 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, pPriv->blue_intensity = 0; pPriv->doubleBuffer = FALSE; setTransform = TRUE; - } - else if(attribute == xvBrightness) + } + else if(attribute == xvBrightness) { pPriv->brightness = ClipValue (value, -1000, 1000); setTransform = TRUE; - } - else if((attribute == xvSaturation) || (attribute == xvColor)) + } + else if((attribute == xvSaturation) || (attribute == xvColor)) { pPriv->saturation = ClipValue (value, -1000, 1000); setTransform = TRUE; - } - else if(attribute == xvContrast) + } + else if(attribute == xvContrast) { pPriv->contrast = ClipValue (value, -1000, 1000); setTransform = TRUE; - } - else if(attribute == xvHue) + } + else if(attribute == xvHue) { pPriv->hue = ClipValue (value, -1000, 1000); setTransform = TRUE; - } - else if(attribute == xvRedIntensity) + } + else if(attribute == xvRedIntensity) { pPriv->red_intensity = ClipValue (value, -1000, 1000); setTransform = TRUE; - } - else if(attribute == xvGreenIntensity) + } + else if(attribute == xvGreenIntensity) { pPriv->green_intensity = ClipValue (value, -1000, 1000); setTransform = TRUE; - } - else if(attribute == xvBlueIntensity) + } + else if(attribute == xvBlueIntensity) { pPriv->blue_intensity = ClipValue (value, -1000, 1000); setTransform = TRUE; - } - else if(attribute == xvDoubleBuffer) + } + else if(attribute == xvDoubleBuffer) { pPriv->doubleBuffer = ClipValue (value, 0, 1); pPriv->doubleBuffer = value; - } - else if(attribute == xvColorKey) + } + else if(attribute == xvColorKey) { pPriv->colorKey = value; RADEONSetColorKey (pScrn, pPriv->colorKey); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); - } - else + } + else return BadMatch; if (setTransform) { - RADEONSetTransform(pScrn, - RTFBrightness(pPriv->brightness), - RTFContrast(pPriv->contrast), - RTFSaturation(pPriv->saturation), + RADEONSetTransform(pScrn, + RTFBrightness(pPriv->brightness), + RTFContrast(pPriv->contrast), + RTFSaturation(pPriv->saturation), RTFHue(pPriv->hue), RTFIntensity(pPriv->red_intensity), RTFIntensity(pPriv->green_intensity), RTFIntensity(pPriv->blue_intensity), pPriv->transform_index); } - + return Success; } @@ -828,7 +705,7 @@ RADEONGetPortAttribute(ScrnInfoPtr pScrn, *value = pPriv->doubleBuffer ? 1 : 0; else if(attribute == xvColorKey) *value = pPriv->colorKey; - else + else return BadMatch; return Success; @@ -980,14 +857,14 @@ RADEONDisplayVideo( CARD32 scaler_src; /* Unlike older Mach64 chips, RADEON has only two ECP settings: 0 for PIXCLK < 175Mhz, and 1 (divide by 2) - for higher clocks, sure makes life nicer - + for higher clocks, sure makes life nicer + Here we need to find ecp_div again, as the user may have switched resolutions */ - if(info->ModeReg.dot_clock_freq < 17500) + if(info->ModeReg.dot_clock_freq < 17500) ecp_div = 0; else ecp_div = 1; - + OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (ecp_div << 8)); v_inc_shift = 20; @@ -995,7 +872,11 @@ RADEONDisplayVideo( v_inc_shift++; if (pScrn->currentMode->Flags & V_DBLSCAN) v_inc_shift--; - v_inc = (src_h << v_inc_shift) / drw_h; + 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 = ((src_w << (12 + ecp_div)) / drw_w); step_by = 1; @@ -1040,13 +921,16 @@ RADEONDisplayVideo( if (pScrn->currentMode->Flags & V_DBLSCAN) y_mult = 2; x_off = 8; - if (info->ChipFamily == CHIP_FAMILY_R200 || - info->ChipFamily == CHIP_FAMILY_R300) + + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350) || + (info->ChipFamily == CHIP_FAMILY_R200)) x_off = 0; /* Put the hardware overlay on CRTC2: * - * Since one hardware overlay can not be displayed on two heads + * Since one hardware overlay can not be displayed on two heads * at the same time, we might need to consider using software * rendering for the second head. */ @@ -1137,7 +1021,7 @@ RADEONPutImage( RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; INT32 xa, xb, ya, yb; unsigned char *dst_start; - int pitch, new_size, offset, s2offset, s3offset; + int new_size, offset, s2offset, s3offset; int srcPitch, srcPitch2, dstPitch; int top, left, npixels, nlines, bpp; BoxRec dstBox; @@ -1146,7 +1030,7 @@ RADEONPutImage( unsigned char *RADEONMMIO = info->MMIO; CARD32 surface_cntl = INREG(RADEON_SURFACE_CNTL); - OUTREG(RADEON_SURFACE_CNTL, (surface_cntl | + OUTREG(RADEON_SURFACE_CNTL, (surface_cntl | RADEON_NONSURF_AP0_SWP_32BPP) & ~RADEON_NONSURF_AP0_SWP_16BPP); #endif @@ -1180,7 +1064,8 @@ RADEONPutImage( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; - if(!RADEONClipVideo(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height)) + if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, + clipBoxes, width, height)) return Success; dstBox.x1 -= pScrn->frameX0; @@ -1189,7 +1074,6 @@ RADEONPutImage( dstBox.y2 -= pScrn->frameY0; bpp = pScrn->bitsPerPixel >> 3; - pitch = bpp * pScrn->displayWidth; switch(id) { case FOURCC_YV12: @@ -1272,20 +1156,14 @@ RADEONPutImage( #endif /* update cliplist */ - if(!RegionsEqual(&pPriv->clip, clipBoxes)) + if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { - REGION_COPY(pScreen, &pPriv->clip, clipBoxes); + REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); /* draw these */ if(pPriv->autopaint_colorkey) - (*info->accel->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, - (CARD32)~0, - REGION_NUM_RECTS(clipBoxes), - REGION_RECTS(clipBoxes)); + xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); } - if (info->cursor_start && !(pPriv->videoStatus & CLIENT_VIDEO_ON)) - xf86ForceHWCursor (pScrn->pScreen, TRUE); - RADEONDisplayVideo(pScrn, id, offset, offset, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); @@ -1350,8 +1228,6 @@ RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now) if(pPriv->offTime < now) { unsigned char *RADEONMMIO = info->MMIO; OUTREG(RADEON_OV0_SCALE_CNTL, 0); - if (info->cursor_start && pPriv->videoStatus & CLIENT_VIDEO_ON) - xf86ForceHWCursor (pScrn->pScreen, FALSE); pPriv->videoStatus = FREE_TIMER; pPriv->freeTime = now + FREE_DELAY; } @@ -1361,8 +1237,6 @@ RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now) xf86FreeOffscreenLinear(info->videoLinear); info->videoLinear = NULL; } - if (info->cursor_start && pPriv->videoStatus & CLIENT_VIDEO_ON) - xf86ForceHWCursor (pScrn->pScreen, FALSE); pPriv->videoStatus = 0; info->VideoTimerCallback = NULL; } @@ -1377,16 +1251,16 @@ typedef struct { Bool isOn; } OffscreenPrivRec, * OffscreenPrivPtr; -static int +static int RADEONAllocateSurface( ScrnInfoPtr pScrn, int id, - unsigned short w, + unsigned short w, unsigned short h, XF86SurfacePtr surface ){ FBLinearPtr linear; - int pitch, fbpitch, size, bpp; + int pitch, size, bpp; OffscreenPrivPtr pPriv; if((w > 1024) || (h > 1024)) return BadAlloc; @@ -1394,7 +1268,6 @@ RADEONAllocateSurface( w = (w + 1) & ~1; pitch = ((w << 1) + 15) & ~15; bpp = pScrn->bitsPerPixel >> 3; - fbpitch = bpp * pScrn->displayWidth; size = ((pitch * h) + bpp - 1) / bpp; if(!(linear = RADEONAllocateMemory(pScrn, NULL, size))) @@ -1423,7 +1296,7 @@ RADEONAllocateSurface( pPriv->isOn = FALSE; surface->pScrn = pScrn; - surface->id = id; + surface->id = id; surface->pitches[0] = pitch; surface->offsets[0] = linear->offset * bpp; surface->devPrivate.ptr = (pointer)pPriv; @@ -1431,7 +1304,7 @@ RADEONAllocateSurface( return Success; } -static int +static int RADEONStopSurface( XF86SurfacePtr surface ){ @@ -1447,7 +1320,7 @@ RADEONStopSurface( } -static int +static int RADEONFreeSurface( XF86SurfacePtr surface ){ @@ -1469,8 +1342,8 @@ RADEONGetSurfaceAttribute( Atom attribute, INT32 *value ){ - return RADEONGetPortAttribute(pScrn, attribute, value, - (pointer)(GET_PORT_PRIVATE(pScrn))); + return RADEONGetPortAttribute(pScrn, attribute, value, + (pointer)(GET_PORT_PRIVATE(pScrn))); } static int @@ -1479,17 +1352,17 @@ RADEONSetSurfaceAttribute( Atom attribute, INT32 value ){ - return RADEONSetPortAttribute(pScrn, attribute, value, - (pointer)(GET_PORT_PRIVATE(pScrn))); + return RADEONSetPortAttribute(pScrn, attribute, value, + (pointer)(GET_PORT_PRIVATE(pScrn))); } -static int +static int RADEONDisplaySurface( XF86SurfacePtr surface, - short src_x, short src_y, + short src_x, short src_y, short drw_x, short drw_y, - short src_w, short src_h, + short src_w, short src_h, short drw_w, short drw_h, RegionPtr clipBoxes ){ @@ -1501,7 +1374,7 @@ RADEONDisplaySurface( INT32 xa, ya, xb, yb; BoxRec dstBox; - + if (src_w > (drw_w << 4)) drw_w = src_w >> 4; if (src_h > (drw_h << 4)) @@ -1517,8 +1390,8 @@ RADEONDisplaySurface( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; - if (!RADEONClipVideo(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, - surface->width, surface->height)) + if (!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, + surface->width, surface->height)) return Success; dstBox.x1 -= pScrn->frameX0; @@ -1534,18 +1407,13 @@ RADEONDisplaySurface( xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); if (portPriv->autopaint_colorkey) - (*info->accel->FillSolidRects)(pScrn, portPriv->colorKey, GXcopy, - (CARD32)~0, - REGION_NUM_RECTS(clipBoxes), - REGION_RECTS(clipBoxes)); + xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); pPriv->isOn = TRUE; /* we've prempted the XvImage stream so set its free timer */ if (portPriv->videoStatus & CLIENT_VIDEO_ON) { - REGION_EMPTY(pScrn->pScreen, &portPriv->clip); + REGION_EMPTY(pScrn->pScreen, &portPriv->clip); UpdateCurrentTime(); - if (info->cursor_start) - xf86ForceHWCursor (pScrn->pScreen, FALSE); portPriv->videoStatus = FREE_TIMER; portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; info->VideoTimerCallback = RADEONVideoTimerCallback; @@ -1555,7 +1423,7 @@ RADEONDisplaySurface( } -static void +static void RADEONInitOffscreenImages(ScreenPtr pScreen) { /* ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -1567,7 +1435,7 @@ RADEONInitOffscreenImages(ScreenPtr pScreen) return; offscreenImages[0].image = &Images[0]; - offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | + offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; offscreenImages[0].alloc_surface = RADEONAllocateSurface; offscreenImages[0].free_surface = RADEONFreeSurface; @@ -1582,5 +1450,3 @@ RADEONInitOffscreenImages(ScreenPtr pScreen) xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); } - -#endif /* !XvExtension */ |