diff options
author | Dave Airlie <airlied@linux.ie> | 2005-03-26 00:53:01 +0000 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2005-03-26 00:53:01 +0000 |
commit | 04cbb8d174cc5e3c7ecdd4e171170213ecb3c7ed (patch) | |
tree | c10f24d28e53dba3db25540f774f3ae1c98f6ab0 | |
parent | 5be4bf9000bdf58584a10a6b8e285d0f173304fa (diff) |
bugzilla #2057 (https://bugs.freedesktop.org/show_bug.cgi?id=2057)
attachment #1516 (https://bugs.freedesktop.org/attachment.cgi?id=1516)
Add TVOUT Support for Mach64 (Leif Delgass, fixed up for Xorg by me).
-rw-r--r-- | src/aticonfig.c | 37 | ||||
-rw-r--r-- | src/aticonsole.c | 430 | ||||
-rw-r--r-- | src/atilock.c | 15 | ||||
-rw-r--r-- | src/atimach64.c | 6 | ||||
-rw-r--r-- | src/atimode.c | 145 | ||||
-rw-r--r-- | src/atioption.c | 40 | ||||
-rw-r--r-- | src/atioption.h | 31 | ||||
-rw-r--r-- | src/atipreinit.c | 19 | ||||
-rw-r--r-- | src/atiscreen.c | 12 | ||||
-rw-r--r-- | src/atistruct.h | 20 |
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)) |