diff options
author | Alex Deucher <alex@botch2.(none)> | 2007-12-21 15:29:47 -0500 |
---|---|---|
committer | Alex Deucher <alex@botch2.(none)> | 2007-12-21 15:29:47 -0500 |
commit | bf14aa5f88fc3b4e69d71db5b23248b8bb2018d0 (patch) | |
tree | e65ead0dee43be5433d9a6f328dcf632317157dc | |
parent | be7f8fd338f5af8b632f16a83db41e15d00af469 (diff) |
RADEON: re-org legacy crtc/output code into separate files
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/legacy_crtc.c | 1268 | ||||
-rw-r--r-- | src/legacy_output.c | 1577 | ||||
-rw-r--r-- | src/radeon.h | 3 | ||||
-rw-r--r-- | src/radeon_crtc.c | 916 | ||||
-rw-r--r-- | src/radeon_display.c | 740 | ||||
-rw-r--r-- | src/radeon_output.c | 1252 |
7 files changed, 2951 insertions, 2808 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 3e0352bd..7b25e4b1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -116,7 +116,8 @@ radeon_drv_ladir = @moduledir@/drivers radeon_drv_la_SOURCES = \ radeon_accel.c radeon_cursor.c radeon_dga.c \ radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \ - radeon_vip.c radeon_misc.c radeon_probe.c radeon_display.c \ + radeon_vip.c radeon_misc.c radeon_probe.c \ + legacy_crtc.c legacy_output.c \ radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \ $(RADEON_ATOMBIOS_SOURCES) radeon_atombios.c radeon_atomwrapper.c \ $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c diff --git a/src/legacy_crtc.c b/src/legacy_crtc.c new file mode 100644 index 00000000..f1bf9be1 --- /dev/null +++ b/src/legacy_crtc.c @@ -0,0 +1,1268 @@ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * 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 on 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 ATI, VA LINUX SYSTEMS AND/OR + * THEIR 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdio.h> + +/* X and server generic header files */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "vgaHW.h" +#include "xf86Modes.h" + +/* Driver data structures */ +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_version.h" + +#ifdef XF86DRI +#define _XF86DRI_SERVER_ +#include "radeon_dri.h" +#include "radeon_sarea.h" +#include "sarea.h" +#endif + + +void +legacy_crtc_dpms(xf86CrtcPtr crtc, int mode) +{ + int mask; + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + mask = radeon_crtc->crtc_id ? (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_REQ_EN_B) : (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_VSYNC_DIS); + + + switch(mode) { + case DPMSModeOn: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask); + } + break; + case DPMSModeStandby: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), ~mask); + } + break; + case DPMSModeSuspend: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), ~mask); + } + break; + case DPMSModeOff: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, mask, ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, mask, ~mask); + } + break; + } + + if (mode != DPMSModeOff) + radeon_crtc_load_lut(crtc); +} + + +/* Define common registers for requested video mode */ +static void +RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) +{ + save->ovr_clr = 0; + save->ovr_wid_left_right = 0; + save->ovr_wid_top_bottom = 0; + save->ov0_scale_cntl = 0; + save->subpic_cntl = 0; + save->viph_control = 0; + save->i2c_cntl_1 = 0; + save->rbbm_soft_reset = 0; + save->cap0_trig_cntl = 0; + save->cap1_trig_cntl = 0; + save->bus_cntl = info->BusCntl; + /* + * If bursts are enabled, turn on discards + * Radeon doesn't have write bursts + */ + if (save->bus_cntl & (RADEON_BUS_READ_BURST)) + save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; +} + +static void +RADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save) +{ + save->surface_cntl = 0; + +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* We must set both apertures as they can be both used to map the entire + * video memory. -BenH. + */ + switch (crtc->scrn->bitsPerPixel) { + case 16: + save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; + save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; + break; + + case 32: + save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; + save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; + break; + } +#endif + +} + + +static Bool +RADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save, + int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int Base; +#ifdef XF86DRI + RADEONSAREAPrivPtr pSAREAPriv; + XF86DRISAREAPtr pSAREA; +#endif + + save->crtc_offset = pScrn->fbOffset; +#ifdef XF86DRI + if (info->allowPageFlip) + save->crtc_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL; + else +#endif + save->crtc_offset_cntl = 0; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) + save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; + } + else { + if (IS_R300_VARIANT) + save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } + + Base = pScrn->fbOffset; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) { + /* On r300/r400 when tiling is enabled crtc_offset is set to the address of + * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc + * Makes tiling MUCH easier. + */ + save->crtc_tile_x0_y0 = x | (y << 16); + Base &= ~0x7ff; + } else { + /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the + drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes + flickering when scrolling vertically in a virtual screen, possibly because crtc will + pick up the new offset value at the end of each scanline, but the new offset_cntl value + only after a vsync. We'd probably need to wait (in drm) for vsync and only then update + OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ + /*save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL) & ~0xf;*/ +#if 0 + /* try to get rid of flickering when scrolling at least for 2d */ +#ifdef XF86DRI + if (!info->have3DWindows) +#endif + save->crtc_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; +#endif + + int byteshift = info->CurrentLayout.bitsPerPixel >> 4; + /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ + int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; + Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + save->crtc_offset_cntl = save->crtc_offset_cntl | (y % 16); + } + } + else { + int offset = y * info->CurrentLayout.displayWidth + x; + switch (info->CurrentLayout.pixel_code) { + case 15: + case 16: offset *= 2; break; + case 24: offset *= 3; break; + case 32: offset *= 4; break; + } + Base += offset; + } + + if (crtc->rotatedData != NULL) { + Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; + } + + Base &= ~7; /* 3 lower bits are always 0 */ + + +#ifdef XF86DRI + if (info->directRenderingInited) { + /* note cannot use pScrn->pScreen since this is unitialized when called from + RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ + /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for + *** pageflipping! + ***/ + pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]); + /* can't get at sarea in a semi-sane way? */ + pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); + + pSAREA->frame.x = (Base / info->CurrentLayout.pixel_bytes) + % info->CurrentLayout.displayWidth; + pSAREA->frame.y = (Base / info->CurrentLayout.pixel_bytes) + / info->CurrentLayout.displayWidth; + pSAREA->frame.width = pScrn->frameX1 - x + 1; + pSAREA->frame.height = pScrn->frameY1 - y + 1; + + if (pSAREAPriv->pfCurrentPage == 1) { + Base += info->backOffset - info->frontOffset; + } + } +#endif + save->crtc_offset = Base; + + return TRUE; + +} + +/* Define CRTC registers for requested video mode */ +static Bool +RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save, + DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + + switch (info->CurrentLayout.pixel_code) { + case 4: format = 1; break; + case 8: format = 2; break; + case 15: format = 3; break; /* 555 */ + case 16: format = 4; break; /* 565 */ + case 24: format = 5; break; /* RGB */ + case 32: format = 6; break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", + info->CurrentLayout.bitsPerPixel); + return FALSE; + } + + /*save->bios_4_scratch = info->SavedReg->bios_4_scratch;*/ + save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN + | RADEON_CRTC_EN + | (format << 8) + | ((mode->Flags & V_DBLSCAN) + ? RADEON_CRTC_DBL_SCAN_EN + : 0) + | ((mode->Flags & V_CSYNC) + ? RADEON_CRTC_CSYNC_EN + : 0) + | ((mode->Flags & V_INTERLACE) + ? RADEON_CRTC_INTERLACE_EN + : 0)); + + save->crtc_ext_cntl |= (RADEON_XCRT_CNT_EN| + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS | + RADEON_CRTC_DISPLAY_DIS); + + save->disp_merge_cntl = info->SavedReg->disp_merge_cntl; + save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; + + save->crtc_more_cntl = 0; + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) { + /* This is to workaround the asic bug for RMX, some versions + of BIOS dosen't have this register initialized correctly. + */ + save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; + } + + save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) + << 16)); + + hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; + if (!hsync_wid) hsync_wid = 1; + hsync_start = mode->CrtcHSyncStart - 8; + + save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->Flags & V_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + /* This works for double scan mode. */ + save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay - 1) << 16)); + + vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; + if (!vsync_wid) vsync_wid = 1; + + save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->Flags & V_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0)); + + save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / + (pScrn->bitsPerPixel * 8)); + save->crtc_pitch |= save->crtc_pitch << 16; + + save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; + save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; + save->fp_crtc_h_total_disp = save->crtc_h_total_disp; + save->fp_crtc_v_total_disp = save->crtc_v_total_disp; + + if (info->IsDellServer) { + save->dac2_cntl = info->SavedReg->dac2_cntl; + save->tv_dac_cntl = info->SavedReg->tv_dac_cntl; + save->crtc2_gen_cntl = info->SavedReg->crtc2_gen_cntl; + save->disp_hw_debug = info->SavedReg->disp_hw_debug; + + save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; + save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; + + /* For CRT on DAC2, don't turn it on if BIOS didn't + enable it, even it's detected. + */ + save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + save->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16)); + save->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16)); + } + + return TRUE; +} + + +static Bool +RADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save, + int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int Base; +#ifdef XF86DRI + RADEONSAREAPrivPtr pSAREAPriv; + XF86DRISAREAPtr pSAREA; +#endif + + /* It seems all fancy options apart from pflip can be safely disabled + */ + save->crtc2_offset = pScrn->fbOffset; +#ifdef XF86DRI + if (info->allowPageFlip) + save->crtc2_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL; + else +#endif + save->crtc2_offset_cntl = 0; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) + save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN; + } + else { + if (IS_R300_VARIANT) + save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } + + Base = pScrn->fbOffset; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) { + /* On r300/r400 when tiling is enabled crtc_offset is set to the address of + * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc + * Makes tiling MUCH easier. + */ + save->crtc2_tile_x0_y0 = x | (y << 16); + Base &= ~0x7ff; + } else { + /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the + drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes + flickering when scrolling vertically in a virtual screen, possibly because crtc will + pick up the new offset value at the end of each scanline, but the new offset_cntl value + only after a vsync. We'd probably need to wait (in drm) for vsync and only then update + OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ + /*save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & ~0xf;*/ +#if 0 + /* try to get rid of flickering when scrolling at least for 2d */ +#ifdef XF86DRI + if (!info->have3DWindows) +#endif + save->crtc2_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; +#endif + + int byteshift = info->CurrentLayout.bitsPerPixel >> 4; + /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ + int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; + Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + save->crtc2_offset_cntl = save->crtc_offset_cntl | (y % 16); + } + } + else { + int offset = y * info->CurrentLayout.displayWidth + x; + switch (info->CurrentLayout.pixel_code) { + case 15: + case 16: offset *= 2; break; + case 24: offset *= 3; break; + case 32: offset *= 4; break; + } + Base += offset; + } + + if (crtc->rotatedData != NULL) { + Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; + } + + Base &= ~7; /* 3 lower bits are always 0 */ + +#ifdef XF86DRI + if (info->directRenderingInited) { + /* note cannot use pScrn->pScreen since this is unitialized when called from + RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ + /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for + *** pageflipping! + ***/ + pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]); + /* can't get at sarea in a semi-sane way? */ + pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); + + pSAREAPriv->crtc2_base = Base; + + if (pSAREAPriv->pfCurrentPage == 1) { + Base += info->backOffset - info->frontOffset; + } + } +#endif + save->crtc2_offset = Base; + + return TRUE; +} + + +/* Define CRTC2 registers for requested video mode */ +static Bool +RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save, + DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + + switch (info->CurrentLayout.pixel_code) { + case 4: format = 1; break; + case 8: format = 2; break; + case 15: format = 3; break; /* 555 */ + case 16: format = 4; break; /* 565 */ + case 24: format = 5; break; /* RGB */ + case 32: format = 6; break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", + info->CurrentLayout.bitsPerPixel); + return FALSE; + } + + save->crtc2_h_total_disp = + ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; + if (!hsync_wid) hsync_wid = 1; + hsync_start = mode->CrtcHSyncStart - 8; + + save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) + | ((hsync_wid & 0x3f) << 16) + | ((mode->Flags & V_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + /* This works for double scan mode. */ + save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay - 1) << 16)); + + vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; + if (!vsync_wid) vsync_wid = 1; + + save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) + | ((vsync_wid & 0x1f) << 16) + | ((mode->Flags & V_NVSYNC) + ? RADEON_CRTC2_V_SYNC_POL + : 0)); + + save->crtc2_pitch = ((pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); + save->crtc2_pitch |= save->crtc2_pitch << 16; + + /* check to see if TV DAC is enabled for another crtc and keep it enabled */ + if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON) + save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON; + else + save->crtc2_gen_cntl = 0; + + save->crtc2_gen_cntl |= (RADEON_CRTC2_EN + | (format << 8) + | RADEON_CRTC2_VSYNC_DIS + | RADEON_CRTC2_HSYNC_DIS + | RADEON_CRTC2_DISP_DIS + | ((mode->Flags & V_DBLSCAN) + ? RADEON_CRTC2_DBL_SCAN_EN + : 0) + | ((mode->Flags & V_CSYNC) + ? RADEON_CRTC2_CSYNC_EN + : 0) + | ((mode->Flags & V_INTERLACE) + ? RADEON_CRTC2_INTERLACE_EN + : 0)); + + save->disp2_merge_cntl = info->SavedReg->disp2_merge_cntl; + save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); + + save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; + save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid; + + if (info->ChipFamily == CHIP_FAMILY_RS400) { + save->rs480_unk_e30 = 0x105DC1CC; /* because I'm worth it */ + save->rs480_unk_e34 = 0x2749D000; /* AMD really should */ + save->rs480_unk_e38 = 0x29ca71dc; /* release docs */ + save->rs480_unk_e3c = 0x28FBC3AC; /* this is so a trade secret */ + } + + return TRUE; +} + + +/* Define PLL registers for requested video mode */ +static void +RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, + RADEONPLLPtr pll, DisplayModePtr mode, + int flags) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD32 feedback_div = 0; + CARD32 reference_div = 0; + CARD32 post_divider = 0; + CARD32 freq = 0; + + struct { + int divider; + int bitvalue; + } *post_div, post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + * Reference Manual (Technical Reference + * Manual P/N RRG-G04100-C Rev. 0.04), page + * 3-17 (PLL_DIV_[3:0]). + */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + { 16, 5 }, /* VCLK_SRC/16 */ + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + + + if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { + save->ppll_ref_div = info->RefDivider; + save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); + save->htotal_cntl = 0; + return; + } + + RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags); + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + if (post_div->divider == post_divider) + break; + } + + if (!post_div->divider) { + save->pll_output_freq = freq; + post_div = &post_divs[0]; + } + + save->dot_clock_freq = freq; + save->feedback_div = feedback_div; + save->reference_div = reference_div; + save->post_div = post_divider; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n", + (unsigned)save->dot_clock_freq, + (unsigned)save->pll_output_freq, + save->feedback_div, + save->reference_div, + save->post_div); + + save->ppll_ref_div = save->reference_div; + +#if defined(__powerpc__) + /* apparently programming this otherwise causes a hang??? */ + if (info->MacModel == RADEON_MAC_IBOOK) + save->ppll_div_3 = 0x000600ad; + else +#endif + save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); + + save->htotal_cntl = mode->HTotal & 0x7; + + save->vclk_ecp_cntl = (info->SavedReg->vclk_ecp_cntl & + ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; +} + +/* Define PLL2 registers for requested video mode */ +static void +RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, + RADEONPLLPtr pll, DisplayModePtr mode, + int flags) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD32 feedback_div = 0; + CARD32 reference_div = 0; + CARD32 post_divider = 0; + CARD32 freq = 0; + + struct { + int divider; + int bitvalue; + } *post_div, post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + * Reference Manual (Technical Reference + * Manual P/N RRG-G04100-C Rev. 0.04), page + * 3-17 (PLL_DIV_[3:0]). + */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + + if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { + save->p2pll_ref_div = info->RefDivider; + save->p2pll_div_0 = info->FeedbackDivider | (info->PostDivider << 16); + save->htotal_cntl2 = 0; + return; + } + + RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags); + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + if (post_div->divider == post_divider) + break; + } + + if (!post_div->divider) { + save->pll_output_freq_2 = freq; + post_div = &post_divs[0]; + } + + save->dot_clock_freq_2 = freq; + save->feedback_div_2 = feedback_div; + save->reference_div_2 = reference_div; + save->post_div_2 = post_divider; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n", + (unsigned)save->dot_clock_freq_2, + (unsigned)save->pll_output_freq_2, + save->feedback_div_2, + save->reference_div_2, + save->post_div_2); + + save->p2pll_ref_div = save->reference_div_2; + + save->p2pll_div_0 = (save->feedback_div_2 | + (post_div->bitvalue << 16)); + + save->htotal_cntl2 = mode->HTotal & 0x7; + + save->pixclks_cntl = ((info->SavedReg->pixclks_cntl & + ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | + RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); +} + +static void +RADEONInitBIOSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + /* tell the bios not to muck with the hardware on events */ + save->bios_4_scratch = 0x4; /* 0x4 needed for backlight */ + save->bios_5_scratch = (info->SavedReg->bios_5_scratch & 0xff) | 0xff00; /* bits 0-3 keep backlight level */ + save->bios_6_scratch = info->SavedReg->bios_6_scratch | 0x40000000; + +} + +static void +radeon_update_tv_routing(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + /* pixclks_cntl controls tv clock routing */ + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl); +} + +/* Calculate display buffer watermark to prevent buffer underflow */ +static void +RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2, DisplayModePtr mode1, DisplayModePtr mode2) +{ + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + CARD32 temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0; + float mem_tcas; + int k1, c; + CARD32 MemTrcdExtMemCntl[4] = {1, 2, 3, 4}; + CARD32 MemTrpExtMemCntl[4] = {1, 2, 3, 4}; + CARD32 MemTrasExtMemCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + CARD32 MemTrcdMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + CARD32 MemTrpMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + CARD32 MemTrasMemTimingCntl[16] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + float MemTcas[8] = {0, 1, 2, 3, 0, 1.5, 2.5, 0}; + float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7}; + float MemTrbs[8] = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5}; + + float mem_bw, peak_disp_bw; + float min_mem_eff = 0.8; + float sclk_eff, sclk_delay; + float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk; + float disp_latency, disp_latency_overhead, disp_drain_rate, disp_drain_rate2; + float pix_clk, pix_clk2; /* in MHz */ + int cur_size = 16; /* in octawords */ + int critical_point, critical_point2; + int stop_req, max_stop_req; + float read_return_rate, time_disp1_drop_priority; + + /* + * Set display0/1 priority up on r3/4xx in the memory controller for + * high res modes if the user specifies HIGH for displaypriority + * option. + */ + if ((info->DispPriority == 2) && IS_R300_VARIANT) { + CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); + if (pRADEONEnt->pCrtc[1]->enabled) { + mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ + } else { + mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ + } + OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); + } + + + /* R420 and RV410 family not supported yet */ + if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; + + /* + * Determine if there is enough bandwidth for current display mode + */ + mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1); + + pix_clk = mode1->Clock/1000.0; + if (mode2) + pix_clk2 = mode2->Clock/1000.0; + else + pix_clk2 = 0; + + peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes); + if (pixel_bytes2) + peak_disp_bw += (pix_clk2 * pixel_bytes2); + + if (peak_disp_bw >= mem_bw * min_mem_eff) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "You may not have enough display bandwidth for current mode\n" + "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); + } + + /* CRTC1 + Set GRPH_BUFFER_CNTL register using h/w defined optimal values. + GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] + */ + stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16; + + /* setup Max GRPH_STOP_REQ default value */ + if (IS_RV100_VARIANT) + max_stop_req = 0x5c; + else + max_stop_req = 0x7c; + if (stop_req > max_stop_req) + stop_req = max_stop_req; + + /* Get values from the EXT_MEM_CNTL register...converting its contents. */ + temp = INREG(RADEON_MEM_TIMING_CNTL); + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + mem_trcd = MemTrcdExtMemCntl[(temp & 0x0c) >> 2]; + mem_trp = MemTrpExtMemCntl[ (temp & 0x03) >> 0]; + mem_tras = MemTrasExtMemCntl[(temp & 0x70) >> 4]; + } else { /* RV200 and later */ + mem_trcd = MemTrcdMemTimingCntl[(temp & 0x07) >> 0]; + mem_trp = MemTrpMemTimingCntl[ (temp & 0x700) >> 8]; + mem_tras = MemTrasMemTimingCntl[(temp & 0xf000) >> 12]; + } + + /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ + temp = INREG(RADEON_MEM_SDRAM_MODE_REG); + data = (temp & (7<<20)) >> 20; + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + mem_tcas = MemTcas [data]; + } else { + mem_tcas = MemTcas2 [data]; + } + + if (IS_R300_VARIANT) { + + /* on the R300, Tcas is included in Trbs. + */ + temp = INREG(RADEON_MEM_CNTL); + data = (R300_MEM_NUM_CHANNELS_MASK & temp); + if (data == 1) { + if (R300_MEM_USE_CD_CH_ONLY & temp) { + temp = INREG(R300_MC_IND_INDEX); + temp &= ~R300_MC_IND_ADDR_MASK; + temp |= R300_MC_READ_CNTL_CD_mcind; + OUTREG(R300_MC_IND_INDEX, temp); + temp = INREG(R300_MC_IND_DATA); + data = (R300_MEM_RBS_POSITION_C_MASK & temp); + } else { + temp = INREG(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + } else { + temp = INREG(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + + mem_trbs = MemTrbs[data]; + mem_tcas += mem_trbs; + } + + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + /* DDR64 SCLK_EFF = SCLK for analysis */ + sclk_eff = info->sclk; + } else { +#ifdef XF86DRI + if (info->directRenderingEnabled) + sclk_eff = info->sclk - (info->agpMode * 50.0 / 3.0); + else +#endif + sclk_eff = info->sclk; + } + + /* Find the memory controller latency for the display client. + */ + if (IS_R300_VARIANT) { + /*not enough for R350 ???*/ + /* + if (!mode2) sclk_delay = 150; + else { + if (info->RamWidth == 256) sclk_delay = 87; + else sclk_delay = 97; + } + */ + sclk_delay = 250; + } else { + if ((info->ChipFamily == CHIP_FAMILY_RV100) || + info->IsIGP) { + if (info->IsDDR) sclk_delay = 41; + else sclk_delay = 33; + } else { + if (info->RamWidth == 128) sclk_delay = 57; + else sclk_delay = 41; + } + } + + mc_latency_sclk = sclk_delay / sclk_eff; + + if (info->IsDDR) { + if (info->RamWidth == 32) { + k1 = 40; + c = 3; + } else { + k1 = 20; + c = 1; + } + } else { + k1 = 40; + c = 3; + } + mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) / + info->mclk) + (4.0 / sclk_eff); + + /* + HW cursor time assuming worst case of full size colour cursor. + */ + cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk; + cur_latency_sclk = cur_size / sclk_eff; + + /* + Find the total latency for the display data. + */ + disp_latency_overhead = 8.0 / info->sclk; + mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk; + mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk; + disp_latency = MAX(mc_latency_mclk, mc_latency_sclk); + + /* + Find the drain rate of the display buffer. + */ + disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes); + if (pixel_bytes2) + disp_drain_rate2 = pix_clk2 / (16.0/pixel_bytes2); + else + disp_drain_rate2 = 0; + + /* + Find the critical point of the display buffer. + */ + critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5); + + /* ???? */ + /* + temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT; + if (critical_point < temp) critical_point = temp; + */ + if (info->DispPriority == 2) { + critical_point = 0; + } + + /* + The critical point should never be above max_stop_req-4. Setting + GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. + */ + if (max_stop_req - critical_point < 4) critical_point = 0; + + if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) { + /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ + critical_point = 0x10; + } + + temp = info->SavedReg->grph_buffer_cntl; + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((info->ChipFamily == CHIP_FAMILY_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + /* + Write the result into the register. + */ + OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "GRPH_BUFFER_CNTL from %x to %x\n", + (unsigned int)info->SavedReg->grph_buffer_cntl, + (unsigned int)INREG(RADEON_GRPH_BUFFER_CNTL)); + + if (mode2) { + stop_req = mode2->HDisplay * pixel_bytes2 / 16; + + if (stop_req > max_stop_req) stop_req = max_stop_req; + + temp = info->SavedReg->grph2_buffer_cntl; + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((info->ChipFamily == CHIP_FAMILY_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) + critical_point2 = 0; + else { + read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128)); + time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate); + + critical_point2 = (CARD32)((disp_latency + time_disp1_drop_priority + + disp_latency) * disp_drain_rate2 + 0.5); + + if (info->DispPriority == 2) { + critical_point2 = 0; + } + + if (max_stop_req - critical_point2 < 4) critical_point2 = 0; + + } + + if (critical_point2 == 0 && info->ChipFamily == CHIP_FAMILY_R300) { + /* some R300 cards have problem with this set to 0 */ + critical_point2 = 0x10; + } + + OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "GRPH2_BUFFER_CNTL from %x to %x\n", + (unsigned int)info->SavedReg->grph2_buffer_cntl, + (unsigned int)INREG(RADEON_GRPH2_BUFFER_CNTL)); + } +} + +void +RADEONInitDispBandwidth(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + DisplayModePtr mode1, mode2; + int pixel_bytes2 = 0; + + if (info->IsPrimary || info->IsSecondary) + mode1 = &xf86_config->crtc[0]->mode; + else + mode1 = info->CurrentLayout.mode; + mode2 = NULL; + pixel_bytes2 = info->CurrentLayout.pixel_bytes; + + if (xf86_config->num_crtc == 2) { + pixel_bytes2 = 0; + mode2 = NULL; + + if (xf86_config->crtc[1]->enabled && xf86_config->crtc[0]->enabled) { + pixel_bytes2 = info->CurrentLayout.pixel_bytes; + mode1 = &xf86_config->crtc[0]->mode; + mode2 = &xf86_config->crtc[1]->mode; + } else if (xf86_config->crtc[0]->enabled) { + mode1 = &xf86_config->crtc[0]->mode; + } else if (xf86_config->crtc[1]->enabled) { + mode1 = &xf86_config->crtc[1]->mode; + } else + return; + } else { + if (xf86_config->crtc[0]->enabled) + mode1 = &xf86_config->crtc[0]->mode; + else + return; + } + + RADEONInitDispBandwidth2(pScrn, info, pixel_bytes2, mode1, mode2); +} + +void +legacy_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode, int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + Bool tilingOld = info->tilingEnabled; + int i = 0; + double dot_clock = 0; + int pll_flags = RADEON_PLL_LEGACY; + Bool update_tv_routing = FALSE; + + + if (info->allowColorTiling) { + info->tilingEnabled = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; +#ifdef XF86DRI + if (info->directRenderingEnabled && (info->tilingEnabled != tilingOld)) { + RADEONSAREAPrivPtr pSAREAPriv; + if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_SWITCH_TILING, (info->tilingEnabled ? 1 : 0)) < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed changing tiling status\n"); + /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ + pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]); + info->tilingEnabled = pSAREAPriv->tiling_enabled ? TRUE : FALSE; + } +#endif + } + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (output->crtc == crtc) { + if (radeon_output->MonType != MT_CRT) + pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; + if (radeon_output->MonType == MT_LCD) + pll_flags |= (RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV); + } + } + + if (info->IsMobility) + RADEONInitBIOSRegisters(pScrn, info->ModeReg); + + ErrorF("init memmap\n"); + RADEONInitMemMapRegisters(pScrn, info->ModeReg, info); + ErrorF("init common\n"); + RADEONInitCommonRegisters(info->ModeReg, info); + + RADEONInitSurfaceCntl(crtc, info->ModeReg); + + switch (radeon_crtc->crtc_id) { + case 0: + ErrorF("init crtc1\n"); + RADEONInitCrtcRegisters(crtc, info->ModeReg, adjusted_mode); + RADEONInitCrtcBase(crtc, info->ModeReg, x, y); + dot_clock = adjusted_mode->Clock / 1000.0; + if (dot_clock) { + ErrorF("init pll1\n"); + RADEONInitPLLRegisters(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags); + } else { + info->ModeReg->ppll_ref_div = info->SavedReg->ppll_ref_div; + info->ModeReg->ppll_div_3 = info->SavedReg->ppll_div_3; + info->ModeReg->htotal_cntl = info->SavedReg->htotal_cntl; + } + break; + case 1: + ErrorF("init crtc2\n"); + RADEONInitCrtc2Registers(crtc, info->ModeReg, adjusted_mode); + RADEONInitCrtc2Base(crtc, info->ModeReg, x, y); + dot_clock = adjusted_mode->Clock / 1000.0; + if (dot_clock) { + ErrorF("init pll2\n"); + RADEONInitPLL2Registers(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags); + } + break; + } + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (output->crtc == crtc) { + if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) { + switch (radeon_crtc->crtc_id) { + case 0: + RADEONAdjustCrtcRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); + RADEONAdjustPLLRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); + update_tv_routing = TRUE; + break; + case 1: + RADEONAdjustCrtc2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); + RADEONAdjustPLL2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); + break; + } + } + } + } + + if (info->IsMobility) + RADEONRestoreBIOSRegisters(pScrn, info->ModeReg); + + ErrorF("restore memmap\n"); + RADEONRestoreMemMapRegisters(pScrn, info->ModeReg); + ErrorF("restore common\n"); + RADEONRestoreCommonRegisters(pScrn, info->ModeReg); + + switch (radeon_crtc->crtc_id) { + case 0: + ErrorF("restore crtc1\n"); + RADEONRestoreCrtcRegisters(pScrn, info->ModeReg); + ErrorF("restore pll1\n"); + RADEONRestorePLLRegisters(pScrn, info->ModeReg); + break; + case 1: + ErrorF("restore crtc2\n"); + RADEONRestoreCrtc2Registers(pScrn, info->ModeReg); + ErrorF("restore pll2\n"); + RADEONRestorePLL2Registers(pScrn, info->ModeReg); + break; + } + + /* pixclks_cntl handles tv-out clock routing */ + if (update_tv_routing) + radeon_update_tv_routing(pScrn, info->ModeReg); + + if (info->DispPriority) + RADEONInitDispBandwidth(pScrn); + + if (info->tilingEnabled != tilingOld) { + /* need to redraw front buffer, I guess this can be considered a hack ? */ + /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ + if (pScrn->pScreen) + xf86EnableDisableFBAccess(pScrn->scrnIndex, FALSE); + RADEONChangeSurfaces(pScrn); + if (pScrn->pScreen) + xf86EnableDisableFBAccess(pScrn->scrnIndex, TRUE); + /* xf86SetRootClip would do, but can't access that here */ + } + + /* reset ecp_div for Xv */ + info->ecp_div = -1; + +} + diff --git a/src/legacy_output.c b/src/legacy_output.c new file mode 100644 index 00000000..6f55ae2d --- /dev/null +++ b/src/legacy_output.c @@ -0,0 +1,1577 @@ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * 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 on 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 ATI, VA LINUX SYSTEMS AND/OR + * THEIR 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdio.h> + +/* X and server generic header files */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "vgaHW.h" +#include "xf86Modes.h" + +/* Driver data structures */ +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_version.h" +#include "radeon_tv.h" +#include "radeon_atombios.h" + +static RADEONMonitorType radeon_detect_tv(ScrnInfoPtr pScrn); +static RADEONMonitorType radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color); +static RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color); +static RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn); + + +Bool +RADEONDVOReadByte(I2CDevPtr dvo, int addr, CARD8 *ch) +{ + if (!xf86I2CReadByte(dvo, addr, ch)) { + xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR, + "Unable to read from %s Slave %d.\n", + dvo->pI2CBus->BusName, dvo->SlaveAddr); + return FALSE; + } + return TRUE; +} + +Bool +RADEONDVOWriteByte(I2CDevPtr dvo, int addr, CARD8 ch) +{ + if (!xf86I2CWriteByte(dvo, addr, ch)) { + xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR, + "Unable to write to %s Slave %d.\n", + dvo->pI2CBus->BusName, dvo->SlaveAddr); + return FALSE; + } + return TRUE; +} + +I2CDevPtr +RADEONDVODeviceInit(I2CBusPtr b, I2CSlaveAddr addr) +{ + I2CDevPtr dvo; + + dvo = xcalloc(1, sizeof(I2CDevRec)); + if (dvo == NULL) + return NULL; + + dvo->DevName = "RADEON DVO Controller"; + dvo->SlaveAddr = addr; + dvo->pI2CBus = b; + dvo->StartTimeout = b->StartTimeout; + dvo->BitTimeout = b->BitTimeout; + dvo->AcknTimeout = b->AcknTimeout; + dvo->ByteTimeout = b->ByteTimeout; + + if (xf86I2CDevInit(dvo)) { + return dvo; + } + + xfree(dvo); + return NULL; +} + +static void +RADEONRestoreDVOChip(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (!radeon_output->DVOChip) + return; + + OUTREG(radeon_output->dvo_i2c_reg, INREG(radeon_output->dvo_i2c_reg) & + (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); + + if (!RADEONInitExtTMDSInfoFromBIOS(output)) { + if (radeon_output->DVOChip) { + switch(info->ext_tmds_chip) { + case RADEON_SIL_164: + RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x30); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x09, 0x00); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x0a, 0x90); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x0c, 0x89); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x3b); + break; +#if 0 + /* needs work see bug 10418 */ + case RADEON_SIL_1178: + RADEONDVOWriteByte(radeon_output->DVOChip, 0x0f, 0x44); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x0f, 0x4c); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x0e, 0x01); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x0a, 0x80); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x09, 0x30); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x0c, 0xc9); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x0d, 0x70); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x32); + RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x33); + break; +#endif + default: + break; + } + } + } +} + +#if 0 +static RADEONMonitorType +RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int bConnected = 0; + + /* the monitor either wasn't connected or it is a non-DDC CRT. + * try to probe it + */ + if(IsCrtDac) { + unsigned long ulOrigVCLK_ECP_CNTL; + unsigned long ulOrigDAC_CNTL; + unsigned long ulOrigDAC_MACRO_CNTL; + unsigned long ulOrigDAC_EXT_CNTL; + unsigned long ulOrigCRTC_EXT_CNTL; + unsigned long ulData; + unsigned long ulMask; + + ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + + ulData = ulOrigVCLK_ECP_CNTL; + ulData &= ~(RADEON_PIXCLK_ALWAYS_ONb + | RADEON_PIXCLK_DAC_ALWAYS_ONb); + ulMask = ~(RADEON_PIXCLK_ALWAYS_ONb + |RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); + + ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL); + ulData = ulOrigCRTC_EXT_CNTL; + ulData |= RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, ulData); + + ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); + ulData = ulOrigDAC_EXT_CNTL; + ulData &= ~RADEON_DAC_FORCE_DATA_MASK; + ulData |= (RADEON_DAC_FORCE_BLANK_OFF_EN + |RADEON_DAC_FORCE_DATA_EN + |RADEON_DAC_FORCE_DATA_SEL_MASK); + if ((info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280)) + ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); + + OUTREG(RADEON_DAC_EXT_CNTL, ulData); + + /* turn on power so testing can go through */ + ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); + ulOrigDAC_CNTL &= ~RADEON_DAC_PDWN; + OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL); + + ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); + ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); + + /* Enable comparators and set DAC range to PS2 (VGA) output level */ + ulData = ulOrigDAC_CNTL; + ulData |= RADEON_DAC_CMP_EN; + ulData &= ~RADEON_DAC_RANGE_CNTL_MASK; + ulData |= 0x2; + OUTREG(RADEON_DAC_CNTL, ulData); + + /* Settle down */ + usleep(10000); + + /* Read comparators */ + ulData = INREG(RADEON_DAC_CNTL); + bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; + + /* Restore things */ + ulData = ulOrigVCLK_ECP_CNTL; + ulMask = 0xFFFFFFFFL; + OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); + + OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); + OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); + OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); + + if (!bConnected) { + /* Power DAC down if CRT is not connected */ + ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); + ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); + + ulData = INREG(RADEON_DAC_CNTL); + ulData |= RADEON_DAC_PDWN; + OUTREG(RADEON_DAC_CNTL, ulData); + } + } else { /* TV DAC */ + + /* This doesn't seem to work reliably (maybe worse on some OEM cards), + for now we always return false. If one wants to connected a + non-DDC monitor on the DVI port when CRT port is also connected, + he will need to explicitly tell the driver in the config file + with Option MonitorLayout. + */ + bConnected = FALSE; + +#if 0 + if (info->ChipFamily == CHIP_FAMILY_R200) { + unsigned long ulOrigGPIO_MONID; + unsigned long ulOrigFP2_GEN_CNTL; + unsigned long ulOrigDISP_OUTPUT_CNTL; + unsigned long ulOrigCRTC2_GEN_CNTL; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_A; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_B; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_C; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_D; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_E; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_F; + unsigned long ulOrigCRTC2_H_TOTAL_DISP; + unsigned long ulOrigCRTC2_V_TOTAL_DISP; + unsigned long ulOrigCRTC2_H_SYNC_STRT_WID; + unsigned long ulOrigCRTC2_V_SYNC_STRT_WID; + unsigned long ulData, i; + + ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID); + ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL); + ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); + ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); + ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); + ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); + ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); + ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); + ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); + ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); + + ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP); + ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP); + ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); + ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); + + ulData = INREG(RADEON_GPIO_MONID); + ulData &= ~RADEON_GPIO_A_0; + OUTREG(RADEON_GPIO_MONID, ulData); + + OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c); + + OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012); + + OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) { + ulData = INREG(RADEON_GPIO_MONID); + bConnected = (ulData & RADEON_GPIO_Y_0)?1:0; + if (!bConnected) break; + + usleep(1000); + } + + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID); + OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL); + OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); + OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); + OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); + } else { + unsigned long ulOrigPIXCLKSDATA; + unsigned long ulOrigTV_MASTER_CNTL; + unsigned long ulOrigTV_DAC_CNTL; + unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; + unsigned long ulOrigDAC_CNTL2; + unsigned long ulData; + unsigned long ulMask; + + ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + + ulData = ulOrigPIXCLKSDATA; + ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); + + ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); + ulData = ulOrigTV_MASTER_CNTL; + ulData &= ~RADEON_TVCLK_ALWAYS_ONb; + OUTREG(RADEON_TV_MASTER_CNTL, ulData); + + ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); + ulData = ulOrigDAC_CNTL2; + ulData &= ~RADEON_DAC2_DAC2_CLK_SEL; + OUTREG(RADEON_DAC_CNTL2, ulData); + + ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); + + ulData = 0x00880213; + OUTREG(RADEON_TV_DAC_CNTL, ulData); + + ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); + + ulData = (RADEON_Y_RED_EN + | RADEON_C_GRN_EN + | RADEON_CMP_BLU_EN + | RADEON_RED_MX_FORCE_DAC_DATA + | RADEON_GRN_MX_FORCE_DAC_DATA + | RADEON_BLU_MX_FORCE_DAC_DATA); + if (IS_R300_VARIANT) + ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT; + else + ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT; + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData); + + usleep(10000); + + ulData = INREG(RADEON_TV_DAC_CNTL); + bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; + + ulData = ulOrigPIXCLKSDATA; + ulMask = 0xFFFFFFFFL; + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); + + OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); + OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); + OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); + } +#endif + return MT_UNKNOWN; + } + + return(bConnected ? MT_CRT : MT_NONE); +} +#endif + +RADEONMonitorType +legacy_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONMonitorType found = MT_NONE; + + if (OUTPUT_IS_TV) { + if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) { + if (radeon_output->type == OUTPUT_STV) + radeon_output->MonType = MT_STV; + else + radeon_output->MonType = MT_CTV; + } else { + if (info->InternalTVOut) { + if (radeon_output->load_detection) + radeon_output->MonType = radeon_detect_tv(pScrn); + else + radeon_output->MonType = MT_NONE; + } + } + } else { + if (radeon_output->DACType == DAC_PRIMARY) { + if (radeon_output->load_detection) + found = radeon_detect_primary_dac(pScrn, TRUE); + } else if (radeon_output->DACType == DAC_TVDAC) { + if (radeon_output->load_detection) { + if (info->ChipFamily == CHIP_FAMILY_R200) + found = radeon_detect_ext_dac(pScrn); + else + found = radeon_detect_tv_dac(pScrn, TRUE); + } else + found = MT_NONE; + } + } + + return found; +} + +/* + * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant). + * + */ +static void +RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (IsPrimaryDAC) { + CARD32 dac_cntl; + CARD32 dac_macro_cntl = 0; + dac_cntl = INREG(RADEON_DAC_CNTL); + dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); + if (IsOn) { + dac_cntl &= ~RADEON_DAC_PDWN; + dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + } else { + dac_cntl |= RADEON_DAC_PDWN; + dac_macro_cntl |= (RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + } + OUTREG(RADEON_DAC_CNTL, dac_cntl); + OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); + } else { + CARD32 tv_dac_cntl; + CARD32 fp2_gen_cntl; + + switch(info->ChipFamily) + { + case CHIP_FAMILY_R420: + case CHIP_FAMILY_RV410: + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + if (IsOn) { + tv_dac_cntl &= ~(R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } else { + tv_dac_cntl |= (R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + break; + case CHIP_FAMILY_R200: + fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); + if (IsOn) { + fp2_gen_cntl |= RADEON_FP2_DVO_EN; + } else { + fp2_gen_cntl &= ~RADEON_FP2_DVO_EN; + } + OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + break; + + default: + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + if (IsOn) { + tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } else { + tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_BDACPD | + RADEON_TV_DAC_BGSLEEP); + } + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + break; + } + } +} + +/* This is to be used enable/disable displays dynamically */ +static void +RADEONEnableDisplay(xf86OutputPtr output, BOOL bEnable) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONSavePtr save = info->ModeReg; + unsigned char * RADEONMMIO = info->MMIO; + unsigned long tmp; + RADEONOutputPrivatePtr radeon_output; + int tv_dac_change = 0, o; + radeon_output = output->driver_private; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + for (o = 0; o < xf86_config->num_output; o++) { + if (output == xf86_config->output[o]) { + break; + } + } + + if (bEnable) { + ErrorF("enable montype: %d\n", radeon_output->MonType); + if (radeon_output->MonType == MT_CRT) { + if (radeon_output->DACType == DAC_PRIMARY) { + info->output_crt1 |= (1 << o); + tmp = INREG(RADEON_CRTC_EXT_CNTL); + tmp |= RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, tmp); + save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + } else if (radeon_output->DACType == DAC_TVDAC) { + info->output_crt2 |= (1 << o); + if (info->ChipFamily == CHIP_FAMILY_R200) { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + } else { + tmp = INREG(RADEON_CRTC2_GEN_CNTL); + tmp |= RADEON_CRTC2_CRT2_ON; + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); + save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; + } + tv_dac_change = 1; + } + } else if (radeon_output->MonType == MT_DFP) { + if (radeon_output->TMDSType == TMDS_INT) { + info->output_dfp1 |= (1 << o); + tmp = INREG(RADEON_FP_GEN_CNTL); + tmp |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); + OUTREG(RADEON_FP_GEN_CNTL, tmp); + save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); + } else if (radeon_output->TMDSType == TMDS_EXT) { + info->output_dfp2 |= (1 << o); + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp &= ~RADEON_FP2_BLANK_EN; + tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); + save->fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN; + } + } else if (radeon_output->MonType == MT_LCD) { + info->output_lcd1 |= (1 << o); + tmp = INREG(RADEON_LVDS_GEN_CNTL); + tmp |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); + tmp &= ~(RADEON_LVDS_DISPLAY_DIS); + usleep (radeon_output->PanelPwrDly * 1000); + OUTREG(RADEON_LVDS_GEN_CNTL, tmp); + save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); + save->lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); + } else if (radeon_output->MonType == MT_STV || + radeon_output->MonType == MT_CTV) { + info->output_tv1 |= (1 << o); + tmp = INREG(RADEON_TV_MASTER_CNTL); + tmp |= RADEON_TV_ON; + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + tv_dac_change = 2; + radeon_output->tv_on = TRUE; + } + } else { + ErrorF("disable montype: %d\n", radeon_output->MonType); + if (radeon_output->MonType == MT_CRT) { + if (radeon_output->DACType == DAC_PRIMARY) { + info->output_crt1 &= ~(1 << o); + if (!info->output_crt1) { + tmp = INREG(RADEON_CRTC_EXT_CNTL); + tmp &= ~RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, tmp); + save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + } + } else if (radeon_output->DACType == DAC_TVDAC) { + info->output_crt2 &= ~(1 << o); + tv_dac_change = 1; + if (!info->output_crt2) { + if (info->ChipFamily == CHIP_FAMILY_R200) { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + } else { + tmp = INREG(RADEON_CRTC2_GEN_CNTL); + tmp &= ~RADEON_CRTC2_CRT2_ON; + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); + save->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; + } + } + } + } else if (radeon_output->MonType == MT_DFP) { + if (radeon_output->TMDSType == TMDS_INT) { + info->output_dfp1 &= ~(1 << o); + if (!info->output_dfp1) { + tmp = INREG(RADEON_FP_GEN_CNTL); + tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + OUTREG(RADEON_FP_GEN_CNTL, tmp); + save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + } + } else if (radeon_output->TMDSType == TMDS_EXT) { + info->output_dfp2 &= ~(1 << o); + if (!info->output_dfp2) { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp |= RADEON_FP2_BLANK_EN; + tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + save->fp2_gen_cntl |= RADEON_FP2_BLANK_EN; + } + } + } else if (radeon_output->MonType == MT_LCD) { + info->output_lcd1 &= ~(1 << o); + if (!info->output_lcd1) { + unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + if (info->IsMobility || info->IsIGP) { + /* Asic bug, when turning off LVDS_ON, we have to make sure + RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off + */ + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); + } + tmp = INREG(RADEON_LVDS_GEN_CNTL); + tmp |= RADEON_LVDS_DISPLAY_DIS; + tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); + OUTREG(RADEON_LVDS_GEN_CNTL, tmp); + save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; + save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); + if (info->IsMobility || info->IsIGP) { + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + } + } + } else if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) { + info->output_tv1 &= ~(1 << o); + tv_dac_change = 2; + if (!info->output_tv1) { + tmp = INREG(RADEON_TV_MASTER_CNTL); + tmp &= ~RADEON_TV_ON; + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + radeon_output->tv_on = FALSE; + } + } + } + + if (tv_dac_change) { + if (bEnable) + info->tv_dac_enable_mask |= tv_dac_change; + else + info->tv_dac_enable_mask &= ~tv_dac_change; + + if (bEnable && info->tv_dac_enable_mask) + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + else if (!bEnable && info->tv_dac_enable_mask == 0) + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + + } +} + +void +legacy_output_dpms(xf86OutputPtr output, int mode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + switch(mode) { + case DPMSModeOn: + RADEONEnableDisplay(output, TRUE); + break; + case DPMSModeOff: + case DPMSModeSuspend: + case DPMSModeStandby: + RADEONEnableDisplay(output, FALSE); + break; + } +} + +static void +RADEONInitFPRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int i; + CARD32 tmp = info->SavedReg->tmds_pll_cntl & 0xfffff; + + for (i=0; i<4; i++) { + if (radeon_output->tmds_pll[i].freq == 0) break; + if ((CARD32)(mode->Clock/10) < radeon_output->tmds_pll[i].freq) { + tmp = radeon_output->tmds_pll[i].value ; + break; + } + } + + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) { + if (tmp & 0xfff00000) + save->tmds_pll_cntl = tmp; + else { + save->tmds_pll_cntl = info->SavedReg->tmds_pll_cntl & 0xfff00000; + save->tmds_pll_cntl |= tmp; + } + } else save->tmds_pll_cntl = tmp; + + save->tmds_transmitter_cntl = info->SavedReg->tmds_transmitter_cntl & + ~(RADEON_TMDS_TRANSMITTER_PLLRST); + + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !pRADEONEnt->HasCRTC2) + save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); + else /* weird, RV chips got this bit reversed? */ + save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); + + save->fp_gen_cntl = info->SavedReg->fp_gen_cntl | + (RADEON_FP_CRTC_DONT_SHADOW_VPAR | + RADEON_FP_CRTC_DONT_SHADOW_HEND ); + + save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + + if (pScrn->rgbBits == 8) + save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ + else + save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ + + + if (IsPrimary) { + if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { + save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + if (mode->Flags & RADEON_USE_RMX) + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; + else + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; + } else + save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1; + } else { + if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { + save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; + } else + save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2; + } + +} + +static void +RADEONInitFP2Registers(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + + if (pScrn->rgbBits == 8) + save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl | + RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ + else + save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl & + ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ + + save->fp2_gen_cntl &= ~(RADEON_FP2_ON | + RADEON_FP2_DVO_EN | + RADEON_FP2_DVO_RATE_SEL_SDR); + + + /* XXX: these may be oem specific */ + if (IS_R300_VARIANT) { + save->fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE; +#if 0 + if (mode->Clock > 165000) + save->fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN; +#endif + } + + if (IsPrimary) { + if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { + save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; + if (mode->Flags & RADEON_USE_RMX) + save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; + } else { + save->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2; + } + } else { + if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { + save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; + save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; + } else { + save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; + } + } + +} + +static void +RADEONInitLVDSRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + save->lvds_pll_cntl = (info->SavedReg->lvds_pll_cntl | + RADEON_LVDS_PLL_EN); + + save->lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; + + save->lvds_gen_cntl = info->SavedReg->lvds_gen_cntl; + save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; + save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | + RADEON_LVDS_BLON | + RADEON_LVDS_EN | + RADEON_LVDS_RST_FM); + + if (IS_R300_VARIANT) + save->lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK); + + if (IsPrimary) { + if (IS_R300_VARIANT) { + if (mode->Flags & RADEON_USE_RMX) + save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX; + } else + save->lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; + } else { + if (IS_R300_VARIANT) { + save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2; + } else + save->lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2; + } + +} + +static void +RADEONInitRMXRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int xres = mode->HDisplay; + int yres = mode->VDisplay; + float Hratio, Vratio; + + save->fp_vert_stretch = info->SavedReg->fp_vert_stretch & + RADEON_VERT_STRETCH_RESERVED; + save->fp_horz_stretch = info->SavedReg->fp_horz_stretch & + (RADEON_HORZ_FP_LOOP_STRETCH | + RADEON_HORZ_AUTO_RATIO_INC); + + if (radeon_output->MonType != MT_LCD && radeon_output->MonType != MT_DFP) + return; + + if (radeon_output->PanelXRes == 0 || radeon_output->PanelYRes == 0) { + Hratio = 1.0; + Vratio = 1.0; + } else { + if (xres > radeon_output->PanelXRes) xres = radeon_output->PanelXRes; + if (yres > radeon_output->PanelYRes) yres = radeon_output->PanelYRes; + + Hratio = (float)xres/(float)radeon_output->PanelXRes; + Vratio = (float)yres/(float)radeon_output->PanelYRes; + } + + if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { + save->fp_horz_stretch |= ((xres/8-1)<<16); + } else { + save->fp_horz_stretch |= ((((unsigned long) + (Hratio * RADEON_HORZ_STRETCH_RATIO_MAX)) & + RADEON_HORZ_STRETCH_RATIO_MASK) | + RADEON_HORZ_STRETCH_BLEND | + RADEON_HORZ_STRETCH_ENABLE | + ((radeon_output->PanelXRes/8-1)<<16)); + } + + if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { + save->fp_vert_stretch |= ((yres-1)<<12); + } else { + save->fp_vert_stretch |= ((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX)) & + RADEON_VERT_STRETCH_RATIO_MASK) | + RADEON_VERT_STRETCH_ENABLE | + RADEON_VERT_STRETCH_BLEND | + ((radeon_output->PanelYRes-1)<<12)); + } + +} + +static void +RADEONInitDACRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (IsPrimary) { + if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg->disp_output_cntl & + ~RADEON_DISP_DAC_SOURCE_MASK; + } else { + save->dac2_cntl = info->SavedReg->dac2_cntl & ~(RADEON_DAC2_DAC_CLK_SEL); + } + } else { + if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg->disp_output_cntl & + ~RADEON_DISP_DAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; + } else { + save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC_CLK_SEL; + } + } + save->dac_cntl = (RADEON_DAC_MASK_ALL + | RADEON_DAC_VGA_ADR_EN + | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN)); + + save->dac_macro_cntl = info->SavedReg->dac_macro_cntl; +} + +static void +RADEONInitTvDacCntl(xf86OutputPtr output, RADEONSavePtr save) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (info->ChipFamily == CHIP_FAMILY_R420 || + info->ChipFamily == CHIP_FAMILY_RV410) { + save->tv_dac_cntl = info->SavedReg->tv_dac_cntl & + ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + R420_TV_DAC_DACADJ_MASK | + R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_TVENABLE); + } else { + save->tv_dac_cntl = info->SavedReg->tv_dac_cntl & + ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + RADEON_TV_DAC_DACADJ_MASK | + RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_GDACPD); + } + + save->tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_DAC_STD_PS2 | + radeon_output->tv_dac_adj); + +} + +static void +RADEONInitDAC2Registers(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + /*0x0028023;*/ + RADEONInitTvDacCntl(output, save); + + if (IS_R300_VARIANT) + save->gpiopad_a = info->SavedReg->gpiopad_a | 1; + + save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; + + if (IsPrimary) { + if (IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg->disp_output_cntl & + ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; + } else if (info->ChipFamily == CHIP_FAMILY_R200) { + save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl & + ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + } else { + save->disp_hw_debug = info->SavedReg->disp_hw_debug | RADEON_CRT2_DISP1_SEL; + } + } else { + if (IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg->disp_output_cntl & + ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + } else if (info->ChipFamily == CHIP_FAMILY_R200) { + save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl & + ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; + } else { + save->disp_hw_debug = info->SavedReg->disp_hw_debug & + ~RADEON_CRT2_DISP1_SEL; + } + } +} + +static void +RADEONInitOutputRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output, + int crtc_num) +{ + Bool IsPrimary = crtc_num == 0 ? TRUE : FALSE; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (crtc_num == 0) + RADEONInitRMXRegisters(output, save, mode); + + if (radeon_output->MonType == MT_CRT) { + if (radeon_output->DACType == DAC_PRIMARY) { + RADEONInitDACRegisters(output, save, mode, IsPrimary); + } else { + RADEONInitDAC2Registers(output, save, mode, IsPrimary); + } + } else if (radeon_output->MonType == MT_LCD) { + RADEONInitLVDSRegisters(output, save, mode, IsPrimary); + } else if (radeon_output->MonType == MT_DFP) { + if (radeon_output->TMDSType == TMDS_INT) { + RADEONInitFPRegisters(output, save, mode, IsPrimary); + } else { + RADEONInitFP2Registers(output, save, mode, IsPrimary); + } + } else if (radeon_output->MonType == MT_STV || + radeon_output->MonType == MT_CTV) { + RADEONInitTVRegisters(output, save, mode, IsPrimary); + } +} + +void +legacy_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + xf86CrtcPtr crtc = output->crtc; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + RADEONInitOutputRegisters(pScrn, info->ModeReg, adjusted_mode, output, radeon_crtc->crtc_id); + + if (radeon_crtc->crtc_id == 0) + RADEONRestoreRMXRegisters(pScrn, info->ModeReg); + + switch(radeon_output->MonType) { + case MT_LCD: + ErrorF("restore LVDS\n"); + RADEONRestoreLVDSRegisters(pScrn, info->ModeReg); + break; + case MT_DFP: + if (radeon_output->TMDSType == TMDS_INT) { + ErrorF("restore FP\n"); + RADEONRestoreFPRegisters(pScrn, info->ModeReg); + } else { + ErrorF("restore FP2\n"); + if (info->IsAtomBios) + atombios_external_tmds_setup(output, mode); + else + RADEONRestoreDVOChip(pScrn, output); + RADEONRestoreFP2Registers(pScrn, info->ModeReg); + } + break; + case MT_STV: + case MT_CTV: + ErrorF("restore tv\n"); + RADEONRestoreDACRegisters(pScrn, info->ModeReg); + RADEONRestoreTVRegisters(pScrn, info->ModeReg); + break; + default: + ErrorF("restore dac\n"); + RADEONRestoreDACRegisters(pScrn, info->ModeReg); + } + +} + +/* the following functions are based on the load detection code + * in the beos radeon driver by Thomas Kurschel and the existing + * load detection code in this driver. + */ +static RADEONMonitorType +radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 vclk_ecp_cntl, crtc_ext_cntl; + CARD32 dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp; + RADEONMonitorType found = MT_NONE; + + /* save the regs we need */ + vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); + dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); + dac_cntl = INREG(RADEON_DAC_CNTL); + dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); + + tmp = vclk_ecp_cntl & + ~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); + + tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, tmp); + + tmp = RADEON_DAC_FORCE_BLANK_OFF_EN | + RADEON_DAC_FORCE_DATA_EN; + + if (color) + tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; + else + tmp |= RADEON_DAC_FORCE_DATA_SEL_G; + + if (IS_R300_VARIANT) + tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); + + OUTREG(RADEON_DAC_EXT_CNTL, tmp); + + tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN); + tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; + OUTREG(RADEON_DAC_CNTL, tmp); + + tmp &= ~(RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + + OUTREG(RADEON_DAC_MACRO_CNTL, tmp); + + usleep(2000); + + if (INREG(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) { + found = MT_CRT; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Found %s CRT connected to primary DAC\n", + color ? "color" : "bw"); + } + + /* restore the regs we used */ + OUTREG(RADEON_DAC_CNTL, dac_cntl); + OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); + OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl); + + return found; +} + +static RADEONMonitorType +radeon_detect_ext_dac(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; + CARD32 disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; + CARD32 disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; + CARD32 tmp, crtc2_h_total_disp, crtc2_v_total_disp; + CARD32 crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; + RADEONMonitorType found = MT_NONE; + int connected = 0; + int i = 0; + + /* save the regs we need */ + gpio_monid = INREG(RADEON_GPIO_MONID); + fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); + disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + disp_lin_trans_grph_a = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); + disp_lin_trans_grph_b = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); + disp_lin_trans_grph_c = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); + disp_lin_trans_grph_d = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); + disp_lin_trans_grph_e = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); + disp_lin_trans_grph_f = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); + crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP); + crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP); + crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); + crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); + + tmp = INREG(RADEON_GPIO_MONID); + tmp &= ~RADEON_GPIO_A_0; + OUTREG(RADEON_GPIO_MONID, tmp); + + OUTREG(RADEON_FP2_GEN_CNTL, + RADEON_FP2_ON | + RADEON_FP2_PANEL_FORMAT | + R200_FP2_SOURCE_SEL_TRANS_UNIT | + RADEON_FP2_DVO_EN | + R200_FP2_DVO_RATE_SEL_SDR); + + OUTREG(RADEON_DISP_OUTPUT_CNTL, + RADEON_DISP_DAC_SOURCE_RMX | + RADEON_DISP_TRANS_MATRIX_GRAPHICS); + + OUTREG(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_EN | + RADEON_CRTC2_DISP_REQ_EN_B); + + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) { + tmp = INREG(RADEON_GPIO_MONID); + if (tmp & RADEON_GPIO_Y_0) + connected = 1; + else + connected = 0; + + if (!connected) + break; + + usleep(1000); + } + + if (connected) + found = MT_CRT; + + /* restore the regs we used */ + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); + OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + OUTREG(RADEON_GPIO_MONID, gpio_monid); + + return found; +} + +static RADEONMonitorType +radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; + CARD32 disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; + RADEONMonitorType found = MT_NONE; + + /* save the regs we need */ + pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + gpiopad_a = IS_R300_VARIANT ? INREG(RADEON_GPIOPAD_A) : 0; + disp_output_cntl = IS_R300_VARIANT ? INREG(RADEON_DISP_OUTPUT_CNTL) : 0; + disp_hw_debug = !IS_R300_VARIANT ? INREG(RADEON_DISP_HW_DEBUG) : 0; + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); + dac_cntl2 = INREG(RADEON_DAC_CNTL2); + + tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + + if (IS_R300_VARIANT) { + OUTREGP(RADEON_GPIOPAD_A, 1, ~1 ); + } + + tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; + tmp |= RADEON_CRTC2_CRT2_ON | + (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); + + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); + + if (IS_R300_VARIANT) { + tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; + tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp); + } else { + tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; + OUTREG(RADEON_DISP_HW_DEBUG, tmp); + } + + tmp = RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | + RADEON_TV_DAC_STD_PS2; + + OUTREG(RADEON_TV_DAC_CNTL, tmp); + + tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN | + RADEON_DAC2_FORCE_DATA_EN; + + if (color) + tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; + else + tmp |= RADEON_DAC_FORCE_DATA_SEL_G; + + if (IS_R300_VARIANT) + tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); + + OUTREG(RADEON_DAC_EXT_CNTL, tmp); + + tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN; + OUTREG(RADEON_DAC_CNTL2, tmp); + + usleep(10000); + + if (IS_R300_VARIANT) { + if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) { + found = MT_CRT; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Found %s CRT connected to TV DAC\n", + color ? "color" : "bw"); + } + } else { + if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) { + found = MT_CRT; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Found %s CRT connected to TV DAC\n", + color ? "color" : "bw"); + } + } + + /* restore regs we used */ + OUTREG(RADEON_DAC_CNTL2, dac_cntl2); + OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + + if (IS_R300_VARIANT) { + OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1 ); + } else { + OUTREG(RADEON_DISP_HW_DEBUG, disp_hw_debug); + } + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, pixclks_cntl); + + return found; +} + +static RADEONMonitorType +r300_detect_tv(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp, dac_cntl2, crtc2_gen_cntl, dac_ext_cntl, tv_dac_cntl; + CARD32 gpiopad_a, disp_output_cntl; + RADEONMonitorType found = MT_NONE; + + /* save the regs we need */ + gpiopad_a = INREG(RADEON_GPIOPAD_A); + dac_cntl2 = INREG(RADEON_DAC_CNTL2); + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); + + OUTREGP(RADEON_GPIOPAD_A, 0, ~1 ); + + OUTREG(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL ); + + OUTREG(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT ); + + tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; + tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp); + + OUTREG(RADEON_DAC_EXT_CNTL, + RADEON_DAC2_FORCE_BLANK_OFF_EN | + RADEON_DAC2_FORCE_DATA_EN | + RADEON_DAC_FORCE_DATA_SEL_RGB | + (0xec << RADEON_DAC_FORCE_DATA_SHIFT )); + + OUTREG(RADEON_TV_DAC_CNTL, + RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT) | + (6 << RADEON_TV_DAC_DACADJ_SHIFT )); + + INREG(RADEON_TV_DAC_CNTL); + + usleep(4000); + + OUTREG(RADEON_TV_DAC_CNTL, + RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | + RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT) | + (6 << RADEON_TV_DAC_DACADJ_SHIFT )); + + INREG(RADEON_TV_DAC_CNTL); + + usleep(6000); + + tmp = INREG(RADEON_TV_DAC_CNTL); + if ( (tmp & RADEON_TV_DAC_GDACDET) != 0 ) { + found = MT_STV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "S-Video TV connection detected\n"); + } else if ( (tmp & RADEON_TV_DAC_BDACDET) != 0 ) { + found = MT_CTV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Composite TV connection detected\n" ); + } + + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl ); + OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + OUTREG(RADEON_DAC_CNTL2, dac_cntl2); + OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1); + + return found; +} + +static RADEONMonitorType +radeon_detect_tv(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp, dac_cntl2, tv_master_cntl; + CARD32 tv_dac_cntl, tv_pre_dac_mux_cntl, config_cntl; + RADEONMonitorType found = MT_NONE; + + if (IS_R300_VARIANT) + return r300_detect_tv(pScrn); + + /* save the regs we need */ + dac_cntl2 = INREG(RADEON_DAC_CNTL2); + tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL); + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + config_cntl = INREG(RADEON_CONFIG_CNTL); + tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); + + tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL; + OUTREG(RADEON_DAC_CNTL2, tmp); + + tmp = tv_master_cntl | RADEON_TV_ON; + tmp &= ~(RADEON_TV_ASYNC_RST | + RADEON_RESTART_PHASE_FIX | + RADEON_CRT_FIFO_CE_EN | + RADEON_TV_FIFO_CE_EN | + RADEON_RE_SYNC_NOW_SEL_MASK); + tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST; + + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + + tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT); + + if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK) + tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT); + else + tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT); + + OUTREG(RADEON_TV_DAC_CNTL, tmp); + + tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN | + RADEON_RED_MX_FORCE_DAC_DATA | + RADEON_GRN_MX_FORCE_DAC_DATA | + RADEON_BLU_MX_FORCE_DAC_DATA | + (0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT); + + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tmp); + + usleep(3000); + + tmp = INREG(RADEON_TV_DAC_CNTL); + if (tmp & RADEON_TV_DAC_GDACDET) { + found = MT_STV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "S-Video TV connection detected\n"); + } else if (tmp & RADEON_TV_DAC_BDACDET) { + found = MT_CTV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Composite TV connection detected\n" ); + } + + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl); + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + OUTREG(RADEON_TV_MASTER_CNTL, tv_master_cntl); + OUTREG(RADEON_DAC_CNTL2, dac_cntl2); + + return found; +} + +/* disable all ouputs before enabling the ones we want */ +void +RADEONDisableDisplays(ScrnInfoPtr pScrn) { + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char * RADEONMMIO = info->MMIO; + unsigned long tmp, tmpPixclksCntl; + + + /* primary DAC */ + tmp = INREG(RADEON_CRTC_EXT_CNTL); + tmp &= ~RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, tmp); + RADEONDacPowerSet(pScrn, FALSE, TRUE); + + /* Secondary DAC */ + if (info->ChipFamily == CHIP_FAMILY_R200) { + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + } else { + tmp = INREG(RADEON_CRTC2_GEN_CNTL); + tmp &= ~RADEON_CRTC2_CRT2_ON; + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); + } + RADEONDacPowerSet(pScrn, FALSE, FALSE); + + /* turn off tv-out */ + if (info->InternalTVOut) { + tmp = INREG(RADEON_TV_MASTER_CNTL); + tmp &= ~RADEON_TV_ON; + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + } + + /* FP 1 */ + tmp = INREG(RADEON_FP_GEN_CNTL); + tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + OUTREG(RADEON_FP_GEN_CNTL, tmp); + + /* FP 2 */ + tmp = INREG(RADEON_FP2_GEN_CNTL); + tmp |= RADEON_FP2_BLANK_EN; + tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + OUTREG(RADEON_FP2_GEN_CNTL, tmp); + + /* LVDS */ + if (info->IsMobility) { + tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + if (info->IsMobility || info->IsIGP) { + /* Asic bug, when turning off LVDS_ON, we have to make sure + RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off + */ + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); + } + tmp = INREG(RADEON_LVDS_GEN_CNTL); + tmp |= RADEON_LVDS_DISPLAY_DIS; + tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); + OUTREG(RADEON_LVDS_GEN_CNTL, tmp); + if (info->IsMobility || info->IsIGP) { + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + } + } + +} diff --git a/src/radeon.h b/src/radeon.h index 7f4d0015..47e1b890 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -842,13 +842,10 @@ extern void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info); extern void RADEONInitDispBandwidth(ScrnInfoPtr pScrn); extern Bool RADEONI2cInit(ScrnInfoPtr pScrn); -extern void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag); extern Bool RADEONSetupConnectors(ScrnInfoPtr pScrn); extern void RADEONPrintPortMap(ScrnInfoPtr pScrn); -extern void RADEONEnableDisplay(xf86OutputPtr pPort, BOOL bEnable); extern void RADEONDisableDisplays(ScrnInfoPtr pScrn); extern void RADEONGetPanelInfo(ScrnInfoPtr pScrn); -extern void RADEONGetTVDacAdjInfo(xf86OutputPtr output); extern void RADEONUnblank(ScrnInfoPtr pScrn); extern void RADEONUnblank(ScrnInfoPtr pScrn); extern void RADEONBlank(ScrnInfoPtr pScrn); diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c index 8e665187..9034cf50 100644 --- a/src/radeon_crtc.c +++ b/src/radeon_crtc.c @@ -53,68 +53,27 @@ #include "sarea.h" #endif -void radeon_crtc_load_lut(xf86CrtcPtr crtc); - extern void atombios_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode, int x, int y); +extern void legacy_crtc_mode_set(xf86CrtcPtr crtc, + DisplayModePtr mode, + DisplayModePtr adjusted_mode, + int x, int y); extern void atombios_crtc_dpms(xf86CrtcPtr crtc, int mode); +extern void legacy_crtc_dpms(xf86CrtcPtr crtc, int mode); static void radeon_crtc_dpms(xf86CrtcPtr crtc, int mode) { - int mask; - ScrnInfoPtr pScrn = crtc->scrn; - RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; + RADEONInfoPtr info = RADEONPTR(crtc->scrn); if (IS_AVIVO_VARIANT) { atombios_crtc_dpms(crtc, mode); - return; - } - - mask = radeon_crtc->crtc_id ? (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_REQ_EN_B) : (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_VSYNC_DIS); - - - switch(mode) { - case DPMSModeOn: - if (radeon_crtc->crtc_id) { - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask); - } else { - OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); - OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask); - } - break; - case DPMSModeStandby: - if (radeon_crtc->crtc_id) { - OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), ~mask); - } else { - OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); - OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), ~mask); - } - break; - case DPMSModeSuspend: - if (radeon_crtc->crtc_id) { - OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), ~mask); - } else { - OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); - OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), ~mask); - } - break; - case DPMSModeOff: - if (radeon_crtc->crtc_id) { - OUTREGP(RADEON_CRTC2_GEN_CNTL, mask, ~mask); - } else { - OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~RADEON_CRTC_DISP_REQ_EN_B); - OUTREGP(RADEON_CRTC_EXT_CNTL, mask, ~mask); - } - break; + } else { + legacy_crtc_dpms(crtc, mode); } - - if (mode != DPMSModeOff) - radeon_crtc_load_lut(crtc); } static Bool @@ -133,491 +92,6 @@ radeon_crtc_mode_prepare(xf86CrtcPtr crtc) radeon_crtc_dpms(crtc, DPMSModeOff); } -/* Define common registers for requested video mode */ -static void -RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) -{ - save->ovr_clr = 0; - save->ovr_wid_left_right = 0; - save->ovr_wid_top_bottom = 0; - save->ov0_scale_cntl = 0; - save->subpic_cntl = 0; - save->viph_control = 0; - save->i2c_cntl_1 = 0; - save->rbbm_soft_reset = 0; - save->cap0_trig_cntl = 0; - save->cap1_trig_cntl = 0; - save->bus_cntl = info->BusCntl; - /* - * If bursts are enabled, turn on discards - * Radeon doesn't have write bursts - */ - if (save->bus_cntl & (RADEON_BUS_READ_BURST)) - save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; -} - -static void -RADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save) -{ - save->surface_cntl = 0; - -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* We must set both apertures as they can be both used to map the entire - * video memory. -BenH. - */ - switch (crtc->scrn->bitsPerPixel) { - case 16: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; - break; - - case 32: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; - break; - } -#endif - -} - -Bool -RADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save, - int x, int y) -{ - ScrnInfoPtr pScrn = crtc->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - int Base; -#ifdef XF86DRI - RADEONSAREAPrivPtr pSAREAPriv; - XF86DRISAREAPtr pSAREA; -#endif - - save->crtc_offset = pScrn->fbOffset; -#ifdef XF86DRI - if (info->allowPageFlip) - save->crtc_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL; - else -#endif - save->crtc_offset_cntl = 0; - - if (info->tilingEnabled && (crtc->rotatedData == NULL)) { - if (IS_R300_VARIANT) - save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; - } - else { - if (IS_R300_VARIANT) - save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; - } - - Base = pScrn->fbOffset; - - if (info->tilingEnabled && (crtc->rotatedData == NULL)) { - if (IS_R300_VARIANT) { - /* On r300/r400 when tiling is enabled crtc_offset is set to the address of - * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc - * Makes tiling MUCH easier. - */ - save->crtc_tile_x0_y0 = x | (y << 16); - Base &= ~0x7ff; - } else { - /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the - drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes - flickering when scrolling vertically in a virtual screen, possibly because crtc will - pick up the new offset value at the end of each scanline, but the new offset_cntl value - only after a vsync. We'd probably need to wait (in drm) for vsync and only then update - OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ - /*save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL) & ~0xf;*/ -#if 0 - /* try to get rid of flickering when scrolling at least for 2d */ -#ifdef XF86DRI - if (!info->have3DWindows) -#endif - save->crtc_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; -#endif - - int byteshift = info->CurrentLayout.bitsPerPixel >> 4; - /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ - int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; - Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); - save->crtc_offset_cntl = save->crtc_offset_cntl | (y % 16); - } - } - else { - int offset = y * info->CurrentLayout.displayWidth + x; - switch (info->CurrentLayout.pixel_code) { - case 15: - case 16: offset *= 2; break; - case 24: offset *= 3; break; - case 32: offset *= 4; break; - } - Base += offset; - } - - if (crtc->rotatedData != NULL) { - Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; - } - - Base &= ~7; /* 3 lower bits are always 0 */ - - -#ifdef XF86DRI - if (info->directRenderingInited) { - /* note cannot use pScrn->pScreen since this is unitialized when called from - RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ - /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for - *** pageflipping! - ***/ - pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]); - /* can't get at sarea in a semi-sane way? */ - pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); - - pSAREA->frame.x = (Base / info->CurrentLayout.pixel_bytes) - % info->CurrentLayout.displayWidth; - pSAREA->frame.y = (Base / info->CurrentLayout.pixel_bytes) - / info->CurrentLayout.displayWidth; - pSAREA->frame.width = pScrn->frameX1 - x + 1; - pSAREA->frame.height = pScrn->frameY1 - y + 1; - - if (pSAREAPriv->pfCurrentPage == 1) { - Base += info->backOffset - info->frontOffset; - } - } -#endif - save->crtc_offset = Base; - - return TRUE; - -} - -/* Define CRTC registers for requested video mode */ -Bool -RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save, - DisplayModePtr mode) -{ - ScrnInfoPtr pScrn = crtc->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - int format; - int hsync_start; - int hsync_wid; - int vsync_wid; - - switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; break; - case 8: format = 2; break; - case 15: format = 3; break; /* 555 */ - case 16: format = 4; break; /* 565 */ - case 24: format = 5; break; /* RGB */ - case 32: format = 6; break; /* xRGB */ - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unsupported pixel depth (%d)\n", - info->CurrentLayout.bitsPerPixel); - return FALSE; - } - - /*save->bios_4_scratch = info->SavedReg->bios_4_scratch;*/ - save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN - | RADEON_CRTC_EN - | (format << 8) - | ((mode->Flags & V_DBLSCAN) - ? RADEON_CRTC_DBL_SCAN_EN - : 0) - | ((mode->Flags & V_CSYNC) - ? RADEON_CRTC_CSYNC_EN - : 0) - | ((mode->Flags & V_INTERLACE) - ? RADEON_CRTC_INTERLACE_EN - : 0)); - - save->crtc_ext_cntl |= (RADEON_XCRT_CNT_EN| - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS | - RADEON_CRTC_DISPLAY_DIS); - - save->disp_merge_cntl = info->SavedReg->disp_merge_cntl; - save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; - - save->crtc_more_cntl = 0; - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200)) { - /* This is to workaround the asic bug for RMX, some versions - of BIOS dosen't have this register initialized correctly. - */ - save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; - } - - save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) - | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) - << 16)); - - hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; - if (!hsync_wid) hsync_wid = 1; - hsync_start = mode->CrtcHSyncStart - 8; - - save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) - | ((hsync_wid & 0x3f) << 16) - | ((mode->Flags & V_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); - - /* This works for double scan mode. */ - save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - 1) << 16)); - - vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; - if (!vsync_wid) vsync_wid = 1; - - save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) - | ((vsync_wid & 0x1f) << 16) - | ((mode->Flags & V_NVSYNC) - ? RADEON_CRTC_V_SYNC_POL - : 0)); - - save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + - ((pScrn->bitsPerPixel * 8) -1)) / - (pScrn->bitsPerPixel * 8)); - save->crtc_pitch |= save->crtc_pitch << 16; - - save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; - save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; - save->fp_crtc_h_total_disp = save->crtc_h_total_disp; - save->fp_crtc_v_total_disp = save->crtc_v_total_disp; - - if (info->IsDellServer) { - save->dac2_cntl = info->SavedReg->dac2_cntl; - save->tv_dac_cntl = info->SavedReg->tv_dac_cntl; - save->crtc2_gen_cntl = info->SavedReg->crtc2_gen_cntl; - save->disp_hw_debug = info->SavedReg->disp_hw_debug; - - save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; - save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; - - /* For CRT on DAC2, don't turn it on if BIOS didn't - enable it, even it's detected. - */ - save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; - save->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16)); - save->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16)); - } - - return TRUE; -} - -Bool -RADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save, - int x, int y) -{ - ScrnInfoPtr pScrn = crtc->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - int Base; -#ifdef XF86DRI - RADEONSAREAPrivPtr pSAREAPriv; - XF86DRISAREAPtr pSAREA; -#endif - - /* It seems all fancy options apart from pflip can be safely disabled - */ - save->crtc2_offset = pScrn->fbOffset; -#ifdef XF86DRI - if (info->allowPageFlip) - save->crtc2_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL; - else -#endif - save->crtc2_offset_cntl = 0; - - if (info->tilingEnabled && (crtc->rotatedData == NULL)) { - if (IS_R300_VARIANT) - save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN; - } - else { - if (IS_R300_VARIANT) - save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN; - } - - Base = pScrn->fbOffset; - - if (info->tilingEnabled && (crtc->rotatedData == NULL)) { - if (IS_R300_VARIANT) { - /* On r300/r400 when tiling is enabled crtc_offset is set to the address of - * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc - * Makes tiling MUCH easier. - */ - save->crtc2_tile_x0_y0 = x | (y << 16); - Base &= ~0x7ff; - } else { - /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the - drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes - flickering when scrolling vertically in a virtual screen, possibly because crtc will - pick up the new offset value at the end of each scanline, but the new offset_cntl value - only after a vsync. We'd probably need to wait (in drm) for vsync and only then update - OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ - /*save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & ~0xf;*/ -#if 0 - /* try to get rid of flickering when scrolling at least for 2d */ -#ifdef XF86DRI - if (!info->have3DWindows) -#endif - save->crtc2_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; -#endif - - int byteshift = info->CurrentLayout.bitsPerPixel >> 4; - /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ - int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; - Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); - save->crtc2_offset_cntl = save->crtc_offset_cntl | (y % 16); - } - } - else { - int offset = y * info->CurrentLayout.displayWidth + x; - switch (info->CurrentLayout.pixel_code) { - case 15: - case 16: offset *= 2; break; - case 24: offset *= 3; break; - case 32: offset *= 4; break; - } - Base += offset; - } - - if (crtc->rotatedData != NULL) { - Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; - } - - Base &= ~7; /* 3 lower bits are always 0 */ - -#ifdef XF86DRI - if (info->directRenderingInited) { - /* note cannot use pScrn->pScreen since this is unitialized when called from - RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ - /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for - *** pageflipping! - ***/ - pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]); - /* can't get at sarea in a semi-sane way? */ - pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); - - pSAREAPriv->crtc2_base = Base; - - if (pSAREAPriv->pfCurrentPage == 1) { - Base += info->backOffset - info->frontOffset; - } - } -#endif - save->crtc2_offset = Base; - - return TRUE; -} - -/* Define CRTC2 registers for requested video mode */ -Bool -RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save, - DisplayModePtr mode) -{ - ScrnInfoPtr pScrn = crtc->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - int format; - int hsync_start; - int hsync_wid; - int vsync_wid; - - switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; break; - case 8: format = 2; break; - case 15: format = 3; break; /* 555 */ - case 16: format = 4; break; /* 565 */ - case 24: format = 5; break; /* RGB */ - case 32: format = 6; break; /* xRGB */ - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unsupported pixel depth (%d)\n", - info->CurrentLayout.bitsPerPixel); - return FALSE; - } - - save->crtc2_h_total_disp = - ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) - | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); - - hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; - if (!hsync_wid) hsync_wid = 1; - hsync_start = mode->CrtcHSyncStart - 8; - - save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) - | ((hsync_wid & 0x3f) << 16) - | ((mode->Flags & V_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); - - /* This works for double scan mode. */ - save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - 1) << 16)); - - vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; - if (!vsync_wid) vsync_wid = 1; - - save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) - | ((vsync_wid & 0x1f) << 16) - | ((mode->Flags & V_NVSYNC) - ? RADEON_CRTC2_V_SYNC_POL - : 0)); - - save->crtc2_pitch = ((pScrn->displayWidth * pScrn->bitsPerPixel) + - ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); - save->crtc2_pitch |= save->crtc2_pitch << 16; - - /* check to see if TV DAC is enabled for another crtc and keep it enabled */ - if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON) - save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON; - else - save->crtc2_gen_cntl = 0; - - save->crtc2_gen_cntl |= (RADEON_CRTC2_EN - | (format << 8) - | RADEON_CRTC2_VSYNC_DIS - | RADEON_CRTC2_HSYNC_DIS - | RADEON_CRTC2_DISP_DIS - | ((mode->Flags & V_DBLSCAN) - ? RADEON_CRTC2_DBL_SCAN_EN - : 0) - | ((mode->Flags & V_CSYNC) - ? RADEON_CRTC2_CSYNC_EN - : 0) - | ((mode->Flags & V_INTERLACE) - ? RADEON_CRTC2_INTERLACE_EN - : 0)); - - save->disp2_merge_cntl = info->SavedReg->disp2_merge_cntl; - save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); - - save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; - save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid; - - if (info->ChipFamily == CHIP_FAMILY_RS400) { - save->rs480_unk_e30 = 0x105DC1CC; /* because I'm worth it */ - save->rs480_unk_e34 = 0x2749D000; /* AMD really should */ - save->rs480_unk_e38 = 0x29ca71dc; /* release docs */ - save->rs480_unk_e3c = 0x28FBC3AC; /* this is so a trade secret */ - } - - return TRUE; -} - - static CARD32 RADEONDiv(CARD64 n, CARD32 d) { return (n + (d / 2)) / d; @@ -716,333 +190,6 @@ RADEONComputePLL(RADEONPLLPtr pll, } -/* Define PLL registers for requested video mode */ -static void -RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - RADEONPLLPtr pll, DisplayModePtr mode, - int flags) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - CARD32 feedback_div = 0; - CARD32 reference_div = 0; - CARD32 post_divider = 0; - CARD32 freq = 0; - - struct { - int divider; - int bitvalue; - } *post_div, post_divs[] = { - /* From RAGE 128 VR/RAGE 128 GL Register - * Reference Manual (Technical Reference - * Manual P/N RRG-G04100-C Rev. 0.04), page - * 3-17 (PLL_DIV_[3:0]). - */ - { 1, 0 }, /* VCLK_SRC */ - { 2, 1 }, /* VCLK_SRC/2 */ - { 4, 2 }, /* VCLK_SRC/4 */ - { 8, 3 }, /* VCLK_SRC/8 */ - { 3, 4 }, /* VCLK_SRC/3 */ - { 16, 5 }, /* VCLK_SRC/16 */ - { 6, 6 }, /* VCLK_SRC/6 */ - { 12, 7 }, /* VCLK_SRC/12 */ - { 0, 0 } - }; - - - if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { - save->ppll_ref_div = info->RefDivider; - save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); - save->htotal_cntl = 0; - return; - } - - RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags); - - for (post_div = &post_divs[0]; post_div->divider; ++post_div) { - if (post_div->divider == post_divider) - break; - } - - if (!post_div->divider) { - save->pll_output_freq = freq; - post_div = &post_divs[0]; - } - - save->dot_clock_freq = freq; - save->feedback_div = feedback_div; - save->reference_div = reference_div; - save->post_div = post_divider; - - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n", - (unsigned)save->dot_clock_freq, - (unsigned)save->pll_output_freq, - save->feedback_div, - save->reference_div, - save->post_div); - - save->ppll_ref_div = save->reference_div; - -#if defined(__powerpc__) - /* apparently programming this otherwise causes a hang??? */ - if (info->MacModel == RADEON_MAC_IBOOK) - save->ppll_div_3 = 0x000600ad; - else -#endif - save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); - - save->htotal_cntl = mode->HTotal & 0x7; - - save->vclk_ecp_cntl = (info->SavedReg->vclk_ecp_cntl & - ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; -} - -/* Define PLL2 registers for requested video mode */ -static void -RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, - RADEONPLLPtr pll, DisplayModePtr mode, - int flags) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - CARD32 feedback_div = 0; - CARD32 reference_div = 0; - CARD32 post_divider = 0; - CARD32 freq = 0; - - struct { - int divider; - int bitvalue; - } *post_div, post_divs[] = { - /* From RAGE 128 VR/RAGE 128 GL Register - * Reference Manual (Technical Reference - * Manual P/N RRG-G04100-C Rev. 0.04), page - * 3-17 (PLL_DIV_[3:0]). - */ - { 1, 0 }, /* VCLK_SRC */ - { 2, 1 }, /* VCLK_SRC/2 */ - { 4, 2 }, /* VCLK_SRC/4 */ - { 8, 3 }, /* VCLK_SRC/8 */ - { 3, 4 }, /* VCLK_SRC/3 */ - { 6, 6 }, /* VCLK_SRC/6 */ - { 12, 7 }, /* VCLK_SRC/12 */ - { 0, 0 } - }; - - if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { - save->p2pll_ref_div = info->RefDivider; - save->p2pll_div_0 = info->FeedbackDivider | (info->PostDivider << 16); - save->htotal_cntl2 = 0; - return; - } - - RADEONComputePLL(pll, mode->Clock, &freq, &feedback_div, &reference_div, &post_divider, flags); - - for (post_div = &post_divs[0]; post_div->divider; ++post_div) { - if (post_div->divider == post_divider) - break; - } - - if (!post_div->divider) { - save->pll_output_freq_2 = freq; - post_div = &post_divs[0]; - } - - save->dot_clock_freq_2 = freq; - save->feedback_div_2 = feedback_div; - save->reference_div_2 = reference_div; - save->post_div_2 = post_divider; - - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - "dc=%u, of=%u, fd=%d, rd=%d, pd=%d\n", - (unsigned)save->dot_clock_freq_2, - (unsigned)save->pll_output_freq_2, - save->feedback_div_2, - save->reference_div_2, - save->post_div_2); - - save->p2pll_ref_div = save->reference_div_2; - - save->p2pll_div_0 = (save->feedback_div_2 | - (post_div->bitvalue << 16)); - - save->htotal_cntl2 = mode->HTotal & 0x7; - - save->pixclks_cntl = ((info->SavedReg->pixclks_cntl & - ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | - RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); -} - -static void -RADEONInitBIOSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - /* tell the bios not to muck with the hardware on events */ - save->bios_4_scratch = 0x4; /* 0x4 needed for backlight */ - save->bios_5_scratch = (info->SavedReg->bios_5_scratch & 0xff) | 0xff00; /* bits 0-3 keep backlight level */ - save->bios_6_scratch = info->SavedReg->bios_6_scratch | 0x40000000; - -} - -static void -radeon_update_tv_routing(ScrnInfoPtr pScrn, RADEONSavePtr restore) -{ - /* pixclks_cntl controls tv clock routing */ - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl); -} - -static void -legacy_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, - DisplayModePtr adjusted_mode, int x, int y) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; - RADEONInfoPtr info = RADEONPTR(pScrn); - Bool tilingOld = info->tilingEnabled; - int i = 0; - double dot_clock = 0; - int pll_flags = RADEON_PLL_LEGACY; - Bool update_tv_routing = FALSE; - - - if (info->allowColorTiling) { - info->tilingEnabled = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; -#ifdef XF86DRI - if (info->directRenderingEnabled && (info->tilingEnabled != tilingOld)) { - RADEONSAREAPrivPtr pSAREAPriv; - if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_SWITCH_TILING, (info->tilingEnabled ? 1 : 0)) < 0) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] failed changing tiling status\n"); - /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ - pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]); - info->tilingEnabled = pSAREAPriv->tiling_enabled ? TRUE : FALSE; - } -#endif - } - - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - RADEONOutputPrivatePtr radeon_output = output->driver_private; - - if (output->crtc == crtc) { - if (radeon_output->MonType != MT_CRT) - pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; - if (radeon_output->MonType == MT_LCD) - pll_flags |= (RADEON_PLL_USE_BIOS_DIVS | RADEON_PLL_USE_REF_DIV); - } - } - - if (info->IsMobility) - RADEONInitBIOSRegisters(pScrn, info->ModeReg); - - ErrorF("init memmap\n"); - RADEONInitMemMapRegisters(pScrn, info->ModeReg, info); - ErrorF("init common\n"); - RADEONInitCommonRegisters(info->ModeReg, info); - - RADEONInitSurfaceCntl(crtc, info->ModeReg); - - switch (radeon_crtc->crtc_id) { - case 0: - ErrorF("init crtc1\n"); - RADEONInitCrtcRegisters(crtc, info->ModeReg, adjusted_mode); - RADEONInitCrtcBase(crtc, info->ModeReg, x, y); - dot_clock = adjusted_mode->Clock / 1000.0; - if (dot_clock) { - ErrorF("init pll1\n"); - RADEONInitPLLRegisters(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags); - } else { - info->ModeReg->ppll_ref_div = info->SavedReg->ppll_ref_div; - info->ModeReg->ppll_div_3 = info->SavedReg->ppll_div_3; - info->ModeReg->htotal_cntl = info->SavedReg->htotal_cntl; - } - break; - case 1: - ErrorF("init crtc2\n"); - RADEONInitCrtc2Registers(crtc, info->ModeReg, adjusted_mode); - RADEONInitCrtc2Base(crtc, info->ModeReg, x, y); - dot_clock = adjusted_mode->Clock / 1000.0; - if (dot_clock) { - ErrorF("init pll2\n"); - RADEONInitPLL2Registers(pScrn, info->ModeReg, &info->pll, adjusted_mode, pll_flags); - } - break; - } - - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - RADEONOutputPrivatePtr radeon_output = output->driver_private; - - if (output->crtc == crtc) { - if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) { - switch (radeon_crtc->crtc_id) { - case 0: - RADEONAdjustCrtcRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); - RADEONAdjustPLLRegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); - update_tv_routing = TRUE; - break; - case 1: - RADEONAdjustCrtc2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); - RADEONAdjustPLL2RegistersForTV(pScrn, info->ModeReg, adjusted_mode, output); - break; - } - } - } - } - - if (info->IsMobility) - RADEONRestoreBIOSRegisters(pScrn, info->ModeReg); - - ErrorF("restore memmap\n"); - RADEONRestoreMemMapRegisters(pScrn, info->ModeReg); - ErrorF("restore common\n"); - RADEONRestoreCommonRegisters(pScrn, info->ModeReg); - - switch (radeon_crtc->crtc_id) { - case 0: - ErrorF("restore crtc1\n"); - RADEONRestoreCrtcRegisters(pScrn, info->ModeReg); - ErrorF("restore pll1\n"); - /*if (info->IsAtomBios) - atombios_crtc_set_pll(crtc, adjusted_mode); - else*/ - RADEONRestorePLLRegisters(pScrn, info->ModeReg); - break; - case 1: - ErrorF("restore crtc2\n"); - RADEONRestoreCrtc2Registers(pScrn, info->ModeReg); - ErrorF("restore pll2\n"); - /*if (info->IsAtomBios) - atombios_crtc_set_pll(crtc, adjusted_mode); - else*/ - RADEONRestorePLL2Registers(pScrn, info->ModeReg); - break; - } - - /* pixclks_cntl handles tv-out clock routing */ - if (update_tv_routing) - radeon_update_tv_routing(pScrn, info->ModeReg); - - if (info->DispPriority) - RADEONInitDispBandwidth(pScrn); - - if (info->tilingEnabled != tilingOld) { - /* need to redraw front buffer, I guess this can be considered a hack ? */ - /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ - if (pScrn->pScreen) - xf86EnableDisableFBAccess(pScrn->scrnIndex, FALSE); - RADEONChangeSurfaces(pScrn); - if (pScrn->pScreen) - xf86EnableDisableFBAccess(pScrn->scrnIndex, TRUE); - /* xf86SetRootClip would do, but can't access that here */ - } - - /* reset ecp_div for Xv */ - info->ecp_div = -1; - -} - static void radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode, int x, int y) @@ -1066,7 +213,8 @@ radeon_crtc_mode_commit(xf86CrtcPtr crtc) radeon_crtc_dpms(crtc, DPMSModeOn); } -void radeon_crtc_load_lut(xf86CrtcPtr crtc) +void +radeon_crtc_load_lut(xf86CrtcPtr crtc) { ScrnInfoPtr pScrn = crtc->scrn; RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; @@ -1499,3 +647,47 @@ RADEONCrtcFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode) return pMode; } +void +RADEONBlank(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + int o, c; + + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + for (o = 0; o < xf86_config->num_output; o++) { + output = xf86_config->output[o]; + if (output->crtc != crtc) + continue; + + output->funcs->dpms(output, DPMSModeOff); + } + crtc->funcs->dpms(crtc, DPMSModeOff); + } +} + +void +RADEONUnblank(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + int o, c; + + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + if(!crtc->enabled) + continue; + crtc->funcs->dpms(crtc, DPMSModeOn); + for (o = 0; o < xf86_config->num_output; o++) { + output = xf86_config->output[o]; + if (output->crtc != crtc) + continue; + + output->funcs->dpms(output, DPMSModeOn); + } + } +} + diff --git a/src/radeon_display.c b/src/radeon_display.c index 2043f248..1c529cfe 100644 --- a/src/radeon_display.c +++ b/src/radeon_display.c @@ -48,27 +48,6 @@ extern int getRADEONEntityIndex(void); -static const CARD32 default_tvdac_adj [CHIP_FAMILY_LAST] = -{ - 0x00000000, /* unknown */ - 0x00000000, /* legacy */ - 0x00000000, /* r100 */ - 0x00280000, /* rv100 */ - 0x00000000, /* rs100 */ - 0x00880000, /* rv200 */ - 0x00000000, /* rs200 */ - 0x00000000, /* r200 */ - 0x00770000, /* rv250 */ - 0x00290000, /* rs300 */ - 0x00560000, /* rv280 */ - 0x00780000, /* r300 */ - 0x00770000, /* r350 */ - 0x00780000, /* rv350 */ - 0x00780000, /* rv380 */ - 0x01080000, /* r420 */ - 0x01080000, /* rv410 */ /* FIXME: just values from r420 used... */ - 0x00780000, /* rs400 */ /* FIXME: just values from rv380 used... */ -}; void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) { @@ -157,722 +136,3 @@ void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) mon->nVrefresh = i; } } - -void RADEONGetTVDacAdjInfo(xf86OutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - - /* Todo: get this setting from BIOS */ - radeon_output->tv_dac_adj = default_tvdac_adj[info->ChipFamily]; - if (info->IsMobility) { /* some mobility chips may different */ - if (info->ChipFamily == CHIP_FAMILY_RV250) - radeon_output->tv_dac_adj = 0x00880000; - } -} - -/* - * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant). - * - */ -static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - if (IsPrimaryDAC) { - CARD32 dac_cntl; - CARD32 dac_macro_cntl = 0; - dac_cntl = INREG(RADEON_DAC_CNTL); - dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); - if (IsOn) { - dac_cntl &= ~RADEON_DAC_PDWN; - dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | - RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - } else { - dac_cntl |= RADEON_DAC_PDWN; - dac_macro_cntl |= (RADEON_DAC_PDWN_R | - RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - } - OUTREG(RADEON_DAC_CNTL, dac_cntl); - OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); - } else { - CARD32 tv_dac_cntl; - CARD32 fp2_gen_cntl; - - switch(info->ChipFamily) - { - case CHIP_FAMILY_R420: - case CHIP_FAMILY_RV410: - tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); - if (IsOn) { - tv_dac_cntl &= ~(R420_TV_DAC_RDACPD | - R420_TV_DAC_GDACPD | - R420_TV_DAC_BDACPD | - RADEON_TV_DAC_BGSLEEP); - } else { - tv_dac_cntl |= (R420_TV_DAC_RDACPD | - R420_TV_DAC_GDACPD | - R420_TV_DAC_BDACPD | - RADEON_TV_DAC_BGSLEEP); - } - OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); - break; - case CHIP_FAMILY_R200: - fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); - if (IsOn) { - fp2_gen_cntl |= RADEON_FP2_DVO_EN; - } else { - fp2_gen_cntl &= ~RADEON_FP2_DVO_EN; - } - OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); - break; - - default: - tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); - if (IsOn) { - tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | - RADEON_TV_DAC_GDACPD | - RADEON_TV_DAC_BDACPD | - RADEON_TV_DAC_BGSLEEP); - } else { - tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | - RADEON_TV_DAC_GDACPD | - RADEON_TV_DAC_BDACPD | - RADEON_TV_DAC_BGSLEEP); - } - OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); - break; - } - } -} - -/* disable all ouputs before enabling the ones we want */ -void RADEONDisableDisplays(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char * RADEONMMIO = info->MMIO; - unsigned long tmp, tmpPixclksCntl; - - - /* primary DAC */ - tmp = INREG(RADEON_CRTC_EXT_CNTL); - tmp &= ~RADEON_CRTC_CRT_ON; - OUTREG(RADEON_CRTC_EXT_CNTL, tmp); - RADEONDacPowerSet(pScrn, FALSE, TRUE); - - /* Secondary DAC */ - if (info->ChipFamily == CHIP_FAMILY_R200) { - tmp = INREG(RADEON_FP2_GEN_CNTL); - tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); - OUTREG(RADEON_FP2_GEN_CNTL, tmp); - } else { - tmp = INREG(RADEON_CRTC2_GEN_CNTL); - tmp &= ~RADEON_CRTC2_CRT2_ON; - OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); - } - RADEONDacPowerSet(pScrn, FALSE, FALSE); - - /* turn off tv-out */ - if (info->InternalTVOut) { - tmp = INREG(RADEON_TV_MASTER_CNTL); - tmp &= ~RADEON_TV_ON; - OUTREG(RADEON_TV_MASTER_CNTL, tmp); - } - - /* FP 1 */ - tmp = INREG(RADEON_FP_GEN_CNTL); - tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - OUTREG(RADEON_FP_GEN_CNTL, tmp); - - /* FP 2 */ - tmp = INREG(RADEON_FP2_GEN_CNTL); - tmp |= RADEON_FP2_BLANK_EN; - tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); - OUTREG(RADEON_FP2_GEN_CNTL, tmp); - - /* LVDS */ - if (info->IsMobility) { - tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - if (info->IsMobility || info->IsIGP) { - /* Asic bug, when turning off LVDS_ON, we have to make sure - RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off - */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); - } - tmp = INREG(RADEON_LVDS_GEN_CNTL); - tmp |= RADEON_LVDS_DISPLAY_DIS; - tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); - OUTREG(RADEON_LVDS_GEN_CNTL, tmp); - if (info->IsMobility || info->IsIGP) { - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); - } - } - -} - -/* This is to be used enable/disable displays dynamically */ -void RADEONEnableDisplay(xf86OutputPtr output, BOOL bEnable) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONSavePtr save = info->ModeReg; - unsigned char * RADEONMMIO = info->MMIO; - unsigned long tmp; - RADEONOutputPrivatePtr radeon_output; - int tv_dac_change = 0, o; - radeon_output = output->driver_private; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - - for (o = 0; o < xf86_config->num_output; o++) { - if (output == xf86_config->output[o]) { - break; - } - } - - if (bEnable) { - ErrorF("enable montype: %d\n", radeon_output->MonType); - if (radeon_output->MonType == MT_CRT) { - if (radeon_output->DACType == DAC_PRIMARY) { - info->output_crt1 |= (1 << o); - tmp = INREG(RADEON_CRTC_EXT_CNTL); - tmp |= RADEON_CRTC_CRT_ON; - OUTREG(RADEON_CRTC_EXT_CNTL, tmp); - save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; - RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); - } else if (radeon_output->DACType == DAC_TVDAC) { - info->output_crt2 |= (1 << o); - if (info->ChipFamily == CHIP_FAMILY_R200) { - tmp = INREG(RADEON_FP2_GEN_CNTL); - tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); - OUTREG(RADEON_FP2_GEN_CNTL, tmp); - save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); - } else { - tmp = INREG(RADEON_CRTC2_GEN_CNTL); - tmp |= RADEON_CRTC2_CRT2_ON; - OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); - save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; - } - tv_dac_change = 1; - } - } else if (radeon_output->MonType == MT_DFP) { - if (radeon_output->TMDSType == TMDS_INT) { - info->output_dfp1 |= (1 << o); - tmp = INREG(RADEON_FP_GEN_CNTL); - tmp |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); - OUTREG(RADEON_FP_GEN_CNTL, tmp); - save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); - } else if (radeon_output->TMDSType == TMDS_EXT) { - info->output_dfp2 |= (1 << o); - tmp = INREG(RADEON_FP2_GEN_CNTL); - tmp &= ~RADEON_FP2_BLANK_EN; - tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); - OUTREG(RADEON_FP2_GEN_CNTL, tmp); - save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); - save->fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN; - } - } else if (radeon_output->MonType == MT_LCD) { - info->output_lcd1 |= (1 << o); - tmp = INREG(RADEON_LVDS_GEN_CNTL); - tmp |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); - tmp &= ~(RADEON_LVDS_DISPLAY_DIS); - usleep (radeon_output->PanelPwrDly * 1000); - OUTREG(RADEON_LVDS_GEN_CNTL, tmp); - save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); - save->lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); - } else if (radeon_output->MonType == MT_STV || - radeon_output->MonType == MT_CTV) { - info->output_tv1 |= (1 << o); - tmp = INREG(RADEON_TV_MASTER_CNTL); - tmp |= RADEON_TV_ON; - OUTREG(RADEON_TV_MASTER_CNTL, tmp); - tv_dac_change = 2; - radeon_output->tv_on = TRUE; - } - } else { - ErrorF("disable montype: %d\n", radeon_output->MonType); - if (radeon_output->MonType == MT_CRT) { - if (radeon_output->DACType == DAC_PRIMARY) { - info->output_crt1 &= ~(1 << o); - if (!info->output_crt1) { - tmp = INREG(RADEON_CRTC_EXT_CNTL); - tmp &= ~RADEON_CRTC_CRT_ON; - OUTREG(RADEON_CRTC_EXT_CNTL, tmp); - save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; - RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); - } - } else if (radeon_output->DACType == DAC_TVDAC) { - info->output_crt2 &= ~(1 << o); - tv_dac_change = 1; - if (!info->output_crt2) { - if (info->ChipFamily == CHIP_FAMILY_R200) { - tmp = INREG(RADEON_FP2_GEN_CNTL); - tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); - OUTREG(RADEON_FP2_GEN_CNTL, tmp); - save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); - } else { - tmp = INREG(RADEON_CRTC2_GEN_CNTL); - tmp &= ~RADEON_CRTC2_CRT2_ON; - OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); - save->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; - } - } - } - } else if (radeon_output->MonType == MT_DFP) { - if (radeon_output->TMDSType == TMDS_INT) { - info->output_dfp1 &= ~(1 << o); - if (!info->output_dfp1) { - tmp = INREG(RADEON_FP_GEN_CNTL); - tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - OUTREG(RADEON_FP_GEN_CNTL, tmp); - save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - } - } else if (radeon_output->TMDSType == TMDS_EXT) { - info->output_dfp2 &= ~(1 << o); - if (!info->output_dfp2) { - tmp = INREG(RADEON_FP2_GEN_CNTL); - tmp |= RADEON_FP2_BLANK_EN; - tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); - OUTREG(RADEON_FP2_GEN_CNTL, tmp); - save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); - save->fp2_gen_cntl |= RADEON_FP2_BLANK_EN; - } - } - } else if (radeon_output->MonType == MT_LCD) { - info->output_lcd1 &= ~(1 << o); - if (!info->output_lcd1) { - unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - if (info->IsMobility || info->IsIGP) { - /* Asic bug, when turning off LVDS_ON, we have to make sure - RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off - */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); - } - tmp = INREG(RADEON_LVDS_GEN_CNTL); - tmp |= RADEON_LVDS_DISPLAY_DIS; - tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); - OUTREG(RADEON_LVDS_GEN_CNTL, tmp); - save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; - save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); - if (info->IsMobility || info->IsIGP) { - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); - } - } - } else if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) { - info->output_tv1 &= ~(1 << o); - tv_dac_change = 2; - if (!info->output_tv1) { - tmp = INREG(RADEON_TV_MASTER_CNTL); - tmp &= ~RADEON_TV_ON; - OUTREG(RADEON_TV_MASTER_CNTL, tmp); - radeon_output->tv_on = FALSE; - } - } - } - - if (tv_dac_change) { - if (bEnable) - info->tv_dac_enable_mask |= tv_dac_change; - else - info->tv_dac_enable_mask &= ~tv_dac_change; - - if (bEnable && info->tv_dac_enable_mask) - RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); - else if (!bEnable && info->tv_dac_enable_mask == 0) - RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); - - } -} - -/* Calculate display buffer watermark to prevent buffer underflow */ -void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2, DisplayModePtr mode1, DisplayModePtr mode2) -{ - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - CARD32 temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0; - float mem_tcas; - int k1, c; - CARD32 MemTrcdExtMemCntl[4] = {1, 2, 3, 4}; - CARD32 MemTrpExtMemCntl[4] = {1, 2, 3, 4}; - CARD32 MemTrasExtMemCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - - CARD32 MemTrcdMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - CARD32 MemTrpMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; - CARD32 MemTrasMemTimingCntl[16] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; - - float MemTcas[8] = {0, 1, 2, 3, 0, 1.5, 2.5, 0}; - float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7}; - float MemTrbs[8] = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5}; - - float mem_bw, peak_disp_bw; - float min_mem_eff = 0.8; - float sclk_eff, sclk_delay; - float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk; - float disp_latency, disp_latency_overhead, disp_drain_rate, disp_drain_rate2; - float pix_clk, pix_clk2; /* in MHz */ - int cur_size = 16; /* in octawords */ - int critical_point, critical_point2; - int stop_req, max_stop_req; - float read_return_rate, time_disp1_drop_priority; - - /* - * Set display0/1 priority up on r3/4xx in the memory controller for - * high res modes if the user specifies HIGH for displaypriority - * option. - */ - if ((info->DispPriority == 2) && IS_R300_VARIANT) { - CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); - if (pRADEONEnt->pCrtc[1]->enabled) { - mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ - } else { - mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ - } - OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); - } - - - /* R420 and RV410 family not supported yet */ - if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; - - /* - * Determine if there is enough bandwidth for current display mode - */ - mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1); - - pix_clk = mode1->Clock/1000.0; - if (mode2) - pix_clk2 = mode2->Clock/1000.0; - else - pix_clk2 = 0; - - peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes); - if (pixel_bytes2) - peak_disp_bw += (pix_clk2 * pixel_bytes2); - - if (peak_disp_bw >= mem_bw * min_mem_eff) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "You may not have enough display bandwidth for current mode\n" - "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); - } - - /* CRTC1 - Set GRPH_BUFFER_CNTL register using h/w defined optimal values. - GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] - */ - stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16; - - /* setup Max GRPH_STOP_REQ default value */ - if (IS_RV100_VARIANT) - max_stop_req = 0x5c; - else - max_stop_req = 0x7c; - if (stop_req > max_stop_req) - stop_req = max_stop_req; - - /* Get values from the EXT_MEM_CNTL register...converting its contents. */ - temp = INREG(RADEON_MEM_TIMING_CNTL); - if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ - mem_trcd = MemTrcdExtMemCntl[(temp & 0x0c) >> 2]; - mem_trp = MemTrpExtMemCntl[ (temp & 0x03) >> 0]; - mem_tras = MemTrasExtMemCntl[(temp & 0x70) >> 4]; - } else { /* RV200 and later */ - mem_trcd = MemTrcdMemTimingCntl[(temp & 0x07) >> 0]; - mem_trp = MemTrpMemTimingCntl[ (temp & 0x700) >> 8]; - mem_tras = MemTrasMemTimingCntl[(temp & 0xf000) >> 12]; - } - - /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ - temp = INREG(RADEON_MEM_SDRAM_MODE_REG); - data = (temp & (7<<20)) >> 20; - if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ - mem_tcas = MemTcas [data]; - } else { - mem_tcas = MemTcas2 [data]; - } - - if (IS_R300_VARIANT) { - - /* on the R300, Tcas is included in Trbs. - */ - temp = INREG(RADEON_MEM_CNTL); - data = (R300_MEM_NUM_CHANNELS_MASK & temp); - if (data == 1) { - if (R300_MEM_USE_CD_CH_ONLY & temp) { - temp = INREG(R300_MC_IND_INDEX); - temp &= ~R300_MC_IND_ADDR_MASK; - temp |= R300_MC_READ_CNTL_CD_mcind; - OUTREG(R300_MC_IND_INDEX, temp); - temp = INREG(R300_MC_IND_DATA); - data = (R300_MEM_RBS_POSITION_C_MASK & temp); - } else { - temp = INREG(R300_MC_READ_CNTL_AB); - data = (R300_MEM_RBS_POSITION_A_MASK & temp); - } - } else { - temp = INREG(R300_MC_READ_CNTL_AB); - data = (R300_MEM_RBS_POSITION_A_MASK & temp); - } - - mem_trbs = MemTrbs[data]; - mem_tcas += mem_trbs; - } - - if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ - /* DDR64 SCLK_EFF = SCLK for analysis */ - sclk_eff = info->sclk; - } else { -#ifdef XF86DRI - if (info->directRenderingEnabled) - sclk_eff = info->sclk - (info->agpMode * 50.0 / 3.0); - else -#endif - sclk_eff = info->sclk; - } - - /* Find the memory controller latency for the display client. - */ - if (IS_R300_VARIANT) { - /*not enough for R350 ???*/ - /* - if (!mode2) sclk_delay = 150; - else { - if (info->RamWidth == 256) sclk_delay = 87; - else sclk_delay = 97; - } - */ - sclk_delay = 250; - } else { - if ((info->ChipFamily == CHIP_FAMILY_RV100) || - info->IsIGP) { - if (info->IsDDR) sclk_delay = 41; - else sclk_delay = 33; - } else { - if (info->RamWidth == 128) sclk_delay = 57; - else sclk_delay = 41; - } - } - - mc_latency_sclk = sclk_delay / sclk_eff; - - if (info->IsDDR) { - if (info->RamWidth == 32) { - k1 = 40; - c = 3; - } else { - k1 = 20; - c = 1; - } - } else { - k1 = 40; - c = 3; - } - mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) / - info->mclk) + (4.0 / sclk_eff); - - /* - HW cursor time assuming worst case of full size colour cursor. - */ - cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk; - cur_latency_sclk = cur_size / sclk_eff; - - /* - Find the total latency for the display data. - */ - disp_latency_overhead = 8.0 / info->sclk; - mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk; - mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk; - disp_latency = MAX(mc_latency_mclk, mc_latency_sclk); - - /* - Find the drain rate of the display buffer. - */ - disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes); - if (pixel_bytes2) - disp_drain_rate2 = pix_clk2 / (16.0/pixel_bytes2); - else - disp_drain_rate2 = 0; - - /* - Find the critical point of the display buffer. - */ - critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5); - - /* ???? */ - /* - temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT; - if (critical_point < temp) critical_point = temp; - */ - if (info->DispPriority == 2) { - critical_point = 0; - } - - /* - The critical point should never be above max_stop_req-4. Setting - GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. - */ - if (max_stop_req - critical_point < 4) critical_point = 0; - - if (critical_point == 0 && mode2 && info->ChipFamily == CHIP_FAMILY_R300) { - /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ - critical_point = 0x10; - } - - temp = info->SavedReg->grph_buffer_cntl; - temp &= ~(RADEON_GRPH_STOP_REQ_MASK); - temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); - temp &= ~(RADEON_GRPH_START_REQ_MASK); - if ((info->ChipFamily == CHIP_FAMILY_R350) && - (stop_req > 0x15)) { - stop_req -= 0x10; - } - temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); - - temp |= RADEON_GRPH_BUFFER_SIZE; - temp &= ~(RADEON_GRPH_CRITICAL_CNTL | - RADEON_GRPH_CRITICAL_AT_SOF | - RADEON_GRPH_STOP_CNTL); - /* - Write the result into the register. - */ - OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | - (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); - - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - "GRPH_BUFFER_CNTL from %x to %x\n", - (unsigned int)info->SavedReg->grph_buffer_cntl, - (unsigned int)INREG(RADEON_GRPH_BUFFER_CNTL)); - - if (mode2) { - stop_req = mode2->HDisplay * pixel_bytes2 / 16; - - if (stop_req > max_stop_req) stop_req = max_stop_req; - - temp = info->SavedReg->grph2_buffer_cntl; - temp &= ~(RADEON_GRPH_STOP_REQ_MASK); - temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); - temp &= ~(RADEON_GRPH_START_REQ_MASK); - if ((info->ChipFamily == CHIP_FAMILY_R350) && - (stop_req > 0x15)) { - stop_req -= 0x10; - } - temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); - temp |= RADEON_GRPH_BUFFER_SIZE; - temp &= ~(RADEON_GRPH_CRITICAL_CNTL | - RADEON_GRPH_CRITICAL_AT_SOF | - RADEON_GRPH_STOP_CNTL); - - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200)) - critical_point2 = 0; - else { - read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128)); - time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate); - - critical_point2 = (CARD32)((disp_latency + time_disp1_drop_priority + - disp_latency) * disp_drain_rate2 + 0.5); - - if (info->DispPriority == 2) { - critical_point2 = 0; - } - - if (max_stop_req - critical_point2 < 4) critical_point2 = 0; - - } - - if (critical_point2 == 0 && info->ChipFamily == CHIP_FAMILY_R300) { - /* some R300 cards have problem with this set to 0 */ - critical_point2 = 0x10; - } - - OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | - (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); - - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - "GRPH2_BUFFER_CNTL from %x to %x\n", - (unsigned int)info->SavedReg->grph2_buffer_cntl, - (unsigned int)INREG(RADEON_GRPH2_BUFFER_CNTL)); - } -} - -void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - DisplayModePtr mode1, mode2; - int pixel_bytes2 = 0; - - if (info->IsPrimary || info->IsSecondary) - mode1 = &xf86_config->crtc[0]->mode; - else - mode1 = info->CurrentLayout.mode; - mode2 = NULL; - pixel_bytes2 = info->CurrentLayout.pixel_bytes; - - if (xf86_config->num_crtc == 2) { - pixel_bytes2 = 0; - mode2 = NULL; - - if (xf86_config->crtc[1]->enabled && xf86_config->crtc[0]->enabled) { - pixel_bytes2 = info->CurrentLayout.pixel_bytes; - mode1 = &xf86_config->crtc[0]->mode; - mode2 = &xf86_config->crtc[1]->mode; - } else if (xf86_config->crtc[0]->enabled) { - mode1 = &xf86_config->crtc[0]->mode; - } else if (xf86_config->crtc[1]->enabled) { - mode1 = &xf86_config->crtc[1]->mode; - } else - return; - } else { - if (xf86_config->crtc[0]->enabled) - mode1 = &xf86_config->crtc[0]->mode; - else - return; - } - - RADEONInitDispBandwidth2(pScrn, info, pixel_bytes2, mode1, mode2); -} - -void RADEONBlank(ScrnInfoPtr pScrn) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86OutputPtr output; - xf86CrtcPtr crtc; - int o, c; - - for (c = 0; c < xf86_config->num_crtc; c++) { - crtc = xf86_config->crtc[c]; - for (o = 0; o < xf86_config->num_output; o++) { - output = xf86_config->output[o]; - if (output->crtc != crtc) - continue; - - output->funcs->dpms(output, DPMSModeOff); - } - crtc->funcs->dpms(crtc, DPMSModeOff); - } -} - -void RADEONUnblank(ScrnInfoPtr pScrn) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86OutputPtr output; - xf86CrtcPtr crtc; - int o, c; - - for (c = 0; c < xf86_config->num_crtc; c++) { - crtc = xf86_config->crtc[c]; - if(!crtc->enabled) - continue; - crtc->funcs->dpms(crtc, DPMSModeOn); - for (o = 0; o < xf86_config->num_output; o++) { - output = xf86_config->output[o]; - if (output->crtc != crtc) - continue; - - output->funcs->dpms(output, DPMSModeOn); - } - } -} diff --git a/src/radeon_output.c b/src/radeon_output.c index 30a73abc..23469329 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -136,12 +136,31 @@ static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */ }; +static const CARD32 default_tvdac_adj [CHIP_FAMILY_LAST] = +{ + 0x00000000, /* unknown */ + 0x00000000, /* legacy */ + 0x00000000, /* r100 */ + 0x00280000, /* rv100 */ + 0x00000000, /* rs100 */ + 0x00880000, /* rv200 */ + 0x00000000, /* rs200 */ + 0x00000000, /* r200 */ + 0x00770000, /* rv250 */ + 0x00290000, /* rs300 */ + 0x00560000, /* rv280 */ + 0x00780000, /* r300 */ + 0x00770000, /* r350 */ + 0x00780000, /* rv350 */ + 0x00780000, /* rv380 */ + 0x01080000, /* r420 */ + 0x01080000, /* rv410 */ /* FIXME: just values from r420 used... */ + 0x00780000, /* rs400 */ /* FIXME: just values from rv380 used... */ +}; + + static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output); static void RADEONUpdatePanelSize(xf86OutputPtr output); -static RADEONMonitorType radeon_detect_tv(ScrnInfoPtr pScrn); -static RADEONMonitorType radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color); -static RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color); -static RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn); static void RADEONGetTMDSInfoFromTable(xf86OutputPtr output); #define AVIVO_I2C_DISABLE 0 #define AVIVO_I2C_ENABLE 1 @@ -150,102 +169,15 @@ static Bool AVIVOI2CDoLock(ScrnInfoPtr pScrn, int lock_state, int gpio); extern void atombios_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode); +extern void legacy_output_mode_set(xf86OutputPtr output, + DisplayModePtr mode, + DisplayModePtr adjusted_mode); extern void atombios_output_dpms(xf86OutputPtr output, int mode); +extern void legacy_output_dpms(xf86OutputPtr output, int mode); extern RADEONMonitorType atombios_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output); +extern RADEONMonitorType legacy_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output); extern int atombios_external_tmds_setup(xf86OutputPtr output, DisplayModePtr mode); -Bool -RADEONDVOReadByte(I2CDevPtr dvo, int addr, CARD8 *ch) -{ - if (!xf86I2CReadByte(dvo, addr, ch)) { - xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR, - "Unable to read from %s Slave %d.\n", - dvo->pI2CBus->BusName, dvo->SlaveAddr); - return FALSE; - } - return TRUE; -} - -Bool -RADEONDVOWriteByte(I2CDevPtr dvo, int addr, CARD8 ch) -{ - if (!xf86I2CWriteByte(dvo, addr, ch)) { - xf86DrvMsg(dvo->pI2CBus->scrnIndex, X_ERROR, - "Unable to write to %s Slave %d.\n", - dvo->pI2CBus->BusName, dvo->SlaveAddr); - return FALSE; - } - return TRUE; -} - -static I2CDevPtr -RADEONDVODeviceInit(I2CBusPtr b, I2CSlaveAddr addr) -{ - I2CDevPtr dvo; - - dvo = xcalloc(1, sizeof(I2CDevRec)); - if (dvo == NULL) - return NULL; - - dvo->DevName = "RADEON DVO Controller"; - dvo->SlaveAddr = addr; - dvo->pI2CBus = b; - dvo->StartTimeout = b->StartTimeout; - dvo->BitTimeout = b->BitTimeout; - dvo->AcknTimeout = b->AcknTimeout; - dvo->ByteTimeout = b->ByteTimeout; - - if (xf86I2CDevInit(dvo)) { - return dvo; - } - - xfree(dvo); - return NULL; -} - -void -RADEONRestoreDVOChip(ScrnInfoPtr pScrn, xf86OutputPtr output) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONOutputPrivatePtr radeon_output = output->driver_private; - - if (!radeon_output->DVOChip) - return; - - OUTREG(radeon_output->dvo_i2c_reg, INREG(radeon_output->dvo_i2c_reg) & - (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); - - if (!RADEONInitExtTMDSInfoFromBIOS(output)) { - if (radeon_output->DVOChip) { - switch(info->ext_tmds_chip) { - case RADEON_SIL_164: - RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x30); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x09, 0x00); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x0a, 0x90); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x0c, 0x89); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x3b); - break; -#if 0 - /* needs work see bug 10418 */ - case RADEON_SIL_1178: - RADEONDVOWriteByte(radeon_output->DVOChip, 0x0f, 0x44); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x0f, 0x4c); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x0e, 0x01); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x0a, 0x80); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x09, 0x30); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x0c, 0xc9); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x0d, 0x70); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x32); - RADEONDVOWriteByte(radeon_output->DVOChip, 0x08, 0x33); - break; -#endif - default: - break; - } - } - } -} void RADEONPrintPortMap(ScrnInfoPtr pScrn) { @@ -404,291 +336,6 @@ RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, xf86OutputPtr output) return MonType; } -#if 0 -static RADEONMonitorType -RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int bConnected = 0; - - /* the monitor either wasn't connected or it is a non-DDC CRT. - * try to probe it - */ - if(IsCrtDac) { - unsigned long ulOrigVCLK_ECP_CNTL; - unsigned long ulOrigDAC_CNTL; - unsigned long ulOrigDAC_MACRO_CNTL; - unsigned long ulOrigDAC_EXT_CNTL; - unsigned long ulOrigCRTC_EXT_CNTL; - unsigned long ulData; - unsigned long ulMask; - - ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - - ulData = ulOrigVCLK_ECP_CNTL; - ulData &= ~(RADEON_PIXCLK_ALWAYS_ONb - | RADEON_PIXCLK_DAC_ALWAYS_ONb); - ulMask = ~(RADEON_PIXCLK_ALWAYS_ONb - |RADEON_PIXCLK_DAC_ALWAYS_ONb); - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); - - ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL); - ulData = ulOrigCRTC_EXT_CNTL; - ulData |= RADEON_CRTC_CRT_ON; - OUTREG(RADEON_CRTC_EXT_CNTL, ulData); - - ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); - ulData = ulOrigDAC_EXT_CNTL; - ulData &= ~RADEON_DAC_FORCE_DATA_MASK; - ulData |= (RADEON_DAC_FORCE_BLANK_OFF_EN - |RADEON_DAC_FORCE_DATA_EN - |RADEON_DAC_FORCE_DATA_SEL_MASK); - if ((info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280)) - ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); - else - ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); - - OUTREG(RADEON_DAC_EXT_CNTL, ulData); - - /* turn on power so testing can go through */ - ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); - ulOrigDAC_CNTL &= ~RADEON_DAC_PDWN; - OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL); - - ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); - ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); - - /* Enable comparators and set DAC range to PS2 (VGA) output level */ - ulData = ulOrigDAC_CNTL; - ulData |= RADEON_DAC_CMP_EN; - ulData &= ~RADEON_DAC_RANGE_CNTL_MASK; - ulData |= 0x2; - OUTREG(RADEON_DAC_CNTL, ulData); - - /* Settle down */ - usleep(10000); - - /* Read comparators */ - ulData = INREG(RADEON_DAC_CNTL); - bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; - - /* Restore things */ - ulData = ulOrigVCLK_ECP_CNTL; - ulMask = 0xFFFFFFFFL; - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); - - OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); - OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); - OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); - - if (!bConnected) { - /* Power DAC down if CRT is not connected */ - ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); - ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); - - ulData = INREG(RADEON_DAC_CNTL); - ulData |= RADEON_DAC_PDWN; - OUTREG(RADEON_DAC_CNTL, ulData); - } - } else { /* TV DAC */ - - /* This doesn't seem to work reliably (maybe worse on some OEM cards), - for now we always return false. If one wants to connected a - non-DDC monitor on the DVI port when CRT port is also connected, - he will need to explicitly tell the driver in the config file - with Option MonitorLayout. - */ - bConnected = FALSE; - -#if 0 - if (info->ChipFamily == CHIP_FAMILY_R200) { - unsigned long ulOrigGPIO_MONID; - unsigned long ulOrigFP2_GEN_CNTL; - unsigned long ulOrigDISP_OUTPUT_CNTL; - unsigned long ulOrigCRTC2_GEN_CNTL; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_A; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_B; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_C; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_D; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_E; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_F; - unsigned long ulOrigCRTC2_H_TOTAL_DISP; - unsigned long ulOrigCRTC2_V_TOTAL_DISP; - unsigned long ulOrigCRTC2_H_SYNC_STRT_WID; - unsigned long ulOrigCRTC2_V_SYNC_STRT_WID; - unsigned long ulData, i; - - ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID); - ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL); - ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); - ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); - ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); - ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); - ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); - ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); - ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); - ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); - - ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP); - ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP); - ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); - ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); - - ulData = INREG(RADEON_GPIO_MONID); - ulData &= ~RADEON_GPIO_A_0; - OUTREG(RADEON_GPIO_MONID, ulData); - - OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c); - - OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012); - - OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); - - for (i = 0; i < 200; i++) { - ulData = INREG(RADEON_GPIO_MONID); - bConnected = (ulData & RADEON_GPIO_Y_0)?1:0; - if (!bConnected) break; - - usleep(1000); - } - - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F); - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID); - OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL); - OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); - OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); - OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); - } else { - unsigned long ulOrigPIXCLKSDATA; - unsigned long ulOrigTV_MASTER_CNTL; - unsigned long ulOrigTV_DAC_CNTL; - unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; - unsigned long ulOrigDAC_CNTL2; - unsigned long ulData; - unsigned long ulMask; - - ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - - ulData = ulOrigPIXCLKSDATA; - ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb - | RADEON_PIX2CLK_DAC_ALWAYS_ONb); - ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb - | RADEON_PIX2CLK_DAC_ALWAYS_ONb); - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); - - ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); - ulData = ulOrigTV_MASTER_CNTL; - ulData &= ~RADEON_TVCLK_ALWAYS_ONb; - OUTREG(RADEON_TV_MASTER_CNTL, ulData); - - ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); - ulData = ulOrigDAC_CNTL2; - ulData &= ~RADEON_DAC2_DAC2_CLK_SEL; - OUTREG(RADEON_DAC_CNTL2, ulData); - - ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); - - ulData = 0x00880213; - OUTREG(RADEON_TV_DAC_CNTL, ulData); - - ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); - - ulData = (RADEON_Y_RED_EN - | RADEON_C_GRN_EN - | RADEON_CMP_BLU_EN - | RADEON_RED_MX_FORCE_DAC_DATA - | RADEON_GRN_MX_FORCE_DAC_DATA - | RADEON_BLU_MX_FORCE_DAC_DATA); - if (IS_R300_VARIANT) - ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT; - else - ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT; - OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData); - - usleep(10000); - - ulData = INREG(RADEON_TV_DAC_CNTL); - bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; - - ulData = ulOrigPIXCLKSDATA; - ulMask = 0xFFFFFFFFL; - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); - - OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); - OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); - OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); - OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); - } -#endif - return MT_UNKNOWN; - } - - return(bConnected ? MT_CRT : MT_NONE); -} -#endif - -static RADEONMonitorType -legacy_dac_detect(ScrnInfoPtr pScrn, xf86OutputPtr output) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - RADEONMonitorType found = MT_NONE; - - if (OUTPUT_IS_TV) { - if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_TVOUT, FALSE)) { - if (radeon_output->type == OUTPUT_STV) - radeon_output->MonType = MT_STV; - else - radeon_output->MonType = MT_CTV; - } else { - if (info->InternalTVOut) { - if (radeon_output->load_detection) - radeon_output->MonType = radeon_detect_tv(pScrn); - else - radeon_output->MonType = MT_NONE; - } - } - } else { - if (radeon_output->DACType == DAC_PRIMARY) { - if (radeon_output->load_detection) - found = radeon_detect_primary_dac(pScrn, TRUE); - } else if (radeon_output->DACType == DAC_TVDAC) { - if (radeon_output->load_detection) { - if (info->ChipFamily == CHIP_FAMILY_R200) - found = radeon_detect_ext_dac(pScrn); - else - found = radeon_detect_tv_dac(pScrn, TRUE); - } else - found = MT_NONE; - } - } - - return found; -} /* Primary Head (DVI or Laptop Int. panel)*/ /* A ddc capable display connected on DVI port */ @@ -818,23 +465,12 @@ static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr static void radeon_dpms(xf86OutputPtr output, int mode) { - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONInfoPtr info = RADEONPTR(output->scrn); if (IS_AVIVO_VARIANT) { atombios_output_dpms(output, mode); - return; - } - - switch(mode) { - case DPMSModeOn: - RADEONEnableDisplay(output, TRUE); - break; - case DPMSModeOff: - case DPMSModeSuspend: - case DPMSModeStandby: - RADEONEnableDisplay(output, FALSE); - break; + } else { + legacy_output_dpms(output, mode); } } @@ -941,402 +577,16 @@ radeon_mode_prepare(xf86OutputPtr output) { } -static void RADEONInitFPRegisters(xf86OutputPtr output, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - int i; - CARD32 tmp = info->SavedReg->tmds_pll_cntl & 0xfffff; - - for (i=0; i<4; i++) { - if (radeon_output->tmds_pll[i].freq == 0) break; - if ((CARD32)(mode->Clock/10) < radeon_output->tmds_pll[i].freq) { - tmp = radeon_output->tmds_pll[i].value ; - break; - } - } - - if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) { - if (tmp & 0xfff00000) - save->tmds_pll_cntl = tmp; - else { - save->tmds_pll_cntl = info->SavedReg->tmds_pll_cntl & 0xfff00000; - save->tmds_pll_cntl |= tmp; - } - } else save->tmds_pll_cntl = tmp; - - save->tmds_transmitter_cntl = info->SavedReg->tmds_transmitter_cntl & - ~(RADEON_TMDS_TRANSMITTER_PLLRST); - - if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !pRADEONEnt->HasCRTC2) - save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); - else /* weird, RV chips got this bit reversed? */ - save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); - - save->fp_gen_cntl = info->SavedReg->fp_gen_cntl | - (RADEON_FP_CRTC_DONT_SHADOW_VPAR | - RADEON_FP_CRTC_DONT_SHADOW_HEND ); - - save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - - if (pScrn->rgbBits == 8) - save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ - else - save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ - - - if (IsPrimary) { - if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { - save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; - if (mode->Flags & RADEON_USE_RMX) - save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; - else - save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; - } else - save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1; - } else { - if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { - save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; - save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; - } else - save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2; - } - -} - -static void RADEONInitFP2Registers(xf86OutputPtr output, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - - - if (pScrn->rgbBits == 8) - save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl | - RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ - else - save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl & - ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ - - save->fp2_gen_cntl &= ~(RADEON_FP2_ON | - RADEON_FP2_DVO_EN | - RADEON_FP2_DVO_RATE_SEL_SDR); - - - /* XXX: these may be oem specific */ - if (IS_R300_VARIANT) { - save->fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE; -#if 0 - if (mode->Clock > 165000) - save->fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN; -#endif - } - - if (IsPrimary) { - if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { - save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; - if (mode->Flags & RADEON_USE_RMX) - save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; - } else { - save->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2; - } - } else { - if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { - save->fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; - save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; - } else { - save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; - } - } - -} - -static void RADEONInitLVDSRegisters(xf86OutputPtr output, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - - save->lvds_pll_cntl = (info->SavedReg->lvds_pll_cntl | - RADEON_LVDS_PLL_EN); - - save->lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; - - save->lvds_gen_cntl = info->SavedReg->lvds_gen_cntl; - save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; - save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | - RADEON_LVDS_BLON | - RADEON_LVDS_EN | - RADEON_LVDS_RST_FM); - - if (IS_R300_VARIANT) - save->lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK); - - if (IsPrimary) { - if (IS_R300_VARIANT) { - if (mode->Flags & RADEON_USE_RMX) - save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX; - } else - save->lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; - } else { - if (IS_R300_VARIANT) { - save->lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2; - } else - save->lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2; - } - -} - -static void RADEONInitRMXRegisters(xf86OutputPtr output, RADEONSavePtr save, - DisplayModePtr mode) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - int xres = mode->HDisplay; - int yres = mode->VDisplay; - float Hratio, Vratio; - - save->fp_vert_stretch = info->SavedReg->fp_vert_stretch & - RADEON_VERT_STRETCH_RESERVED; - save->fp_horz_stretch = info->SavedReg->fp_horz_stretch & - (RADEON_HORZ_FP_LOOP_STRETCH | - RADEON_HORZ_AUTO_RATIO_INC); - - if (radeon_output->MonType != MT_LCD && radeon_output->MonType != MT_DFP) - return; - - if (radeon_output->PanelXRes == 0 || radeon_output->PanelYRes == 0) { - Hratio = 1.0; - Vratio = 1.0; - } else { - if (xres > radeon_output->PanelXRes) xres = radeon_output->PanelXRes; - if (yres > radeon_output->PanelYRes) yres = radeon_output->PanelYRes; - - Hratio = (float)xres/(float)radeon_output->PanelXRes; - Vratio = (float)yres/(float)radeon_output->PanelYRes; - } - - if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { - save->fp_horz_stretch |= ((xres/8-1)<<16); - } else { - save->fp_horz_stretch |= ((((unsigned long) - (Hratio * RADEON_HORZ_STRETCH_RATIO_MAX)) & - RADEON_HORZ_STRETCH_RATIO_MASK) | - RADEON_HORZ_STRETCH_BLEND | - RADEON_HORZ_STRETCH_ENABLE | - ((radeon_output->PanelXRes/8-1)<<16)); - } - - if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { - save->fp_vert_stretch |= ((yres-1)<<12); - } else { - save->fp_vert_stretch |= ((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX)) & - RADEON_VERT_STRETCH_RATIO_MASK) | - RADEON_VERT_STRETCH_ENABLE | - RADEON_VERT_STRETCH_BLEND | - ((radeon_output->PanelYRes-1)<<12)); - } - -} - -static void RADEONInitDACRegisters(xf86OutputPtr output, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (IsPrimary) { - if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { - save->disp_output_cntl = info->SavedReg->disp_output_cntl & - ~RADEON_DISP_DAC_SOURCE_MASK; - } else { - save->dac2_cntl = info->SavedReg->dac2_cntl & ~(RADEON_DAC2_DAC_CLK_SEL); - } - } else { - if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { - save->disp_output_cntl = info->SavedReg->disp_output_cntl & - ~RADEON_DISP_DAC_SOURCE_MASK; - save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; - } else { - save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC_CLK_SEL; - } - } - save->dac_cntl = (RADEON_DAC_MASK_ALL - | RADEON_DAC_VGA_ADR_EN - | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN)); - - save->dac_macro_cntl = info->SavedReg->dac_macro_cntl; -} - -static void -RADEONInitTvDacCntl(xf86OutputPtr output, RADEONSavePtr save) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - - if (info->ChipFamily == CHIP_FAMILY_R420 || - info->ChipFamily == CHIP_FAMILY_RV410) { - save->tv_dac_cntl = info->SavedReg->tv_dac_cntl & - ~(RADEON_TV_DAC_STD_MASK | - RADEON_TV_DAC_BGADJ_MASK | - R420_TV_DAC_DACADJ_MASK | - R420_TV_DAC_RDACPD | - R420_TV_DAC_GDACPD | - R420_TV_DAC_GDACPD | - R420_TV_DAC_TVENABLE); - } else { - save->tv_dac_cntl = info->SavedReg->tv_dac_cntl & - ~(RADEON_TV_DAC_STD_MASK | - RADEON_TV_DAC_BGADJ_MASK | - RADEON_TV_DAC_DACADJ_MASK | - RADEON_TV_DAC_RDACPD | - RADEON_TV_DAC_GDACPD | - RADEON_TV_DAC_GDACPD); - } - - save->tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | - RADEON_TV_DAC_NHOLD | - RADEON_TV_DAC_STD_PS2 | - radeon_output->tv_dac_adj); - -} - -static void RADEONInitDAC2Registers(xf86OutputPtr output, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - - /*0x0028023;*/ - RADEONInitTvDacCntl(output, save); - - if (IS_R300_VARIANT) - save->gpiopad_a = info->SavedReg->gpiopad_a | 1; - - save->dac2_cntl = info->SavedReg->dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; - - if (IsPrimary) { - if (IS_R300_VARIANT) { - save->disp_output_cntl = info->SavedReg->disp_output_cntl & - ~RADEON_DISP_TVDAC_SOURCE_MASK; - save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; - } else if (info->ChipFamily == CHIP_FAMILY_R200) { - save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl & - ~(R200_FP2_SOURCE_SEL_MASK | - RADEON_FP2_DVO_RATE_SEL_SDR); - } else { - save->disp_hw_debug = info->SavedReg->disp_hw_debug | RADEON_CRT2_DISP1_SEL; - } - } else { - if (IS_R300_VARIANT) { - save->disp_output_cntl = info->SavedReg->disp_output_cntl & - ~RADEON_DISP_TVDAC_SOURCE_MASK; - save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; - } else if (info->ChipFamily == CHIP_FAMILY_R200) { - save->fp2_gen_cntl = info->SavedReg->fp2_gen_cntl & - ~(R200_FP2_SOURCE_SEL_MASK | - RADEON_FP2_DVO_RATE_SEL_SDR); - save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; - } else { - save->disp_hw_debug = info->SavedReg->disp_hw_debug & - ~RADEON_CRT2_DISP1_SEL; - } - } -} - -static void -RADEONInitOutputRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, xf86OutputPtr output, - int crtc_num) -{ - Bool IsPrimary = crtc_num == 0 ? TRUE : FALSE; - RADEONOutputPrivatePtr radeon_output = output->driver_private; - - if (crtc_num == 0) - RADEONInitRMXRegisters(output, save, mode); - - if (radeon_output->MonType == MT_CRT) { - if (radeon_output->DACType == DAC_PRIMARY) { - RADEONInitDACRegisters(output, save, mode, IsPrimary); - } else { - RADEONInitDAC2Registers(output, save, mode, IsPrimary); - } - } else if (radeon_output->MonType == MT_LCD) { - RADEONInitLVDSRegisters(output, save, mode, IsPrimary); - } else if (radeon_output->MonType == MT_DFP) { - if (radeon_output->TMDSType == TMDS_INT) { - RADEONInitFPRegisters(output, save, mode, IsPrimary); - } else { - RADEONInitFP2Registers(output, save, mode, IsPrimary); - } - } else if (radeon_output->MonType == MT_STV || - radeon_output->MonType == MT_CTV) { - RADEONInitTVRegisters(output, save, mode, IsPrimary); - } -} - -static void -legacy_mode_set(xf86OutputPtr output, DisplayModePtr mode, - DisplayModePtr adjusted_mode) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - xf86CrtcPtr crtc = output->crtc; - RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; - - RADEONInitOutputRegisters(pScrn, info->ModeReg, adjusted_mode, output, radeon_crtc->crtc_id); - - if (radeon_crtc->crtc_id == 0) - RADEONRestoreRMXRegisters(pScrn, info->ModeReg); - - switch(radeon_output->MonType) { - case MT_LCD: - ErrorF("restore LVDS\n"); - RADEONRestoreLVDSRegisters(pScrn, info->ModeReg); - break; - case MT_DFP: - if (radeon_output->TMDSType == TMDS_INT) { - ErrorF("restore FP\n"); - RADEONRestoreFPRegisters(pScrn, info->ModeReg); - } else { - ErrorF("restore FP2\n"); - if (info->IsAtomBios) - atombios_external_tmds_setup(output, mode); - else - RADEONRestoreDVOChip(pScrn, output); - RADEONRestoreFP2Registers(pScrn, info->ModeReg); - } - break; - case MT_STV: - case MT_CTV: - ErrorF("restore tv\n"); - RADEONRestoreDACRegisters(pScrn, info->ModeReg); - RADEONRestoreTVRegisters(pScrn, info->ModeReg); - break; - default: - ErrorF("restore dac\n"); - RADEONRestoreDACRegisters(pScrn, info->ModeReg); - } - -} - static void radeon_mode_set(xf86OutputPtr output, DisplayModePtr mode, - DisplayModePtr adjusted_mode) + DisplayModePtr adjusted_mode) { - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONInfoPtr info = RADEONPTR(output->scrn); if (IS_AVIVO_VARIANT) atombios_output_mode_set(output, mode, adjusted_mode); else - legacy_mode_set(output, mode, adjusted_mode); + legacy_output_mode_set(output, mode, adjusted_mode); } @@ -1346,423 +596,6 @@ radeon_mode_commit(xf86OutputPtr output) radeon_dpms(output, DPMSModeOn); } -/* the following functions are based on the load detection code - * in the beos radeon driver by Thomas Kurschel and the existing - * load detection code in this driver. - */ -static RADEONMonitorType -radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - CARD32 vclk_ecp_cntl, crtc_ext_cntl; - CARD32 dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp; - RADEONMonitorType found = MT_NONE; - - /* save the regs we need */ - vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); - dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); - dac_cntl = INREG(RADEON_DAC_CNTL); - dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); - - tmp = vclk_ecp_cntl & - ~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb); - OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); - - tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; - OUTREG(RADEON_CRTC_EXT_CNTL, tmp); - - tmp = RADEON_DAC_FORCE_BLANK_OFF_EN | - RADEON_DAC_FORCE_DATA_EN; - - if (color) - tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; - else - tmp |= RADEON_DAC_FORCE_DATA_SEL_G; - - if (IS_R300_VARIANT) - tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); - else - tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); - - OUTREG(RADEON_DAC_EXT_CNTL, tmp); - - tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN); - tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; - OUTREG(RADEON_DAC_CNTL, tmp); - - tmp &= ~(RADEON_DAC_PDWN_R | - RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - - OUTREG(RADEON_DAC_MACRO_CNTL, tmp); - - usleep(2000); - - if (INREG(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) { - found = MT_CRT; - xf86DrvMsg (pScrn->scrnIndex, X_INFO, - "Found %s CRT connected to primary DAC\n", - color ? "color" : "bw"); - } - - /* restore the regs we used */ - OUTREG(RADEON_DAC_CNTL, dac_cntl); - OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); - OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); - OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); - OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl); - - return found; -} - -static RADEONMonitorType -radeon_detect_ext_dac(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - CARD32 gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; - CARD32 disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; - CARD32 disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; - CARD32 tmp, crtc2_h_total_disp, crtc2_v_total_disp; - CARD32 crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; - RADEONMonitorType found = MT_NONE; - int connected = 0; - int i = 0; - - /* save the regs we need */ - gpio_monid = INREG(RADEON_GPIO_MONID); - fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); - disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); - crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); - disp_lin_trans_grph_a = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); - disp_lin_trans_grph_b = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); - disp_lin_trans_grph_c = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); - disp_lin_trans_grph_d = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); - disp_lin_trans_grph_e = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); - disp_lin_trans_grph_f = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); - crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP); - crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP); - crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); - crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); - - tmp = INREG(RADEON_GPIO_MONID); - tmp &= ~RADEON_GPIO_A_0; - OUTREG(RADEON_GPIO_MONID, tmp); - - OUTREG(RADEON_FP2_GEN_CNTL, - RADEON_FP2_ON | - RADEON_FP2_PANEL_FORMAT | - R200_FP2_SOURCE_SEL_TRANS_UNIT | - RADEON_FP2_DVO_EN | - R200_FP2_DVO_RATE_SEL_SDR); - - OUTREG(RADEON_DISP_OUTPUT_CNTL, - RADEON_DISP_DAC_SOURCE_RMX | - RADEON_DISP_TRANS_MATRIX_GRAPHICS); - - OUTREG(RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_EN | - RADEON_CRTC2_DISP_REQ_EN_B); - - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); - - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); - - for (i = 0; i < 200; i++) { - tmp = INREG(RADEON_GPIO_MONID); - if (tmp & RADEON_GPIO_Y_0) - connected = 1; - else - connected = 0; - - if (!connected) - break; - - usleep(1000); - } - - if (connected) - found = MT_CRT; - - /* restore the regs we used */ - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); - OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); - OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); - OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); - OUTREG(RADEON_GPIO_MONID, gpio_monid); - - return found; -} - -static RADEONMonitorType -radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - CARD32 crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; - CARD32 disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; - RADEONMonitorType found = MT_NONE; - - /* save the regs we need */ - pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - gpiopad_a = IS_R300_VARIANT ? INREG(RADEON_GPIOPAD_A) : 0; - disp_output_cntl = IS_R300_VARIANT ? INREG(RADEON_DISP_OUTPUT_CNTL) : 0; - disp_hw_debug = !IS_R300_VARIANT ? INREG(RADEON_DISP_HW_DEBUG) : 0; - crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); - tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); - dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); - dac_cntl2 = INREG(RADEON_DAC_CNTL2); - - tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb - | RADEON_PIX2CLK_DAC_ALWAYS_ONb); - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); - - if (IS_R300_VARIANT) { - OUTREGP(RADEON_GPIOPAD_A, 1, ~1 ); - } - - tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; - tmp |= RADEON_CRTC2_CRT2_ON | - (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); - - OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); - - if (IS_R300_VARIANT) { - tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; - tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; - OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp); - } else { - tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; - OUTREG(RADEON_DISP_HW_DEBUG, tmp); - } - - tmp = RADEON_TV_DAC_NBLANK | - RADEON_TV_DAC_NHOLD | - RADEON_TV_MONITOR_DETECT_EN | - RADEON_TV_DAC_STD_PS2; - - OUTREG(RADEON_TV_DAC_CNTL, tmp); - - tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN | - RADEON_DAC2_FORCE_DATA_EN; - - if (color) - tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; - else - tmp |= RADEON_DAC_FORCE_DATA_SEL_G; - - if (IS_R300_VARIANT) - tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); - else - tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); - - OUTREG(RADEON_DAC_EXT_CNTL, tmp); - - tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN; - OUTREG(RADEON_DAC_CNTL2, tmp); - - usleep(10000); - - if (IS_R300_VARIANT) { - if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) { - found = MT_CRT; - xf86DrvMsg (pScrn->scrnIndex, X_INFO, - "Found %s CRT connected to TV DAC\n", - color ? "color" : "bw"); - } - } else { - if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) { - found = MT_CRT; - xf86DrvMsg (pScrn->scrnIndex, X_INFO, - "Found %s CRT connected to TV DAC\n", - color ? "color" : "bw"); - } - } - - /* restore regs we used */ - OUTREG(RADEON_DAC_CNTL2, dac_cntl2); - OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); - OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); - OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); - - if (IS_R300_VARIANT) { - OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); - OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1 ); - } else { - OUTREG(RADEON_DISP_HW_DEBUG, disp_hw_debug); - } - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, pixclks_cntl); - - return found; -} - -static RADEONMonitorType -r300_detect_tv(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - CARD32 tmp, dac_cntl2, crtc2_gen_cntl, dac_ext_cntl, tv_dac_cntl; - CARD32 gpiopad_a, disp_output_cntl; - RADEONMonitorType found = MT_NONE; - - /* save the regs we need */ - gpiopad_a = INREG(RADEON_GPIOPAD_A); - dac_cntl2 = INREG(RADEON_DAC_CNTL2); - crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); - dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); - tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); - disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); - - OUTREGP(RADEON_GPIOPAD_A, 0, ~1 ); - - OUTREG(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL ); - - OUTREG(RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT ); - - tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; - tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; - OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp); - - OUTREG(RADEON_DAC_EXT_CNTL, - RADEON_DAC2_FORCE_BLANK_OFF_EN | - RADEON_DAC2_FORCE_DATA_EN | - RADEON_DAC_FORCE_DATA_SEL_RGB | - (0xec << RADEON_DAC_FORCE_DATA_SHIFT )); - - OUTREG(RADEON_TV_DAC_CNTL, - RADEON_TV_DAC_STD_NTSC | - (8 << RADEON_TV_DAC_BGADJ_SHIFT) | - (6 << RADEON_TV_DAC_DACADJ_SHIFT )); - - INREG(RADEON_TV_DAC_CNTL); - - usleep(4000); - - OUTREG(RADEON_TV_DAC_CNTL, - RADEON_TV_DAC_NBLANK | - RADEON_TV_DAC_NHOLD | - RADEON_TV_MONITOR_DETECT_EN | - RADEON_TV_DAC_STD_NTSC | - (8 << RADEON_TV_DAC_BGADJ_SHIFT) | - (6 << RADEON_TV_DAC_DACADJ_SHIFT )); - - INREG(RADEON_TV_DAC_CNTL); - - usleep(6000); - - tmp = INREG(RADEON_TV_DAC_CNTL); - if ( (tmp & RADEON_TV_DAC_GDACDET) != 0 ) { - found = MT_STV; - xf86DrvMsg (pScrn->scrnIndex, X_INFO, - "S-Video TV connection detected\n"); - } else if ( (tmp & RADEON_TV_DAC_BDACDET) != 0 ) { - found = MT_CTV; - xf86DrvMsg (pScrn->scrnIndex, X_INFO, - "Composite TV connection detected\n" ); - } - - OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl ); - OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); - OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); - OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); - OUTREG(RADEON_DAC_CNTL2, dac_cntl2); - OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1); - - return found; -} - -static RADEONMonitorType -radeon_detect_tv(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - CARD32 tmp, dac_cntl2, tv_master_cntl; - CARD32 tv_dac_cntl, tv_pre_dac_mux_cntl, config_cntl; - RADEONMonitorType found = MT_NONE; - - if (IS_R300_VARIANT) - return r300_detect_tv(pScrn); - - /* save the regs we need */ - dac_cntl2 = INREG(RADEON_DAC_CNTL2); - tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL); - tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); - config_cntl = INREG(RADEON_CONFIG_CNTL); - tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); - - tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL; - OUTREG(RADEON_DAC_CNTL2, tmp); - - tmp = tv_master_cntl | RADEON_TV_ON; - tmp &= ~(RADEON_TV_ASYNC_RST | - RADEON_RESTART_PHASE_FIX | - RADEON_CRT_FIFO_CE_EN | - RADEON_TV_FIFO_CE_EN | - RADEON_RE_SYNC_NOW_SEL_MASK); - tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST; - - OUTREG(RADEON_TV_MASTER_CNTL, tmp); - - tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | - RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC | - (8 << RADEON_TV_DAC_BGADJ_SHIFT); - - if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK) - tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT); - else - tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT); - - OUTREG(RADEON_TV_DAC_CNTL, tmp); - - tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN | - RADEON_RED_MX_FORCE_DAC_DATA | - RADEON_GRN_MX_FORCE_DAC_DATA | - RADEON_BLU_MX_FORCE_DAC_DATA | - (0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT); - - OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tmp); - - usleep(3000); - - tmp = INREG(RADEON_TV_DAC_CNTL); - if (tmp & RADEON_TV_DAC_GDACDET) { - found = MT_STV; - xf86DrvMsg (pScrn->scrnIndex, X_INFO, - "S-Video TV connection detected\n"); - } else if (tmp & RADEON_TV_DAC_BDACDET) { - found = MT_CTV; - xf86DrvMsg (pScrn->scrnIndex, X_INFO, - "Composite TV connection detected\n" ); - } - - OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl); - OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); - OUTREG(RADEON_TV_MASTER_CNTL, tv_master_cntl); - OUTREG(RADEON_DAC_CNTL2, dac_cntl2); - - return found; -} - static xf86OutputStatus radeon_detect(xf86OutputPtr output) { @@ -1851,7 +684,7 @@ radeon_get_modes(xf86OutputPtr output) static void radeon_destroy (xf86OutputPtr output) { - if(output->driver_private) + if (output->driver_private) xfree(output->driver_private); } @@ -2813,6 +1646,21 @@ RADEONGetTVInfo(xf86OutputPtr output) } +static void +RADEONGetTVDacAdjInfo(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + /* Todo: get this setting from BIOS */ + radeon_output->tv_dac_adj = default_tvdac_adj[info->ChipFamily]; + if (info->IsMobility) { /* some mobility chips may different */ + if (info->ChipFamily == CHIP_FAMILY_RV250) + radeon_output->tv_dac_adj = 0x00880000; + } +} + void RADEONInitConnector(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; |