summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alex@botch2.(none)>2007-12-21 15:29:47 -0500
committerAlex Deucher <alex@botch2.(none)>2007-12-21 15:29:47 -0500
commitbf14aa5f88fc3b4e69d71db5b23248b8bb2018d0 (patch)
treee65ead0dee43be5433d9a6f328dcf632317157dc
parentbe7f8fd338f5af8b632f16a83db41e15d00af469 (diff)
RADEON: re-org legacy crtc/output code into separate files
-rw-r--r--src/Makefile.am3
-rw-r--r--src/legacy_crtc.c1268
-rw-r--r--src/legacy_output.c1577
-rw-r--r--src/radeon.h3
-rw-r--r--src/radeon_crtc.c916
-rw-r--r--src/radeon_display.c740
-rw-r--r--src/radeon_output.c1252
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;