|
|
|
|
File: [XFree86 CVS] / xc / programs / Xserver / hw / xfree86 / drivers / ati / atimach64.c
(download)
Revision: 1.27, Wed Dec 13 00:25:12 2000 UTC (12 years, 6 months ago) by tsi Branch: MAIN CVS Tags: xf-4_0_3b, xf-4_0_3a, xf-4_0_3, xf-4_0_2c, xf-4_0_2b, xf-4_0_2a, xf-4_0_2-branch, xf-4_0_2-bindist, xf-4_0_2, xf-4_0_1Zc, xf-4_0_1Zb Changes since 1.26: +76 -38 lines 1175. Fix ATI DPMS support on panels by mimicking BIOS behaviour more closely
(Marc La France).
|
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.c,v 1.26 2000/11/02 16:55:28 tsi Exp $ */
/*
* Copyright 1997 through 2000 by Marc Aurele La France (TSI @ UQV), tsi@ualberta.ca
*
* 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 "atibus.h"
#include "atichip.h"
#include "atimach64.h"
#include "atimach64io.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
* all video modes generated by the driver.
*/
void
ATIMach64PreInit
(
ScrnInfoPtr pScreenInfo,
ATIPtr pATI,
ATIHWPtr pATIHW
)
{
CARD32 bus_cntl, config_cntl;
int tmp;
#ifndef AVOID_CPIO
if (pATI->depth <= 4)
pATIHW->crtc_off_pitch = SetBits(pATI->displayWidth >> 4, CRTC_PITCH);
else
#endif /* AVOID_CPIO */
{
pATIHW->crtc_off_pitch = SetBits(pATI->displayWidth >> 3, CRTC_PITCH);
}
bus_cntl = inr(BUS_CNTL);
pATIHW->bus_cntl = (bus_cntl & ~BUS_HOST_ERR_INT_EN) | BUS_HOST_ERR_INT;
if (pATI->Chip < ATI_CHIP_264VTB)
{
pATIHW->bus_cntl &= ~(BUS_FIFO_ERR_INT_EN | BUS_ROM_DIS);
pATIHW->bus_cntl |= SetBits(15, BUS_FIFO_WS) | BUS_FIFO_ERR_INT;
}
else
pATIHW->bus_cntl |= BUS_APER_REG_DIS;
if (pATI->Chip >= ATI_CHIP_264VT)
pATIHW->bus_cntl |= BUS_EXT_REG_EN; /* Enable Block 1 */
#ifdef AVOID_CPIO
pATIHW->mem_vga_wp_sel = SetBits(0, MEM_VGA_WPS0) |
SetBits(1, MEM_VGA_WPS1);
pATIHW->mem_vga_rp_sel = SetBits(0, MEM_VGA_RPS0) |
SetBits(1, MEM_VGA_RPS1);
#else /* AVOID_CPIO */
pATIHW->mem_vga_wp_sel = SetBits(0, MEM_VGA_WPS0) |
SetBits(pATIHW->nPlane, MEM_VGA_WPS1);
pATIHW->mem_vga_rp_sel = SetBits(0, MEM_VGA_RPS0) |
SetBits(pATIHW->nPlane, MEM_VGA_RPS1);
#endif /* AVOID_CPIO */
pATIHW->dac_cntl = inr(DAC_CNTL) &
~(DAC1_CLK_SEL | DAC_PALETTE_ACCESS_CNTL | DAC_8BIT_EN);
if ((pATI->depth > 8) || (pScreenInfo->rgbBits == 8))
pATIHW->dac_cntl |= DAC_8BIT_EN;
pATIHW->config_cntl = config_cntl = inr(CONFIG_CNTL);
#ifndef AVOID_CPIO
if (pATI->UseSmallApertures)
pATIHW->config_cntl |= CFG_MEM_VGA_AP_EN;
else
#endif /* AVOID_CPIO */
{
pATIHW->config_cntl &= ~CFG_MEM_VGA_AP_EN;
}
if (pATI->LinearBase && (pATI->Chip < ATI_CHIP_264CT))
{
/* Replace linear aperture size and address */
pATIHW->config_cntl &= ~(CFG_MEM_AP_LOC | CFG_MEM_AP_SIZE);
pATIHW->config_cntl |= SetBits(pATI->LinearBase >> 22, CFG_MEM_AP_LOC);
if ((pATI->Chip < ATI_CHIP_264CT) && (pATI->VideoRAM < 4096))
pATIHW->config_cntl |= SetBits(1, CFG_MEM_AP_SIZE);
else
pATIHW->config_cntl |= SetBits(2, CFG_MEM_AP_SIZE);
}
/* Draw engine setup */
if (pATI->OptionAccel)
{
/* Ensure apertures are enabled */
outr(BUS_CNTL, pATIHW->bus_cntl);
outr(CONFIG_CNTL, pATIHW->config_cntl);
/*
* When possible, max out command FIFO size.
*/
if (pATI->Chip >= ATI_CHIP_264VT4)
pATIHW->gui_cntl = inm(GUI_CNTL) & ~CMDFIFO_SIZE_MODE;
/* Initialise destination registers */
pATIHW->dst_off_pitch =
SetBits((pATI->displayWidth * pATI->XModifier) >> 3, DST_PITCH);
pATIHW->dst_cntl = DST_X_DIR | DST_Y_DIR | DST_LAST_PEL;
/* Initialise source registers */
pATIHW->src_off_pitch = pATIHW->dst_off_pitch;
pATIHW->src_width1 = pATIHW->src_height1 =
pATIHW->src_width2 = pATIHW->src_height2 = 1;
pATIHW->src_cntl = SRC_LINE_X_DIR;
/* Initialise scissor, allowing for offscreen areas */
pATIHW->sc_right = (pATI->displayWidth * pATI->XModifier) - 1;
tmp = (pScreenInfo->videoRam * (1024 * 8) /
pATI->displayWidth / pATI->bitsPerPixel) - 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) |
SetWord(pATI->NewHW.sc_top, 0);
/* Initialise data path */
pATIHW->dp_frgd_clr = (CARD32)(-1);
pATIHW->dp_write_mask = (CARD32)(-1);
switch (pATI->depth)
{
case 8:
pATIHW->dp_chain_mask = DP_CHAIN_8BPP;
pATIHW->dp_pix_width = DP_BYTE_PIX_ORDER |
SetBits(PIX_WIDTH_8BPP, DP_DST_PIX_WIDTH) |
SetBits(PIX_WIDTH_8BPP, DP_SRC_PIX_WIDTH) |
SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
break;
case 15:
pATIHW->dp_chain_mask = DP_CHAIN_15BPP_1555;
pATIHW->dp_pix_width = DP_BYTE_PIX_ORDER |
SetBits(PIX_WIDTH_15BPP, DP_DST_PIX_WIDTH) |
SetBits(PIX_WIDTH_15BPP, DP_SRC_PIX_WIDTH) |
SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
break;
case 16:
pATIHW->dp_chain_mask = DP_CHAIN_16BPP_565;
pATIHW->dp_pix_width = DP_BYTE_PIX_ORDER |
SetBits(PIX_WIDTH_16BPP, DP_DST_PIX_WIDTH) |
SetBits(PIX_WIDTH_16BPP, DP_SRC_PIX_WIDTH) |
SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
break;
case 24:
if (pATI->bitsPerPixel == 24)
{
pATIHW->dp_chain_mask = DP_CHAIN_24BPP_888;
pATIHW->dp_pix_width = DP_BYTE_PIX_ORDER |
SetBits(PIX_WIDTH_8BPP, DP_DST_PIX_WIDTH) |
SetBits(PIX_WIDTH_8BPP, DP_SRC_PIX_WIDTH) |
SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
}
else
{
pATIHW->dp_chain_mask = DP_CHAIN_32BPP_8888;
pATIHW->dp_pix_width = DP_BYTE_PIX_ORDER |
SetBits(PIX_WIDTH_32BPP, DP_DST_PIX_WIDTH) |
SetBits(PIX_WIDTH_32BPP, DP_SRC_PIX_WIDTH) |
SetBits(PIX_WIDTH_1BPP, DP_HOST_PIX_WIDTH);
}
break;
default:
break;
}
pATIHW->dp_mix = SetBits(MIX_SRC, DP_FRGD_MIX) |
SetBits(MIX_DST, DP_BKGD_MIX);
pATIHW->dp_src = DP_MONO_SRC_ALLONES |
SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC);
/* Initialise colour compare */
pATIHW->clr_cmp_msk = (1 << pATI->depth) - 1;
/* Restore aperture enablement */
outr(BUS_CNTL, bus_cntl);
outr(CONFIG_CNTL, config_cntl);
}
}
/*
* ATIMach64Save --
*
* This function is called to save the Mach64 portion of the current video
* state.
*/
void
ATIMach64Save
(
ATIPtr pATI,
ATIHWPtr pATIHW
)
{
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);
pATIHW->crtc_off_pitch = inr(CRTC_OFF_PITCH);
pATIHW->crtc_gen_cntl = inr(CRTC_GEN_CNTL);
pATIHW->ovr_clr = inr(OVR_CLR);
pATIHW->ovr_wid_left_right = inr(OVR_WID_LEFT_RIGHT);
pATIHW->ovr_wid_top_bottom = inr(OVR_WID_TOP_BOTTOM);
pATIHW->clock_cntl = inr(CLOCK_CNTL);
pATIHW->bus_cntl = inr(BUS_CNTL);
pATIHW->mem_vga_wp_sel = inr(MEM_VGA_WP_SEL);
pATIHW->mem_vga_rp_sel = inr(MEM_VGA_RP_SEL);
pATIHW->dac_cntl = inr(DAC_CNTL);
pATIHW->config_cntl = inr(CONFIG_CNTL);
/* Save draw engine state */
if (pATI->OptionAccel && (pATIHW == &pATI->OldHW))
{
/* Ensure apertures are enabled */
outr(BUS_CNTL, pATI->NewHW.bus_cntl);
outr(CONFIG_CNTL, pATI->NewHW.config_cntl);
ATIMach64WaitForIdle(pATI);
/* Save FIFO size */
if (pATI->Chip >= ATI_CHIP_264VT4)
pATIHW->gui_cntl = inm(GUI_CNTL);
/* Save destination registers */
pATIHW->dst_off_pitch = inm(DST_OFF_PITCH);
pATIHW->dst_x = inm(DST_X);
pATIHW->dst_y = inm(DST_Y);
pATIHW->dst_height = inm(DST_HEIGHT);
pATIHW->dst_bres_err = inm(DST_BRES_ERR);
pATIHW->dst_bres_inc = inm(DST_BRES_INC);
pATIHW->dst_bres_dec = inm(DST_BRES_DEC);
pATIHW->dst_cntl = inm(DST_CNTL);
/* Save source registers */
pATIHW->src_off_pitch = inm(SRC_OFF_PITCH);
pATIHW->src_x = inm(SRC_X);
pATIHW->src_y = inm(SRC_Y);
pATIHW->src_width1 = inm(SRC_WIDTH1);
pATIHW->src_height1 = inm(SRC_HEIGHT1);
pATIHW->src_x_start = inm(SRC_X_START);
pATIHW->src_y_start = inm(SRC_Y_START);
pATIHW->src_width2 = inm(SRC_WIDTH2);
pATIHW->src_height2 = inm(SRC_HEIGHT2);
pATIHW->src_cntl = inm(SRC_CNTL);
/* Save host data register */
pATIHW->host_cntl = inm(HOST_CNTL);
/* Save pattern registers */
pATIHW->pat_reg0 = inm(PAT_REG0);
pATIHW->pat_reg1 = inm(PAT_REG1);
pATIHW->pat_cntl = inm(PAT_CNTL);
/* Save scissor registers */
pATIHW->sc_left = pATI->sc_left = inm(SC_LEFT);
pATIHW->sc_right = pATI->sc_right = inm(SC_RIGHT);
pATIHW->sc_top = pATI->sc_top = inm(SC_TOP);
pATIHW->sc_bottom = pATI->sc_bottom = inm(SC_BOTTOM);
/* Save data path registers */
pATIHW->dp_bkgd_clr = inm(DP_BKGD_CLR);
pATIHW->dp_frgd_clr = inm(DP_FRGD_CLR);
pATIHW->dp_write_mask = inm(DP_WRITE_MASK);
pATIHW->dp_chain_mask = inm(DP_CHAIN_MASK);
pATIHW->dp_pix_width = inm(DP_PIX_WIDTH);
pATIHW->dp_mix = inm(DP_MIX);
pATIHW->dp_src = inm(DP_SRC);
/* Save colour compare registers */
pATIHW->clr_cmp_clr = inm(CLR_CMP_CLR);
pATIHW->clr_cmp_msk = inm(CLR_CMP_MSK);
pATIHW->clr_cmp_cntl = inm(CLR_CMP_CNTL);
/* Save context */
pATIHW->context_mask = inm(CONTEXT_MASK);
/* Restore aperture enablement */
outr(BUS_CNTL, pATIHW->bus_cntl);
outr(CONFIG_CNTL, pATIHW->config_cntl);
}
}
/*
* ATIMach64Calculate --
*
* This function is called to fill in the Mach64 portion of an ATIHWRec.
*/
void
ATIMach64Calculate
(
ATIPtr pATI,
ATIHWPtr pATIHW,
DisplayModePtr pMode
)
{
int VDisplay;
/* If not already done adjust horizontal timings */
if (!pMode->CrtcHAdjusted)
{
pMode->CrtcHAdjusted = TRUE;
/* XXX Deal with Blank Start/End and overscan later */
pMode->CrtcHDisplay = (pMode->HDisplay >> 3) - 1;
pMode->CrtcHSyncStart = (pMode->HSyncStart >> 3) - 1;
pMode->CrtcHSyncEnd = (pMode->HSyncEnd >> 3) - 1;
pMode->CrtcHTotal = (pMode->HTotal >> 3) - 1;
/* 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)
pMode->CrtcHSyncStart--;
else if (pMode->CrtcHSyncEnd < pMode->CrtcHTotal)
pMode->CrtcHSyncEnd++;
}
}
/*
* Always re-do vertical adjustments.
*/
pMode->CrtcVDisplay = pMode->VDisplay;
pMode->CrtcVSyncStart = pMode->VSyncStart;
pMode->CrtcVSyncEnd = pMode->VSyncEnd;
pMode->CrtcVTotal = pMode->VTotal;
if ((pATI->Chip >= ATI_CHIP_264CT) &&
((pMode->Flags & V_DBLSCAN) || (pMode->VScan > 1)))
{
pMode->CrtcVDisplay <<= 1;
pMode->CrtcVSyncStart <<= 1;
pMode->CrtcVSyncEnd <<= 1;
pMode->CrtcVTotal <<= 1;
}
/*
* Might as well default to the same as VGA with respect to sync
* polarities.
*/
if ((!(pMode->Flags & (V_PHSYNC | V_NHSYNC))) ||
(!(pMode->Flags & (V_PVSYNC | V_NVSYNC))))
{
pMode->Flags &= ~(V_PHSYNC | V_NHSYNC | V_PVSYNC | V_NVSYNC);
if (!pATI->OptionCRT && (pATI->LCDPanelID >= 0))
VDisplay = pATI->LCDVertical;
else
VDisplay = pMode->CrtcVDisplay;
if (VDisplay < 400)
pMode->Flags |= V_PHSYNC | V_NVSYNC;
else if (VDisplay < 480)
pMode->Flags |= V_NHSYNC | V_PVSYNC;
else if (VDisplay < 768)
pMode->Flags |= V_NHSYNC | V_NVSYNC;
else
pMode->Flags |= V_PHSYNC | V_PVSYNC;
}
pMode->CrtcVDisplay--;
pMode->CrtcVSyncStart--;
pMode->CrtcVSyncEnd--;
pMode->CrtcVTotal--;
/* Make sure sync pulse is not too wide */
if ((pMode->CrtcVSyncEnd - pMode->CrtcVSyncStart) >
(int)MaxBits(CRTC_V_SYNC_WID))
pMode->CrtcVSyncEnd = pMode->CrtcVSyncStart + MaxBits(CRTC_V_SYNC_WID);
pMode->CrtcVAdjusted = TRUE; /* Redundant */
/* Build register contents */
pATIHW->crtc_h_total_disp =
SetBits(pMode->CrtcHTotal, CRTC_H_TOTAL) |
SetBits(pMode->CrtcHDisplay, CRTC_H_DISP);
pATIHW->crtc_h_sync_strt_wid =
SetBits(pMode->CrtcHSyncStart, CRTC_H_SYNC_STRT) |
SetBits(pMode->CrtcHSkew, CRTC_H_SYNC_DLY) | /* ? */
SetBits(GetBits(pMode->CrtcHSyncStart, 0x0100U),
CRTC_H_SYNC_STRT_HI) |
SetBits(pMode->CrtcHSyncEnd - pMode->CrtcHSyncStart,
CRTC_H_SYNC_WID);
if (pMode->Flags & V_NHSYNC)
pATIHW->crtc_h_sync_strt_wid |= CRTC_H_SYNC_POL;
pATIHW->crtc_v_total_disp =
SetBits(pMode->CrtcVTotal, CRTC_V_TOTAL) |
SetBits(pMode->CrtcVDisplay, CRTC_V_DISP);
pATIHW->crtc_v_sync_strt_wid =
SetBits(pMode->CrtcVSyncStart, CRTC_V_SYNC_STRT) |
SetBits(pMode->CrtcVSyncEnd - pMode->CrtcVSyncStart,
CRTC_V_SYNC_WID);
if (pMode->Flags & V_NVSYNC)
pATIHW->crtc_v_sync_strt_wid |= CRTC_V_SYNC_POL;
pATIHW->crtc_gen_cntl = inr(CRTC_GEN_CNTL) &
~(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_PIX_WIDTH | CRTC_BYTE_PIX_ORDER | CRTC_FIFO_LWM |
CRTC_VGA_128KAP_PAGING | CRTC_VFC_SYNC_TRISTATE |
CRTC_LOCK_REGS | /* Already off, but ... */
CRTC_SYNC_TRISTATE | CRTC_DISP_REQ_EN |
CRTC_VGA_TEXT_132 | CRTC_CUR_B_TEST);
pATIHW->crtc_gen_cntl |=
CRTC_EXT_DISP_EN | CRTC_EN | CRTC_VGA_LINEAR | CRTC_CNT_EN;
switch (pATI->depth)
{
#ifndef AVOID_CPIO
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;
#endif /* AVOID_CPIO */
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 ((pMode->Flags & V_DBLSCAN) || (pMode->VScan > 1))
pATIHW->crtc_gen_cntl |= CRTC_DBL_SCAN_EN;
if (pMode->Flags & V_INTERLACE)
pATIHW->crtc_gen_cntl |= CRTC_INTERLACE_EN;
if (pATI->OptionCSync || (pMode->Flags & (V_CSYNC | V_PCSYNC)))
pATIHW->crtc_gen_cntl |= CRTC_CSYNC_EN;
/* For now, set display FIFO low water mark as high as possible */
if (pATI->Chip < ATI_CHIP_264VTB)
pATIHW->crtc_gen_cntl |= CRTC_FIFO_LWM;
}
/*
* ATIMach64Set --
*
* This function is called to load a Mach64's accelerator CRTC and draw engine.
*/
void
ATIMach64Set
(
ATIPtr pATI,
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 */
/* 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);
/* Set pixel clock */
outr(CLOCK_CNTL, pATIHW->clock_cntl | CLOCK_STROBE);
/* 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);
/* Finalise CRTC setup and turn on the screen */
outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl);
/* Load draw engine */
if (pATI->OptionAccel)
{
/* Clobber MMIO cache */
(void)memset(pATI->MMIOCached, 0, SizeOf(pATI->MMIOCached));
/* Ensure apertures are enabled */
outr(BUS_CNTL, pATI->NewHW.bus_cntl);
outr(CONFIG_CNTL, pATI->NewHW.config_cntl);
pATI->EngineIsBusy = TRUE; /* Force engine poll */
ATIMach64WaitForIdle(pATI);
/* Load FIFO size */
if (pATI->Chip >= ATI_CHIP_264VT4)
{
outm(GUI_CNTL, pATIHW->gui_cntl);
pATI->nAvailableFIFOEntries = 0;
ATIMach64PollEngineStatus(pATI);
}
/* Set FIFO depth */
pATI->nFIFOEntries = pATI->nAvailableFIFOEntries;
/* Load destination registers */
ATIMach64WaitForFIFO(pATI, 7);
outf(DST_OFF_PITCH, pATIHW->dst_off_pitch);
outf(DST_Y_X, SetWord(pATIHW->dst_x, 1) | SetWord(pATIHW->dst_y, 0));
outf(DST_HEIGHT, pATIHW->dst_height);
outf(DST_BRES_ERR, pATIHW->dst_bres_err);
outf(DST_BRES_INC, pATIHW->dst_bres_inc);
outf(DST_BRES_DEC, pATIHW->dst_bres_dec);
outf(DST_CNTL, pATIHW->dst_cntl);
/* Load source registers */
ATIMach64WaitForFIFO(pATI, 6);
outf(SRC_OFF_PITCH, pATIHW->src_off_pitch);
outf(SRC_Y_X, SetWord(pATIHW->src_x, 1) | SetWord(pATIHW->src_y, 0));
outf(SRC_HEIGHT1_WIDTH1,
SetWord(pATIHW->src_width1, 1) | SetWord(pATIHW->src_height1, 0));
outf(SRC_Y_X_START,
SetWord(pATIHW->src_x_start, 1) | SetWord(pATIHW->src_y_start, 0));
outf(SRC_HEIGHT2_WIDTH2,
SetWord(pATIHW->src_width2, 1) | SetWord(pATIHW->src_height2, 0));
outf(SRC_CNTL, pATIHW->src_cntl);
/* Load host data register */
ATIMach64WaitForFIFO(pATI, 1);
outf(HOST_CNTL, pATIHW->host_cntl);
/* Set host transfer window address and size clamp */
pATI->pHOST_DATA =
(CARD8 *)pATI->pBlock[GetBits(HOST_DATA_0, BLOCK_SELECT)] +
(HOST_DATA_0 & MM_IO_SELECT);
pATI->nHostFIFOEntries = pATI->nFIFOEntries >> 1;
if (pATI->nHostFIFOEntries > 16)
pATI->nHostFIFOEntries = 16;
/* Load pattern registers */
ATIMach64WaitForFIFO(pATI, 3);
outf(PAT_REG0, pATIHW->pat_reg0);
outf(PAT_REG1, pATIHW->pat_reg1);
outf(PAT_CNTL, pATIHW->pat_cntl);
/* Load scissor registers */
ATIMach64WaitForFIFO(pATI, 2);
outf(SC_LEFT_RIGHT,
SetWord(pATIHW->sc_right, 1) | SetWord(pATIHW->sc_left, 0));
outf(SC_TOP_BOTTOM,
SetWord(pATIHW->sc_bottom, 1) | SetWord(pATIHW->sc_top, 0));
pATI->sc_left = pATIHW->sc_left;
pATI->sc_right = pATIHW->sc_right;
pATI->sc_top = pATIHW->sc_top;
pATI->sc_bottom = pATIHW->sc_bottom;
/* Load data path registers */
ATIMach64WaitForFIFO(pATI, 7);
outf(DP_BKGD_CLR, pATIHW->dp_bkgd_clr);
outf(DP_FRGD_CLR, pATIHW->dp_frgd_clr);
outf(DP_WRITE_MASK, pATIHW->dp_write_mask);
outf(DP_CHAIN_MASK, pATIHW->dp_chain_mask);
outf(DP_PIX_WIDTH, pATIHW->dp_pix_width);
outf(DP_MIX, pATIHW->dp_mix);
outf(DP_SRC, pATIHW->dp_src);
/* Load colour compare registers */
ATIMach64WaitForFIFO(pATI, 3);
outf(CLR_CMP_CLR, pATIHW->clr_cmp_clr);
outf(CLR_CMP_MSK, pATIHW->clr_cmp_msk);
outf(CLR_CMP_CNTL, pATIHW->clr_cmp_cntl);
/* Load context mask */
ATIMach64WaitForFIFO(pATI, 1);
outf(CONTEXT_MASK, pATIHW->context_mask);
ATIMach64WaitForIdle(pATI);
if (pATI->OptionMMIOCache)
{
/*
* Enable write caching for selected MMIO registers. This can only
* be done for those registers whose value does not change without
* driver intervention.
*/
CacheRegister(SRC_CNTL);
CacheRegister(HOST_CNTL);
CacheRegister(PAT_REG0);
CacheRegister(PAT_REG1);
CacheRegister(PAT_CNTL);
CacheRegister(SC_LEFT_RIGHT);
CacheRegister(SC_TOP_BOTTOM);
CacheRegister(DP_BKGD_CLR);
CacheRegister(DP_FRGD_CLR);
CacheRegister(DP_WRITE_MASK);
CacheRegister(DP_MIX);
CacheRegister(CLR_CMP_CLR);
CacheRegister(CLR_CMP_MSK);
CacheRegister(CLR_CMP_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);
}
/*
* ATIMach64SaveScreen --
*
* This function blanks or unblanks a Mach64 screen.
*/
void
ATIMach64SaveScreen
(
ATIPtr pATI,
int Mode
)
{
CARD32 crtc_gen_cntl = inr(CRTC_GEN_CNTL);
switch (Mode)
{
case SCREEN_SAVER_OFF:
case SCREEN_SAVER_FORCER:
outr(CRTC_GEN_CNTL, crtc_gen_cntl & ~CRTC_DISPLAY_DIS);
break;
case SCREEN_SAVER_ON:
case SCREEN_SAVER_CYCLE:
outr(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_DISPLAY_DIS);
break;
default:
break;
}
}
/*
* ATIMach64SetDPMSMode --
*
* This function sets a Mach64's VESA Display Power Management Signaling mode.
*/
void
ATIMach64SetDPMSMode
(
ATIPtr pATI,
int DPMSMode
)
{
CARD32 crtc_gen_cntl =
inr(CRTC_GEN_CNTL) & ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS);
switch (DPMSMode)
{
case DPMSModeOn: /* HSync on, VSync on */
break;
case DPMSModeStandby: /* HSync off, VSync on */
crtc_gen_cntl |= CRTC_HSYNC_DIS;
break;
case DPMSModeSuspend: /* HSync on, VSync off */
crtc_gen_cntl |= CRTC_VSYNC_DIS;
break;
case DPMSModeOff: /* HSync off, VSync off */
crtc_gen_cntl |= CRTC_HSYNC_DIS | CRTC_VSYNC_DIS;
break;
default: /* Muffle compiler */
return;
}
outr(CRTC_GEN_CNTL, crtc_gen_cntl);
if ((pATI->LCDPanelID >= 0) && !pATI->OptionCRT)
{
CARD32 lcd_index = 0;
/*
* ATI's BIOS simply turns the panel on and off, so do the same by
* default, but keep the previous behaviour around for reference.
*/
if (pATI->OptionDevel)
{
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 &= ~(STANDBY_NOW | SUSPEND_NOW);
switch (DPMSMode)
{
case DPMSModeOn:
break;
case DPMSModeStandby:
power_management |= STANDBY_NOW;
break;
case DPMSModeSuspend:
power_management |= SUSPEND_NOW;
break;
case DPMSModeOff:
power_management |= STANDBY_NOW | SUSPEND_NOW; /* ? */
break;
default: /* Muffle compiler */
return;
}
/* Panel power management seems to involve the engine */
if (pATI->OptionAccel)
ATIMach64WaitForIdle(pATI);
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);
outr(LCD_INDEX, lcd_index);
}
}
else
{
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);
}
if (DPMSMode == DPMSModeOn)
lcd_gen_ctrl |= LCD_ON;
else
lcd_gen_ctrl &= ~LCD_ON;
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);
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 = *(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);
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;
ATIMach64WaitForFIFO(pATI, 3);
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
outf(DP_WRITE_MASK, planemask);
outf(DP_SRC, DP_MONO_SRC_ALLONES |
SetBits(SRC_BLIT, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
if (TransparencyColour == -1)
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);
}
}
/*
* 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);
if (pATI->XModifier == 1)
outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
ATIMach64WaitForFIFO(pATI, 5);
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
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(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
}
/*
* 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_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
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(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);
if (pATI->XModifier == 1)
outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
if (bg == -1)
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
SetBits(MIX_DST, DP_BKGD_MIX));
else
{
ATIMach64WaitForFIFO(pATI, 2);
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
SetBits(ATIMach64ALU[rop], DP_BKGD_MIX));
outf(DP_BKGD_CLR, bg);
}
ATIMach64WaitForFIFO(pATI, 7);
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);
outf(PAT_REG0, patx);
outf(PAT_REG1, paty);
outf(PAT_CNTL, PAT_MONO_EN);
outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
}
/*
* 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);
if (pATI->XModifier == 1)
outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
if (bg == -1)
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
SetBits(MIX_DST, DP_BKGD_MIX));
else
{
ATIMach64WaitForFIFO(pATI, 2);
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
SetBits(ATIMach64ALU[rop], DP_BKGD_MIX));
outf(DP_BKGD_CLR, bg);
}
ATIMach64WaitForFIFO(pATI, 4);
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);
outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
}
/*
* 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];
CARD32 *pDst, *pSrc;
int w = pATI->ExpansionBitmapWidth;
int nDWord;
unsigned int iDWord;
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.
*/
iDWord = 16 - nDWord;
pDst = (CARD32 *)pATI->pHOST_DATA - iDWord;
pSrc = pBitmapData - iDWord;
/*
* Transfer current chunk. With any luck, the compiler won't mangle
* this too badly...
*/
switch (iDWord)
{
case 0: MMIO_OUT32(pDst + 0, 0, *(pSrc + 0));
case 1: MMIO_OUT32(pDst + 1, 0, *(pSrc + 1));
case 2: MMIO_OUT32(pDst + 2, 0, *(pSrc + 2));
case 3: MMIO_OUT32(pDst + 3, 0, *(pSrc + 3));
case 4: MMIO_OUT32(pDst + 4, 0, *(pSrc + 4));
case 5: MMIO_OUT32(pDst + 5, 0, *(pSrc + 5));
case 6: MMIO_OUT32(pDst + 6, 0, *(pSrc + 6));
case 7: MMIO_OUT32(pDst + 7, 0, *(pSrc + 7));
case 8: MMIO_OUT32(pDst + 8, 0, *(pSrc + 8));
case 9: MMIO_OUT32(pDst + 9, 0, *(pSrc + 9));
case 10: MMIO_OUT32(pDst + 10, 0, *(pSrc + 10));
case 11: MMIO_OUT32(pDst + 11, 0, *(pSrc + 11));
case 12: MMIO_OUT32(pDst + 12, 0, *(pSrc + 12));
case 13: MMIO_OUT32(pDst + 13, 0, *(pSrc + 13));
case 14: MMIO_OUT32(pDst + 14, 0, *(pSrc + 14));
case 15: MMIO_OUT32(pDst + 15, 0, *(pSrc + 15));
default: /* Muffle compiler */
break;
}
/* 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.
*/
Bool
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 =
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 TRUE;
/* Solid lines */
pXAAInfo->SetupForSolidLine = ATIMach64SetupForSolidLine;
pXAAInfo->SubsequentSolidHorVertLine = ATIMach64SubsequentSolidHorVertLine;
pXAAInfo->SubsequentSolidBresenhamLine =
ATIMach64SubsequentSolidBresenhamLine;
return TRUE;
}
|
Powered by ViewCVS 0.9.2 |