summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/aticonfig.c37
-rw-r--r--src/aticonsole.c430
-rw-r--r--src/atilock.c15
-rw-r--r--src/atimach64.c6
-rw-r--r--src/atimode.c145
-rw-r--r--src/atioption.c40
-rw-r--r--src/atioption.h31
-rw-r--r--src/atipreinit.c19
-rw-r--r--src/atiscreen.c12
-rw-r--r--src/atistruct.h20
10 files changed, 742 insertions, 13 deletions
diff --git a/src/aticonfig.c b/src/aticonfig.c
index 40ee24f6..1a1e6b46 100644
--- a/src/aticonfig.c
+++ b/src/aticonfig.c
@@ -134,6 +134,13 @@ ATIProcessOptions
#endif /* XF86DRI_DEVEL */
+#ifdef TV_OUT
+
+# define TvOut PublicOption[ATI_OPTION_TV_OUT].value.bool
+# define TvStd PublicOption[ATI_OPTION_TV_STD].value.str
+
+#endif /* TV_OUT */
+
# 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
@@ -165,6 +172,11 @@ ATIProcessOptions
#endif /* AVOID_CPIO */
+#ifdef TV_OUT
+
+ TvStd = "None"; /* No tv standard change requested */
+
+#endif
}
ReferenceClock = ((double)157500000.0) / ((double)11.0);
@@ -216,6 +228,31 @@ ATIProcessOptions
#endif /* AVOID_CPIO */
+#ifdef TV_OUT
+
+ if (TvOut && pATI->Chip < ATI_CHIP_264GT) {
+ /* Only allow this for 3D Rage (I) or greater chip ID
+ * AFAIK, no chips before this supported TV-Out
+ * mach64VT has support for TV tuner, but no TV-Out
+ */
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "TV Out not supported for this chip.\n");
+ } else {
+ ATITVStandard std;
+ pATI->OptionTvOut = TvOut;
+ pATI->OptionTvStd = ATI_TV_STD_INVALID;
+ for (std = 0; std < ATI_TV_STDS_MAX_VALID; std++) {
+ if (std != ATI_TV_STD_RESERVED1 && std != ATI_TV_STD_RESERVED2) {
+ if (strncasecmp(TvStd, ATITVStandardNames[std], ATI_TV_STDS_NAME_MAXLEN)==0) {
+ pATI->OptionTvStd = std;
+ break;
+ }
+ }
+ }
+ }
+
+#endif /* TV_OUT */
+
pATI->OptionMMIOCache = CacheMMIO;
pATI->OptionTestMMIOCache = TestCacheMMIO;
pATI->OptionProbeClocks = ProbeClocks;
diff --git a/src/aticonsole.c b/src/aticonsole.c
index 9c020e80..b3c09000 100644
--- a/src/aticonsole.c
+++ b/src/aticonsole.c
@@ -49,6 +49,20 @@
#include "xf86.h"
+#ifdef TV_OUT
+
+#include "atichip.h"
+#include "atiprint.h"
+#include "atioption.h"
+#include "vbe.h"
+
+static const char *vbeSymbols[] = {
+ "VBEGetVBEMode",
+ NULL
+};
+
+#endif /* TV_OUT */
+
/*
* ATISaveScreen --
*
@@ -142,6 +156,398 @@ ATISetDPMSMode
}
}
+#ifdef TV_OUT
+
+static void
+ATIProbeAndSetActiveDisplays
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI
+)
+{
+ vbeInfoPtr pVbe;
+ Bool tv_attached, crt_attached, lcd_attached;
+ int disp_request;
+ ATITVStandard tv_std, tv_std_request;
+
+ xf86LoaderRefSymLists(vbeSymbols, NULL);
+
+ if (xf86GetVerbosity() > 3) {
+ xf86ErrorFVerb(4, "\n Before TV-Out queries\n\n",
+ pScreenInfo->currentMode->name);
+ ATIPrintRegisters(pATI);
+ }
+
+ pATI->tvActive = FALSE;
+ pVbe = pATI->pVBE;
+ if (pVbe) {
+ /* LT Pro, XL, Mobility specific BIOS functions */
+ if (pATI->Chip == ATI_CHIP_264LTPRO ||
+ pATI->Chip == ATI_CHIP_264XL ||
+ pATI->Chip == ATI_CHIP_MOBILITY) {
+
+ /* Get attached display(s) - LTPro, XL, Mobility */
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0xa083;
+ pVbe->pInt10->cx = 0x0700; /* ch=0x07 - probe all, 0x01 CRT, 0x02 TV, 0x04 LCD */
+ xf86ExecX86int10(pVbe->pInt10);
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Attached displays: ax=0x%04x, cx=0x%04x\n",
+ pVbe->pInt10->ax, pVbe->pInt10->cx);
+
+ tv_attached = crt_attached = lcd_attached = FALSE;
+ if (pVbe->pInt10->ax & 0xff00) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Failed to detect attached displays\n");
+ } else {
+
+ if (pVbe->pInt10->cx & 0x3)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ " CRT attached\n");
+ crt_attached = TRUE;
+ }
+ else
+ crt_attached = FALSE;
+
+ if ((pVbe->pInt10->cx >> 2) & 0x3)
+ {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ " DFP/LCD attached\n");
+ lcd_attached = TRUE;
+ }
+ else
+ lcd_attached = FALSE;
+
+ switch ((pVbe->pInt10->cx >> 4) & 0x3) {
+ case 0:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ " No TV attached\n");
+ break;
+ case 1:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ " TV attached (composite connector)\n");
+ tv_attached = TRUE;
+ break;
+ case 2:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ " TV attached (S-video connector)\n");
+ tv_attached = TRUE;
+ break;
+ case 3:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ " TV attached (S-video/composite connectors)\n");
+ tv_attached = TRUE;
+ break;
+ default:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Unrecognized return code: 0x%04x\n",
+ pVbe->pInt10->cx);
+ }
+
+ }
+
+ /* Get active display - LTPro, XL, Mobility */
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0xa084;
+ pVbe->pInt10->bx = 0x0000; /* bh=0x00 get active, bh=0x01 set active */
+ xf86ExecX86int10(pVbe->pInt10);
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Active displays: ax=0x%04x, bx=0x%04x, cx=0x%04x\n",
+ pVbe->pInt10->ax, pVbe->pInt10->bx, pVbe->pInt10->cx);
+
+ if (pVbe->pInt10->ax & 0xff00) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Failed to detect active display\n");
+ } else {
+ if (pVbe->pInt10->bx & 0x1)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ " DFP/LCD is active\n");
+
+ if (pVbe->pInt10->bx & 0x2)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ " CRT is active\n");
+
+ if (pVbe->pInt10->bx & 0x4) {
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ " TV is active\n");
+
+ if (!tv_attached) {
+ /* tv not connected - disable tv */
+ disp_request = 0x00;
+ if (crt_attached)
+ disp_request |= 0x02; /* enable CRT */
+ if (lcd_attached && pATI->OptionPanelDisplay)
+ disp_request |= 0x01; /* enable DFP/LCD */
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0xa084;
+ pVbe->pInt10->bx = 0x0100; /* bh=0x01 set active */
+ pVbe->pInt10->cx = disp_request;
+ xf86ExecX86int10(pVbe->pInt10);
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV not present, disabling: ax=0x%04x, bx=0x%04x, cx=0x%04x\n",
+ pVbe->pInt10->ax, pVbe->pInt10->bx, pVbe->pInt10->cx);
+ if (pVbe->pInt10->ax & 0xff00) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Disabling TV failed\n");
+ }
+ } else {
+ pATI->tvActive = TRUE;
+ }
+
+ } else if (tv_attached && (pVbe->pInt10->bx & 0x0400)) {
+ /* tv connected and available - enable TV */
+ disp_request = 0x04; /* enable TV */
+
+#if 0
+ /* This works, but CRT image is vertically compressed */
+ if (crt_attached)
+ disp_request |= 0x02; /* enable CRT */
+ /* NOTE: For me, LCD+TV does NOT work */
+ /*if (lcd_attached && pATI->OptionPanelDisplay)
+ disp_request |= 0x01; * enable DFP/LCD */
+#endif
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0xa084;
+ pVbe->pInt10->bx = 0x0100; /* bh=0x01 set active */
+ pVbe->pInt10->cx = disp_request; /* try to activate TV */
+ xf86ExecX86int10(pVbe->pInt10);
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Setting TV active: ax=0x%04x, bx=0x%04x, cx=0x%04x\n",
+ pVbe->pInt10->ax, pVbe->pInt10->bx, pVbe->pInt10->cx);
+ if (pVbe->pInt10->ax & 0xff00) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Setting TV active failed\n");
+ } else {
+ pATI->tvActive = TRUE;
+ }
+ }
+ }
+
+ } else { /* pATI->Chip < ATI_CHIP_264LTPRO */
+ /* TVOut Hooks - Check for TVOut BIOS/hardware */
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0xa019;
+ pVbe->pInt10->cx = 0x0000; /* TVOut BIOS query */
+ xf86ExecX86int10(pVbe->pInt10);
+
+ tv_attached = FALSE;
+
+ if (pVbe->pInt10->ax & 0xff00) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Failed to detect TV-Out BIOS\n");
+ } else {
+ switch (pVbe->pInt10->ax & 0x0003) {
+ case 3:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV-Out BIOS detected and active\n");
+
+ /* TV attached query */
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0xa070;
+ pVbe->pInt10->bx = 0x0002; /* Sub-function: return tv attached info */
+ xf86ExecX86int10(pVbe->pInt10);
+
+ if (pVbe->pInt10->ax & 0xff00) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Failed to detect if TV is attached\n");
+ } else {
+ switch (pVbe->pInt10->cx & 0x0003) {
+ case 3:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV attached to composite and S-video connectors\n");
+ tv_attached = TRUE;
+ break;
+ case 2:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV attached to S-video connector\n");
+ tv_attached = TRUE;
+ break;
+ case 1:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV attached to composite connector\n");
+ tv_attached = TRUE;
+ break;
+ default:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV is not attached\n");
+ }
+ }
+ break;
+ case 1:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV-Out BIOS service is not available due to"
+ "a system BIOS error or TV-Out hardware not being installed\n");
+ break;
+ default:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "No TV-Out BIOS or hardware detected\n");
+ }
+ }
+ }
+
+ /* Return TV-Out configuration
+ * see Programmer's Guide under "TV Out Specific Functions"
+ * It's not clear exactly which adapters support these
+ */
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0xa070;
+ pVbe->pInt10->bx = 0x00;
+ xf86ExecX86int10(pVbe->pInt10);
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV-Out query: ax=0x%04x, bx=0x%04x, cx=0x%04x, dx=0x%04x\n",
+ pVbe->pInt10->ax, pVbe->pInt10->bx, pVbe->pInt10->cx, pVbe->pInt10->dx);
+
+ if (pVbe->pInt10->ax & 0xff00) {
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Failed to detect TV-Out configuration.\n");
+
+ } else if (pVbe->pInt10->bx == 0) {
+ if (pVbe->pInt10->dx == 0) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV-Out is not detected.\n");
+ } else {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV-Out is detected but not supported.\n");
+ }
+
+ } else if ((pVbe->pInt10->cx & 0xff) == 0) {
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV-Out is currently disabled.\n");
+ if (tv_attached && pATI->Chip < ATI_CHIP_264LTPRO) {
+ /* Try to enable TV-Out */
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0xa070;
+ pVbe->pInt10->bx = 0x0001; /* Sub-function: Select TV Out */
+ /* cl=0x001 enable, cl=0x000 disable,
+ * cl=0x080 disable with feature connector bit preserved
+ */
+ pVbe->pInt10->cx = 0x0001;
+
+ xf86ExecX86int10(pVbe->pInt10);
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Setting TV active: ax=0x%04x, bx=0x%04x, cx=0x%04x\n",
+ pVbe->pInt10->ax, pVbe->pInt10->bx, pVbe->pInt10->cx);
+
+ if (pVbe->pInt10->ax & 0xff00) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Setting TV active failed\n");
+ } else {
+ pATI->tvActive = TRUE;
+ }
+ }
+
+ } else {
+ pATI->tvActive = TRUE;
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV-Out is currently enabled (TV-Out revision code: %d).\n",
+ (pVbe->pInt10->dx >> 8) & 0xff);
+
+ switch ((pVbe->pInt10->cx >> 8) & 0xff) {
+ case 0:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "Reference frequency 29.49892\n");
+ break;
+ case 1:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "Reference frequency 28.63636\n");
+ break;
+ case 2:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "Reference frequency 14.31818\n");
+ break;
+ case 3:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "Reference frequency 27.00000\n");
+ break;
+ default:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Unknown reference frequency cx=0x%04x\n", pVbe->pInt10->cx);
+
+ }
+
+ /* Return TV standard
+ * see Programmer's Guide under "TV Out Specific Functions"
+ * It's not clear exactly which adapters support these
+ */
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0xa071;
+ pVbe->pInt10->bx = 0x00;
+ xf86ExecX86int10(pVbe->pInt10);
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "TV standard query result: ax=0x%04x, bx=0x%04x, cx=0x%04x\n",
+ pVbe->pInt10->ax, pVbe->pInt10->bx, pVbe->pInt10->cx);
+
+ if (pVbe->pInt10->ax & 0xff00) {
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Failed to return TV standard.\n");
+ } else {
+ tv_std = pVbe->pInt10->cx & 0x00ff;
+ switch (tv_std) {
+ case ATI_TV_STD_NTSC:
+ case ATI_TV_STD_PAL:
+ case ATI_TV_STD_PALM:
+ case ATI_TV_STD_PAL60:
+ case ATI_TV_STD_NTSCJ:
+ case ATI_TV_STD_PALCN:
+ case ATI_TV_STD_PALN:
+ case ATI_TV_STD_SCARTPAL:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Current TV standard: %s\n", ATITVStandardNames[tv_std]);
+ break;
+ default:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Unrecognized TV standard return code cx=0x%04x\n",
+ pVbe->pInt10->cx);
+ }
+
+ tv_std_request = pATI->OptionTvStd;
+ if (tv_std_request < 0 ||
+ tv_std_request > ATI_TV_STD_NONE ||
+ tv_std_request == ATI_TV_STD_RESERVED1 ||
+ tv_std_request == ATI_TV_STD_RESERVED2) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Invalid TV standard requested, please check configuration file\n");
+ } else if (tv_std_request != ATI_TV_STD_NONE) {
+ /* Set TV standard if requested (LT Pro not supported) */
+ if (pATI->Chip != ATI_CHIP_264LTPRO &&
+ tv_std_request != tv_std) {
+
+ pVbe->pInt10->num = 0x10;
+ pVbe->pInt10->ax = 0xa070;
+ pVbe->pInt10->bx = 0x0003; /* sub-function: set TV standard */
+ pVbe->pInt10->cx = tv_std_request;
+ xf86ExecX86int10(pVbe->pInt10);
+ if (pVbe->pInt10->ax & 0xff00)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Failed to set TV standard\n");
+ else
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
+ "Set TV standard to %s\n", ATITVStandardNames[tv_std_request]);
+ } else {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
+ "Setting TV standard not supported on ATI Rage LT Pro\n");
+ }
+ }
+ }
+
+ }
+ } else {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "VBE module not loaded\n");
+ }
+}
+
+#endif /* TV_OUT */
+
/*
* ATIEnterGraphics --
*
@@ -170,9 +576,28 @@ ATIEnterGraphics
pScreenInfo->vtSema = TRUE;
+#ifdef TV_OUT
+ if (pATI->OptionTvOut) {
+
+ xf86LoaderRefSymLists(vbeSymbols, NULL);
+
+ if (pATI->pVBE) {
+ if (VBEGetVBEMode(pATI->pVBE, &pATI->vbemode)) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "Saving VESA mode: 0x%x\n",
+ pATI->vbemode);
+ }
+ }
+ }
+#endif /* TV_OUT */
+
/* Save current state */
ATIModeSave(pScreenInfo, pATI, &pATI->OldHW);
+#ifdef TV_OUT
+ if (pATI->OptionTvOut)
+ ATIProbeAndSetActiveDisplays(pScreenInfo, pATI);
+#endif /* TV_OUT */
+
/* Set graphics state */
ATIModeSet(pScreenInfo, pATI, &pATI->NewHW);
@@ -207,6 +632,11 @@ ATILeaveGraphics
if (!xf86ServerIsExiting())
ATIModeSave(pScreenInfo, pATI, &pATI->NewHW);
+#ifdef TV_OUT
+ if (pATI->OptionTvOut)
+ ATIProbeAndSetActiveDisplays(pScreenInfo, pATI);
+#endif /* TV_OUT */
+
/* Restore mode in effect on server entry */
ATIModeSet(pScreenInfo, pATI, &pATI->OldHW);
diff --git a/src/atilock.c b/src/atilock.c
index 8dafcf76..8b40d6de 100644
--- a/src/atilock.c
+++ b/src/atilock.c
@@ -154,9 +154,14 @@ ATIUnlock
*/
if (!pATI->OptionBIOSDisplay && (pATI->Chip != ATI_CHIP_264XL))
{
- pATI->LockData.scratch_reg3 = inr(SCRATCH_REG3);
- outr(SCRATCH_REG3,
- pATI->LockData.scratch_reg3 | DISPLAY_SWITCH_DISABLE);
+#ifdef TV_OUT
+ pATI->LockData.scratch_reg3 = inr(SCRATCH_REG3) & ~DISPLAY_SWITCH_DISABLE;
+ outr(SCRATCH_REG3, pATI->LockData.scratch_reg3);
+#else
+ pATI->LockData.scratch_reg3 = inr(SCRATCH_REG3);
+ outr(SCRATCH_REG3,
+ pATI->LockData.scratch_reg3 | DISPLAY_SWITCH_DISABLE);
+#endif /* TV_OUT */
}
}
@@ -575,14 +580,18 @@ ATILock
if ((pATI->LCDPanelID >= 0) && (pATI->Chip != ATI_CHIP_264LT))
{
outr(LCD_INDEX, pATI->LockData.lcd_index);
+#ifndef TV_OUT
if (!pATI->OptionBIOSDisplay && (pATI->Chip != ATI_CHIP_264XL))
outr(SCRATCH_REG3, pATI->LockData.scratch_reg3);
+#endif /* TV_OUT */
}
if (pATI->Chip >= ATI_CHIP_264VTB)
{
outr(MPP_CONFIG, pATI->LockData.mpp_config);
outr(MPP_STROBE_SEQ, pATI->LockData.mpp_strobe_seq);
+#ifndef TV_OUT
outr(TVO_CNTL, pATI->LockData.tvo_cntl);
+#endif /* TV_OUT */
if (pATI->Chip >= ATI_CHIP_264GT2C)
{
outr(HW_DEBUG, pATI->LockData.hw_debug);
diff --git a/src/atimach64.c b/src/atimach64.c
index dfbe8d76..0693c287 100644
--- a/src/atimach64.c
+++ b/src/atimach64.c
@@ -617,7 +617,11 @@ ATIMach64Calculate
{
pMode->Flags &= ~(V_PHSYNC | V_NHSYNC | V_PVSYNC | V_NVSYNC);
- if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
+ if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0)
+#ifdef TV_OUT
+ && !pATI->tvActive
+#endif
+)
VDisplay = pATI->LCDVertical;
else
VDisplay = pMode->CrtcVDisplay;
diff --git a/src/atimode.c b/src/atimode.c
index 02cf3193..63b0dcdb 100644
--- a/src/atimode.c
+++ b/src/atimode.c
@@ -1,6 +1,6 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimode.c,v 1.17 2003/04/23 21:51:29 tsi Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimode.c,v 1.18 2004/01/05 16:42:03 tsi Exp $ */
/*
- * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ * Copyright 2000 through 2004 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
@@ -35,6 +35,18 @@
#include "atiwonder.h"
#include "atiwonderio.h"
+#ifdef TV_OUT
+
+#include "vbe.h"
+
+static const char *vbeSymbols[] = {
+ "VBESetVBEMode",
+ "vbeFree",
+ NULL
+};
+
+#endif /* TV_OUT */
+
#ifndef AVOID_CPIO
/*
@@ -125,7 +137,6 @@ ATISwap
seq4 = GetReg(SEQX, 0x04U);
gra1 = GetReg(GRAX, 0x01U);
gra3 = GetReg(GRAX, 0x03U);
- gra4 = GetReg(GRAX, 0x04U);
gra5 = GetReg(GRAX, 0x05U);
gra6 = GetReg(GRAX, 0x06U);
gra8 = GetReg(GRAX, 0x08U);
@@ -365,7 +376,7 @@ ATIModeSave
int Index;
- /* Get bank to bank 0 */
+ /* Get back to bank 0 */
(*pATIHW->SetBank)(pATI, 0);
#endif /* AVOID_CPIO */
@@ -908,11 +919,17 @@ ATIModeCalculate
else
MaxScalerClock = 80000; /* Conservative */
pATIHW->pll_vclk_cntl &= ~PLL_ECP_DIV;
- /* XXX Don't do this for TVOut! */
- ECPClock = pMode->SynthClock;
- for (Index = 0; (ECPClock > MaxScalerClock) && (Index < 2); Index++)
- ECPClock >>= 1;
- pATIHW->pll_vclk_cntl |= SetBits(Index, PLL_ECP_DIV);
+#ifdef TV_OUT
+ if (!pATI->OptionTvOut) {
+#endif /* TV_OUT */
+ /* XXX Don't do this for TVOut! */
+ ECPClock = pMode->SynthClock;
+ for (Index = 0; (ECPClock > MaxScalerClock) && (Index < 2); Index++)
+ ECPClock >>= 1;
+ pATIHW->pll_vclk_cntl |= SetBits(Index, PLL_ECP_DIV);
+#ifdef TV_OUT
+ }
+#endif /* TV_OUT */
}
else if (pATI->DAC == ATI_DAC_IBMRGB514)
{
@@ -922,6 +939,108 @@ ATIModeCalculate
return TRUE;
}
+#ifdef TV_OUT
+
+static void
+ATISetVBEMode
+(
+ ScrnInfoPtr pScreenInfo,
+ ATIPtr pATI,
+ ATIHWPtr pATIHW
+)
+{
+
+ xf86LoaderRefSymLists(vbeSymbols, NULL);
+
+ if (pATIHW->crtc == ATI_CRTC_MACH64) {
+ int vbemode, modekey;
+
+ /* Find a suitable VESA VBE mode, if one exists */
+ modekey = (pScreenInfo->depth << 16) |
+ (pScreenInfo->currentMode->HDisplay);
+
+ switch (modekey) {
+ case (15<<16)|(640):
+ vbemode = 0x110;
+ break;
+ case (16<<16)|(640):
+ vbemode = 0x111;
+ break;
+#if 0
+ case (24<<16)|(640):
+ vbemode = 0x112;
+ break;
+#endif
+ case (15<<16)|(800):
+ vbemode = 0x113;
+ break;
+ case (16<<16)|(800):
+ vbemode = 0x114;
+ break;
+#if 0
+ case (24<<16)|(800):
+ vbemode = 0x115;
+ break;
+#endif
+ case (15<<16)|(1024):
+ vbemode = 0x116;
+ break;
+ case (16<<16)|(1024):
+ vbemode = 0x117;
+ break;
+#if 0
+ case (24<<16)|(1024):
+ vbemode = 0x118;
+ break;
+#endif
+ default:
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Mode not supported for TV-Out: depth: %ld HDisplay: %ld\n",
+ modekey>>16, modekey & 0xffff);
+ return;
+ }
+
+ if (pATI->pVBE) {
+
+ /* Preserve video memory contents */
+ vbemode |= (1<<15);
+
+ if (VBESetVBEMode(pATI->pVBE, vbemode, NULL)) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "VBESetMode: 0x%X (width: %d, pitch: %d, depth: %d)\n",
+ vbemode,
+ pScreenInfo->currentMode->HDisplay,
+ pScreenInfo->displayWidth,
+ pScreenInfo->depth);
+ outr(CRTC_OFF_PITCH,
+ SetBits(pScreenInfo->displayWidth>>3, CRTC_PITCH));
+ } else {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "VBESetMode failed.\n");
+ }
+ } else {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "VBE module not loaded.\n");
+ }
+ } else {
+ /* restore text mode with VBESetMode */
+ if (pATI->pVBE) {
+ if (VBESetVBEMode(pATI->pVBE, pATI->vbemode, NULL)) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, "Restoring VESA mode: 0x%x\n",
+ pATI->vbemode);
+ } else {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "VBESetMode failed.\n");
+ }
+ } else {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "VBE module not loaded.\n");
+ }
+ }
+ if (xf86ServerIsExiting()) {
+ if (pATI->pVBE) vbeFree(pATI->pVBE);
+ if (pATI->pInt10) xf86FreeInt10(pATI->pInt10);
+ }
+}
+
+#endif /* TV_OUT */
+
/*
* ATIModeSet --
*
@@ -1165,6 +1284,14 @@ ATIModeSet
/* Reset hardware cursor caching */
pATI->CursorXOffset = pATI->CursorYOffset = (CARD16)(-1);
+#ifdef TV_OUT
+
+ /* Set VBE mode for TV-Out */
+ if (pATI->OptionTvOut /* && pATI->tvActive */)
+ ATISetVBEMode(pScreenInfo, pATI, pATIHW);
+
+#endif /* TV_OUT */
+
#ifndef AVOID_CPIO
/* Restore video memory */
diff --git a/src/atioption.c b/src/atioption.c
index 24536fcc..2b97abf5 100644
--- a/src/atioption.c
+++ b/src/atioption.c
@@ -30,6 +30,28 @@
#include "radeon_probe.h"
#include "r128_probe.h"
+#ifdef TV_OUT
+
+/*
+ * List of supported TV standard names
+ */
+const char *ATITVStandardNames[ATI_TV_STDS_MAX_VALID+1] = {
+ "NTSC",
+ "PAL",
+ "PAL-M",
+ "PAL-60",
+ "NTSC-J",
+ "PAL-CN",
+ "PAL-N",
+ "Reserved1",
+ "Reserved2",
+ "SCART-PAL",
+ "None",
+ "Invalid"
+};
+
+#endif /* TV_OUT */
+
/*
* Recognised XF86Config options.
*/
@@ -123,6 +145,24 @@ const OptionInfoRec ATIPublicOptions[] =
#endif /* XF86DRI_DEVEL */
+#ifdef TV_OUT
+ {
+ ATI_OPTION_TV_OUT,
+ "tv_out",
+ OPTV_BOOLEAN,
+ {0, },
+ FALSE
+ },
+ {
+ ATI_OPTION_TV_STD,
+ "tv_standard",
+ OPTV_STRING,
+ {0, },
+ FALSE
+ },
+
+#endif /* TV_OUT */
+
{
ATI_OPTION_MMIO_CACHE,
"mmio_cache",
diff --git a/src/atioption.h b/src/atioption.h
index 85970796..51778a4c 100644
--- a/src/atioption.h
+++ b/src/atioption.h
@@ -56,6 +56,13 @@ typedef enum
#endif /* XF86DRI_DEVEL */
+#ifdef TV_OUT
+
+ ATI_OPTION_TV_OUT,
+ ATI_OPTION_TV_STD,
+
+#endif /* TV_OUT */
+
ATI_OPTION_MMIO_CACHE,
ATI_OPTION_TEST_MMIO_CACHE,
ATI_OPTION_PANEL_DISPLAY,
@@ -65,6 +72,30 @@ typedef enum
ATI_OPTION_SWCURSOR
} ATIPublicOptionType;
+#ifdef TV_OUT
+
+#define ATI_TV_STDS_MAX_VALID 11
+#define ATI_TV_STDS_NAME_MAXLEN 9
+
+typedef enum {
+ ATI_TV_STD_NTSC = 0,
+ ATI_TV_STD_PAL,
+ ATI_TV_STD_PALM,
+ ATI_TV_STD_PAL60,
+ ATI_TV_STD_NTSCJ,
+ ATI_TV_STD_PALCN,
+ ATI_TV_STD_PALN,
+ ATI_TV_STD_RESERVED1, /* NOT usable */
+ ATI_TV_STD_RESERVED2, /* NOT usable */
+ ATI_TV_STD_SCARTPAL,
+ ATI_TV_STD_NONE, /* OK, means no tv standard change requested */
+ ATI_TV_STD_INVALID /* Invalid tv standard requested */
+} ATITVStandard;
+
+extern const char * ATITVStandardNames[];
+
+#endif /* TV_OUT */
+
extern const OptionInfoRec ATIPublicOptions[];
extern const unsigned long ATIPublicOptionSize;
diff --git a/src/atipreinit.c b/src/atipreinit.c
index ebe54ad1..4327efb1 100644
--- a/src/atipreinit.c
+++ b/src/atipreinit.c
@@ -597,6 +597,13 @@ ATIPreInit
#else /* AVOID_CPIO */
+#ifdef TV_OUT
+
+ pATI->pVBE = NULL;
+ pATI->pInt10 = NULL;
+
+#endif /* TV_OUT */
+
/*
* If there is an ix86-style BIOS, ensure its initialisation entry point
* has been executed, and retrieve DDC and VBE information from it.
@@ -629,9 +636,17 @@ ATIPreInit
if ((pVBE = VBEInit(pInt10Info, pATI->iEntity)))
{
ConfiguredMonitor = vbeDoEDID(pVBE, pDDCModule);
+#ifdef TV_OUT
+ pATI->pInt10 = pInt10Info;
+ pATI->pVBE = pVBE;
+ pVBE = NULL;
+#else
vbeFree(pVBE);
+#endif /* TV_OUT */
}
+#ifndef TV_OUT
xf86UnloadSubModule(pVBEModule);
+#endif /* TV_OUT */
}
if (!(flags & PROBE_DETECT))
@@ -654,9 +669,13 @@ ATIPreInit
}
}
+#ifndef TV_OUT
/* De-activate int10 */
xf86FreeInt10(pInt10Info);
xf86UnloadSubModule(pInt10Module);
+#else
+ pInt10Info = NULL;
+#endif /* TV_OUT */
if (flags & PROBE_DETECT)
{
diff --git a/src/atiscreen.c b/src/atiscreen.c
index 9f8b6982..812aa2c3 100644
--- a/src/atiscreen.c
+++ b/src/atiscreen.c
@@ -47,6 +47,12 @@
#include "mach64_sarea.h"
#endif
+#ifdef TV_OUT
+
+#include "atichip.h"
+
+#endif /* TV_OUT */
+
#include "shadowfb.h"
#include "xf86cmap.h"
@@ -553,6 +559,12 @@ ATIScreenInit
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScreenInfo->scrnIndex, pScreenInfo->options);
+#ifdef TV_OUT
+ /* Fix-up TV out after ImpacTV probe */
+ if (pATI->OptionTvOut && pATI->Chip < ATI_CHIP_264GTPRO)
+ ATISwitchMode(0, pScreenInfo->currentMode, 0);
+#endif /* TV_OUT */
+
#ifdef XF86DRI_DEVEL
/* DRI finalization */
diff --git a/src/atistruct.h b/src/atistruct.h
index 87ff0a1c..edee9e3a 100644
--- a/src/atistruct.h
+++ b/src/atistruct.h
@@ -46,6 +46,12 @@
#endif /* XF86DRI_DEVEL */
+#ifdef TV_OUT
+
+#include "vbe.h"
+
+#endif /* TV_OUT */
+
#include "xaa.h"
#include "xf86Cursor.h"
#include "xf86Pci.h"
@@ -436,6 +442,13 @@ typedef struct _ATIRec
CARD8 OptionLinear:1; /* Use linear fb aperture when available */
#endif /* AVOID_CPIO */
+
+#ifdef TV_OUT
+
+ CARD8 OptionTvOut; /* Enable TV out if TV is connected */
+ CARD8 OptionTvStd; /* Requested TV standard - see ATITVStandard enum in atioption.h */
+
+#endif /* TV_OUT */
CARD8 OptionMMIOCache:1; /* Cache MMIO writes */
CARD8 OptionTestMMIOCache:1;/* Test MMIO cache integrity */
@@ -485,6 +498,13 @@ typedef struct _ATIRec
#endif /* XF86DRI_DEVEL */
+#ifdef TV_OUT
+ /* TV out */
+ vbeInfoPtr pVBE;
+ xf86Int10InfoPtr pInt10;
+ int vbemode; /* saved text mode */
+ Bool tvActive;
+#endif /* TV_OUT */
} ATIRec;
#define ATIPTR(_p) ((ATIPtr)((_p)->driverPrivate))