diff options
Diffstat (limited to 'src/atimach64.c')
-rw-r--r-- | src/atimach64.c | 1243 |
1 files changed, 1243 insertions, 0 deletions
diff --git a/src/atimach64.c b/src/atimach64.c new file mode 100644 index 0000000..95a9c07 --- /dev/null +++ b/src/atimach64.c @@ -0,0 +1,1243 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atimach64.c,v 1.52 2003/04/23 21:51:28 tsi Exp $ */ +/* + * Copyright 1997 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 + * 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. + */ +/* + * DRI support by: + * Manuel Teira + * Leif Delgass <ldelgass@retinalburn.net> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ati.h" +#include "atibus.h" +#include "atichip.h" +#include "atidac.h" +#include "atimach64.h" +#include "atimach64accel.h" +#include "atimach64io.h" +#include "atirgb514.h" + +#ifndef DPMS_SERVER +# define DPMS_SERVER +#endif +#include <X11/extensions/dpms.h> + +/* + * 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); + } + + if ((pATI->LockData.crtc_gen_cntl & CRTC_CSYNC_EN) && !pATI->OptionCSync) + { + xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE, + "Using composite sync to match input timing.\n"); + pATI->OptionCSync = TRUE; + } + + pATIHW->bus_cntl = bus_cntl = inr(BUS_CNTL); + if (pATI->Chip < ATI_CHIP_264VT4) + pATIHW->bus_cntl = (pATIHW->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 if (pATI->MMIOInLinear) + { + pATIHW->bus_cntl &= ~BUS_APER_REG_DIS; + } + 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->Chip >= ATI_CHIP_264CT) + pATIHW->dac_cntl &= ~DAC_FEA_CON_EN; + if (pATI->rgbBits == 8) + pATIHW->dac_cntl |= DAC_8BIT_EN; + + pATIHW->gen_test_cntl = pATI->LockData.gen_test_cntl & ~GEN_CUR_EN; + if (pATI->DAC == ATI_DAC_IBMRGB514) + pATIHW->gen_test_cntl |= GEN_OVR_OUTPUT_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); + } + + if (pATI->Chip >= ATI_CHIP_264VTB) + { + pATIHW->mem_cntl = (pATI->LockData.mem_cntl & + ~(CTL_MEM_LOWER_APER_ENDIAN | CTL_MEM_UPPER_APER_ENDIAN)) | + SetBits(CTL_MEM_APER_BYTE_ENDIAN, CTL_MEM_LOWER_APER_ENDIAN); + + switch (pATI->bitsPerPixel) + { + default: + pATIHW->mem_cntl |= SetBits(CTL_MEM_APER_BYTE_ENDIAN, + CTL_MEM_UPPER_APER_ENDIAN); + break; + + case 16: + pATIHW->mem_cntl |= SetBits(CTL_MEM_APER_WORD_ENDIAN, + CTL_MEM_UPPER_APER_ENDIAN); + break; + + case 32: + pATIHW->mem_cntl |= SetBits(CTL_MEM_APER_LONG_ENDIAN, + CTL_MEM_UPPER_APER_ENDIAN); + break; + } + + pATIHW->mpp_config = inr(MPP_CONFIG); + pATIHW->mpp_config &= + ~(MPP_PRESCALE | MPP_NSTATES | MPP_FORMAT | MPP_WAIT_STATE | + MPP_INSERT_WAIT | MPP_TRISTATE_ADDR | MPP_AUTO_INC_EN | + MPP_CHKREQ_EN | MPP_BUFFER_SIZE | MPP_BUFFER_MODE | MPP_BUSY); + pATIHW->mpp_config |= + (MPP_NSTATES_8 | MPP_FORMAT_DA8 | SetBits(4, MPP_WAIT_STATE) | + MPP_CHKRDY_EN | MPP_READ_EARLY | MPP_RW_MODE | MPP_EN); + pATIHW->mpp_strobe_seq = inr(MPP_STROBE_SEQ); + pATIHW->mpp_strobe_seq &= ~(MPP_STB0_SEQ | MPP_STB1_SEQ); + pATIHW->mpp_strobe_seq |= + SetBits(0x0087U, MPP_STB0_SEQ) | SetBits(0x0083U, MPP_STB1_SEQ); + pATIHW->tvo_cntl = 0; + } + + /* Draw engine setup */ + if (pATI->Block0Base) + { + /* 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) + +#ifdef XF86DRI_DEVEL + + /* Changing the FIFO depth seems to interfere with DMA, so use + * default of 128 entries (0x01) + */ + pATIHW->gui_cntl = (inm(GUI_CNTL) & ~CMDFIFO_SIZE_MODE) | 0x01; + +#else /* XF86DRI_DEVEL */ + + pATIHW->gui_cntl = inm(GUI_CNTL) & ~CMDFIFO_SIZE_MODE; + +#endif /* XF86DRI_DEVEL */ + + /* 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 = pATI->displayWidth * pATI->bitsPerPixel; + tmp = (((pScreenInfo->videoRam * (1024 * 8)) + tmp - 1) / tmp) - 1; + if (tmp > ATIMach64MaxY) + tmp = ATIMach64MaxY; + pATIHW->sc_bottom = tmp; + pATI->sc_left_right = SetWord(pATI->NewHW.sc_right, 1) | + SetWord(pATI->NewHW.sc_left, 0); + pATI->sc_top_bottom = SetWord(pATI->NewHW.sc_bottom, 1) | + 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 = + 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 = + 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 = + 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 = + 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 = + 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; + } + +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + + pATIHW->dp_pix_width |= DP_BYTE_PIX_ORDER; + +#endif /* X_BYTE_ORDER */ + + 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; + + if (pATI->Block1Base) + { + pATIHW->overlay_y_x_start = SetBits(0, OVERLAY_Y_START) | + SetBits(0, OVERLAY_X_START) | OVERLAY_LOCK_START; + pATIHW->overlay_y_x_end = SetBits(0, OVERLAY_Y_END) | + SetBits(0, OVERLAY_X_END) | OVERLAY_LOCK_END; + + pATIHW->overlay_graphics_key_clr = + (3 << ((2 * pATI->depth) / 3)) | + (2 << ((1 * pATI->depth) / 3)) | + (1 << ((0 * pATI->depth) / 3)); + pATIHW->overlay_graphics_key_msk = (1 << pATI->depth) - 1; + + pATIHW->overlay_key_cntl = + SetBits(OVERLAY_MIX_FALSE, OVERLAY_VIDEO_FN) | + SetBits(OVERLAY_MIX_EQUAL, OVERLAY_GRAPHICS_FN); + + pATIHW->overlay_scale_cntl = SCALE_EN; + + pATIHW->video_format = VIDEO_IN_VYUY422 | SCALER_IN_VYUY422; + + if (pATI->Chip >= ATI_CHIP_264GTPRO) + { + /* These values are documented voodoo */ + pATIHW->scaler_h_coeff0 = SetByte(0x20U, 1); + pATIHW->scaler_h_coeff1 = SetByte(0x0DU, 0) | + SetByte(0x20U, 1) | SetByte(0x06U, 2) | SetByte(0x0DU, 3); + pATIHW->scaler_h_coeff2 = SetByte(0x0DU, 0) | + SetByte(0x1CU, 1) | SetByte(0x0AU, 2) | SetByte(0x0DU, 3); + pATIHW->scaler_h_coeff3 = SetByte(0x0CU, 0) | + SetByte(0x1AU, 1) | SetByte(0x0EU, 2) | SetByte(0x0CU, 3); + pATIHW->scaler_h_coeff4 = SetByte(0x0CU, 0) | + SetByte(0x14U, 1) | SetByte(0x14U, 2) | SetByte(0x0CU, 3); + } + } + + /* Restore aperture enablement */ + outr(BUS_CNTL, bus_cntl); + outr(CONFIG_CNTL, config_cntl); + } +} + +/* + * 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->cur_clr0 = inr(CUR_CLR0); + pATIHW->cur_clr1 = inr(CUR_CLR1); + pATIHW->cur_offset = inr(CUR_OFFSET); + pATIHW->cur_horz_vert_posn = inr(CUR_HORZ_VERT_POSN); + pATIHW->cur_horz_vert_off = inr(CUR_HORZ_VERT_OFF); + + 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); + + pATIHW->gen_test_cntl = inr(GEN_TEST_CNTL) & ~GEN_CUR_EN; + + if (pATI->Chip >= ATI_CHIP_264VTB) + { + pATIHW->mem_cntl = inr(MEM_CNTL); + pATIHW->mpp_config = inr(MPP_CONFIG); + pATIHW->mpp_strobe_seq = inr(MPP_STROBE_SEQ); + pATIHW->tvo_cntl = inr(TVO_CNTL); + } + + /* Save draw engine state */ + if (pATI->Block0Base && (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); + + if (pATI->Block1Base) + { + /* Save overlay & scaler registers */ + pATIHW->overlay_y_x_start = inm(OVERLAY_Y_X_START); + pATIHW->overlay_y_x_end = inm(OVERLAY_Y_X_END); + + pATIHW->overlay_graphics_key_clr = inm(OVERLAY_GRAPHICS_KEY_CLR); + pATIHW->overlay_graphics_key_msk = inm(OVERLAY_GRAPHICS_KEY_MSK); + + pATIHW->overlay_key_cntl = inm(OVERLAY_KEY_CNTL); + + pATIHW->overlay_scale_inc = inm(OVERLAY_SCALE_INC); + pATIHW->overlay_scale_cntl = inm(OVERLAY_SCALE_CNTL); + + pATIHW->scaler_height_width = inm(SCALER_HEIGHT_WIDTH); + + pATIHW->scaler_test = inm(SCALER_TEST); + + pATIHW->video_format = inm(VIDEO_FORMAT); + + if (pATI->Chip < ATI_CHIP_264VTB) + { + pATIHW->buf0_offset = inm(BUF0_OFFSET); + pATIHW->buf0_pitch = inm(BUF0_PITCH); + pATIHW->buf1_offset = inm(BUF1_OFFSET); + pATIHW->buf1_pitch = inm(BUF1_PITCH); + } + else + { + pATIHW->scaler_buf0_offset = inm(SCALER_BUF0_OFFSET); + pATIHW->scaler_buf1_offset = inm(SCALER_BUF1_OFFSET); + pATIHW->scaler_buf_pitch = inm(SCALER_BUF_PITCH); + + pATIHW->overlay_exclusive_horz = inm(OVERLAY_EXCLUSIVE_HORZ); + pATIHW->overlay_exclusive_vert = inm(OVERLAY_EXCLUSIVE_VERT); + + if (pATI->Chip >= ATI_CHIP_264GTPRO) + { + pATIHW->scaler_colour_cntl = inm(SCALER_COLOUR_CNTL); + + pATIHW->scaler_h_coeff0 = inm(SCALER_H_COEFF0); + pATIHW->scaler_h_coeff1 = inm(SCALER_H_COEFF1); + pATIHW->scaler_h_coeff2 = inm(SCALER_H_COEFF2); + pATIHW->scaler_h_coeff3 = inm(SCALER_H_COEFF3); + pATIHW->scaler_h_coeff4 = inm(SCALER_H_COEFF4); + + pATIHW->scaler_buf0_offset_u = inm(SCALER_BUF0_OFFSET_U); + pATIHW->scaler_buf0_offset_v = inm(SCALER_BUF0_OFFSET_V); + pATIHW->scaler_buf1_offset_u = inm(SCALER_BUF1_OFFSET_U); + pATIHW->scaler_buf1_offset_v = inm(SCALER_BUF1_OFFSET_V); + } + } + } + + /* Restore aperture enablement */ + outr(BUS_CNTL, pATIHW->bus_cntl); + outr(CONFIG_CNTL, pATIHW->config_cntl); + } +} + +/* + * 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->OptionPanelDisplay && (pATI->LCDPanelID >= 0) +#ifdef TV_OUT + && !pATI->tvActive +#endif +) + 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_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 +) +{ + +#ifndef AVOID_CPIO + + if (pATIHW->crtc == ATI_CRTC_MACH64) + +#endif /* AVOID_CPIO */ + + { + if ((pATIHW->FeedbackDivider > 0) && + (pATI->ProgrammableClock != ATI_CLOCK_NONE)) + ATIClockSet(pATI, pATIHW); /* Programme clock */ + + if (pATI->DAC == ATI_DAC_IBMRGB514) + ATIRGB514Set(pATI, pATIHW); + + /* Load Mach64 CRTC registers */ + outr(CRTC_H_TOTAL_DISP, pATIHW->crtc_h_total_disp); + outr(CRTC_H_SYNC_STRT_WID, pATIHW->crtc_h_sync_strt_wid); + outr(CRTC_V_TOTAL_DISP, pATIHW->crtc_v_total_disp); + outr(CRTC_V_SYNC_STRT_WID, pATIHW->crtc_v_sync_strt_wid); + + outr(CRTC_OFF_PITCH, pATIHW->crtc_off_pitch); + + /* Load overscan registers */ + outr(OVR_CLR, pATIHW->ovr_clr); + outr(OVR_WID_LEFT_RIGHT, pATIHW->ovr_wid_left_right); + outr(OVR_WID_TOP_BOTTOM, pATIHW->ovr_wid_top_bottom); + + /* Load hardware cursor registers */ + outr(CUR_CLR0, pATIHW->cur_clr0); + outr(CUR_CLR1, pATIHW->cur_clr1); + outr(CUR_OFFSET, pATIHW->cur_offset); + outr(CUR_HORZ_VERT_POSN, pATIHW->cur_horz_vert_posn); + outr(CUR_HORZ_VERT_OFF, pATIHW->cur_horz_vert_off); + + /* Set pixel clock */ + outr(CLOCK_CNTL, pATIHW->clock_cntl | CLOCK_STROBE); + + outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN); + outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl); + outr(GEN_TEST_CNTL, pATIHW->gen_test_cntl | GEN_GUI_EN); + + /* Finalise CRTC setup and turn on the screen */ + outr(CRTC_GEN_CNTL, pATIHW->crtc_gen_cntl); + } + + /* Load draw engine */ + if (pATI->Block0Base) + { + /* 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); + + if (pATI->Block1Base) + { + /* Load overlay & scaler registers */ + ATIMach64WaitForFIFO(pATI, 10); + outf(OVERLAY_Y_X_START, pATIHW->overlay_y_x_start); + outf(OVERLAY_Y_X_END, pATIHW->overlay_y_x_end); + + outf(OVERLAY_GRAPHICS_KEY_CLR, pATIHW->overlay_graphics_key_clr); + outf(OVERLAY_GRAPHICS_KEY_MSK, pATIHW->overlay_graphics_key_msk); + + outf(OVERLAY_KEY_CNTL, pATIHW->overlay_key_cntl); + + outf(OVERLAY_SCALE_INC, pATIHW->overlay_scale_inc); + outf(OVERLAY_SCALE_CNTL, pATIHW->overlay_scale_cntl); + + outf(SCALER_HEIGHT_WIDTH, pATIHW->scaler_height_width); + + outf(SCALER_TEST, pATIHW->scaler_test); + + outf(VIDEO_FORMAT, pATIHW->video_format); + + if (pATI->Chip < ATI_CHIP_264VTB) + { + ATIMach64WaitForFIFO(pATI, 4); + outf(BUF0_OFFSET, pATIHW->buf0_offset); + outf(BUF0_PITCH, pATIHW->buf0_pitch); + outf(BUF1_OFFSET, pATIHW->buf1_offset); + outf(BUF1_PITCH, pATIHW->buf1_pitch); + } + else + { + ATIMach64WaitForFIFO(pATI, 5); + outf(SCALER_BUF0_OFFSET, pATIHW->scaler_buf0_offset); + outf(SCALER_BUF1_OFFSET, pATIHW->scaler_buf1_offset); + outf(SCALER_BUF_PITCH, pATIHW->scaler_buf_pitch); + + outf(OVERLAY_EXCLUSIVE_HORZ, pATIHW->overlay_exclusive_horz); + outf(OVERLAY_EXCLUSIVE_VERT, pATIHW->overlay_exclusive_vert); + + if (pATI->Chip >= ATI_CHIP_264GTPRO) + { + ATIMach64WaitForFIFO(pATI, 10); + outf(SCALER_COLOUR_CNTL, pATIHW->scaler_colour_cntl); + + outf(SCALER_H_COEFF0, pATIHW->scaler_h_coeff0); + outf(SCALER_H_COEFF1, pATIHW->scaler_h_coeff1); + outf(SCALER_H_COEFF2, pATIHW->scaler_h_coeff2); + outf(SCALER_H_COEFF3, pATIHW->scaler_h_coeff3); + outf(SCALER_H_COEFF4, pATIHW->scaler_h_coeff4); + + outf(SCALER_BUF0_OFFSET_U, pATIHW->scaler_buf0_offset_u); + outf(SCALER_BUF0_OFFSET_V, pATIHW->scaler_buf0_offset_v); + outf(SCALER_BUF1_OFFSET_U, pATIHW->scaler_buf1_offset_u); + outf(SCALER_BUF1_OFFSET_V, pATIHW->scaler_buf1_offset_v); + } + } + } + + ATIMach64WaitForIdle(pATI); + + if (pATI->OptionMMIOCache) + { + /* + * 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); + + if (pATI->Block1Base) + { + CacheRegister(OVERLAY_Y_X_START); + CacheRegister(OVERLAY_Y_X_END); + + CacheRegister(OVERLAY_GRAPHICS_KEY_CLR); + CacheRegister(OVERLAY_GRAPHICS_KEY_MSK); + + CacheRegister(OVERLAY_KEY_CNTL); + + CacheRegister(OVERLAY_SCALE_INC); + CacheRegister(OVERLAY_SCALE_CNTL); + + CacheRegister(SCALER_HEIGHT_WIDTH); + + CacheRegister(SCALER_TEST); + + CacheRegister(VIDEO_FORMAT); + + if (pATI->Chip < ATI_CHIP_264VTB) + { + CacheRegister(BUF0_OFFSET); + CacheRegister(BUF0_PITCH); + CacheRegister(BUF1_OFFSET); + CacheRegister(BUF1_PITCH); + } + else + { + CacheRegister(SCALER_BUF0_OFFSET); + CacheRegister(SCALER_BUF1_OFFSET); + CacheRegister(SCALER_BUF_PITCH); + + CacheRegister(OVERLAY_EXCLUSIVE_HORZ); + CacheRegister(OVERLAY_EXCLUSIVE_VERT); + + if (pATI->Chip >= ATI_CHIP_264GTPRO) + { + CacheRegister(SCALER_COLOUR_CNTL); + + CacheRegister(SCALER_H_COEFF0); + CacheRegister(SCALER_H_COEFF1); + CacheRegister(SCALER_H_COEFF2); + CacheRegister(SCALER_H_COEFF3); + CacheRegister(SCALER_H_COEFF4); + + CacheRegister(SCALER_BUF0_OFFSET_U); + CacheRegister(SCALER_BUF0_OFFSET_V); + CacheRegister(SCALER_BUF1_OFFSET_U); + CacheRegister(SCALER_BUF1_OFFSET_V); + } + } + } + } + } + +#ifndef AVOID_CPIO + + if (pATIHW->crtc == ATI_CRTC_MACH64) + +#endif /* AVOID_CPIO */ + + { + /* Aperture setup */ + outr(MEM_VGA_WP_SEL, pATIHW->mem_vga_wp_sel); + outr(MEM_VGA_RP_SEL, pATIHW->mem_vga_rp_sel); + + outr(DAC_CNTL, pATIHW->dac_cntl); + + outr(CONFIG_CNTL, pATIHW->config_cntl); + outr(BUS_CNTL, pATIHW->bus_cntl); + + if (pATI->Chip >= ATI_CHIP_264VTB) + { + outr(MEM_CNTL, pATIHW->mem_cntl); + outr(MPP_CONFIG, pATIHW->mpp_config); + outr(MPP_STROBE_SEQ, pATIHW->mpp_strobe_seq); + outr(TVO_CNTL, pATIHW->tvo_cntl); + } + } +} + +/* + * 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 +( + ScrnInfoPtr pScreenInfo, + 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; + } + +#ifdef XF86DRI_DEVEL + + /* XAA Sync requires the DRM lock if DRI enabled */ + ATIDRILock(pScreenInfo); + +#endif /* XF86DRI_DEVEL */ + + ATIMach64Sync(pScreenInfo); + + outr(CRTC_GEN_CNTL, crtc_gen_cntl); + + if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0)) + { + 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 = ATIMach64GetLCDReg(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; + } + + 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)) */ + { + ATIMach64PutLCDReg(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 = ATIMach64GetLCDReg(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)) */ + { + ATIMach64PutLCDReg(LCD_GEN_CNTL, lcd_gen_ctrl); + outr(LCD_INDEX, lcd_index); + } + } + } + +#ifdef XF86DRI_DEVEL + + ATIDRIUnlock(pScreenInfo); + +#endif /* XF86DRI_DEVEL */ + +} |