diff options
author | Alex Deucher <alex@t41p.hsd1.va.comcast.net> | 2007-05-13 15:43:39 -0400 |
---|---|---|
committer | Alex Deucher <alex@t41p.hsd1.va.comcast.net> | 2007-05-13 15:43:39 -0400 |
commit | e776fa9ecc53d63f916a5447a76fb2bb3b824167 (patch) | |
tree | 82b341b73107f1d79ce2bb65af2c0be196a02aeb | |
parent | 58ce388452b7bc790c438d75c9cf4a0f69f0d7b2 (diff) |
RADEON: re-org randr code
- move crtc stuff to radeon_crtc.c
- move output stuff to radeon_output.c
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/radeon_crtc.c | 446 | ||||
-rw-r--r-- | src/radeon_display.c | 1000 | ||||
-rw-r--r-- | src/radeon_output.c | 641 |
4 files changed, 1096 insertions, 994 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 55a0f2a..bdc2979 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -80,7 +80,8 @@ 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_modes.c $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) + radeon_crtc.c radeon_output.c radeon_modes.c \ + $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) theatre_detect_drv_la_LTLIBRARIES = theatre_detect_drv.la theatre_detect_drv_la_LDFLAGS = -module -avoid-version diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c new file mode 100644 index 0000000..1047dcf --- /dev/null +++ b/src/radeon_crtc.c @@ -0,0 +1,446 @@ +/* + * 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 "fbdevhw.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" + +void radeon_crtc_load_lut(xf86CrtcPtr crtc); + +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; + + mask = radeon_crtc->crtc_id ? (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS) : (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_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_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_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_EXT_CNTL, mask, ~mask); + } + break; + } + + if (mode != DPMSModeOff) + radeon_crtc_load_lut(crtc); +} + +static Bool +radeon_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +static void +radeon_crtc_mode_prepare(xf86CrtcPtr crtc) +{ + radeon_crtc_dpms(crtc, DPMSModeOff); +} + +static void +radeon_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); + RADEONMonitorType montype; + int i = 0; + double dot_clock = 0; + + 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) { + montype = radeon_output->MonType; + } + } + + ErrorF("init memmap\n"); + RADEONInitMemMapRegisters(pScrn, &info->ModeReg, info); + ErrorF("init common\n"); + RADEONInitCommonRegisters(&info->ModeReg, info); + + switch (radeon_crtc->crtc_id) { + case 0: + ErrorF("init crtc1\n"); + RADEONInitCrtcRegisters(crtc, &info->ModeReg, adjusted_mode, x, y); + dot_clock = adjusted_mode->Clock / 1000.0; + if (dot_clock) { + ErrorF("init pll1\n"); + RADEONInitPLLRegisters(pScrn, info, &info->ModeReg, &info->pll, dot_clock); + } 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, x, y); + dot_clock = adjusted_mode->Clock / 1000.0; + if (dot_clock) { + ErrorF("init pll2\n"); + RADEONInitPLL2Registers(pScrn, &info->ModeReg, &info->pll, dot_clock, montype != MT_CRT); + } + break; + } + + 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; + } + + if (info->DispPriority) + RADEONInitDispBandwidth(pScrn); + +} + +static void +radeon_crtc_mode_commit(xf86CrtcPtr crtc) +{ + radeon_crtc_dpms(crtc, DPMSModeOn); +} + +void radeon_crtc_load_lut(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int i; + + if (!crtc->enabled) + return; + + PAL_SELECT(radeon_crtc->crtc_id); + + for (i = 0; i < 256; i++) { + OUTPAL(i, radeon_crtc->lut_r[i], radeon_crtc->lut_g[i], radeon_crtc->lut_b[i]); + } +} + + +static void +radeon_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, + CARD16 *blue, int size) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + int i; + + for (i = 0; i < 256; i++) { + radeon_crtc->lut_r[i] = red[i] >> 8; + radeon_crtc->lut_g[i] = green[i] >> 8; + radeon_crtc->lut_b[i] = blue[i] >> 8; + } + + radeon_crtc_load_lut(crtc); +} + +static Bool +radeon_crtc_lock(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + Bool CPStarted = info->CPStarted; + +#ifdef XF86DRI + if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); +#endif + + if (info->accelOn) + RADEON_SYNC(info, pScrn); + return FALSE; +} + +static void +radeon_crtc_unlock(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + +#ifdef XF86DRI + if (info->CPStarted && pScrn->pScreen) DRIUnlock(pScrn->pScreen); +#endif + + if (info->accelOn) + RADEON_SYNC(info, pScrn); +} + +static const xf86CrtcFuncsRec radeon_crtc_funcs = { + .dpms = radeon_crtc_dpms, + .save = NULL, /* XXX */ + .restore = NULL, /* XXX */ + .mode_fixup = radeon_crtc_mode_fixup, + .prepare = radeon_crtc_mode_prepare, + .mode_set = radeon_crtc_mode_set, + .commit = radeon_crtc_mode_commit, + .gamma_set = radeon_crtc_gamma_set, + .lock = radeon_crtc_lock, + .unlock = radeon_crtc_unlock, + .set_cursor_colors = radeon_crtc_set_cursor_colors, + .set_cursor_position = radeon_crtc_set_cursor_position, + .show_cursor = radeon_crtc_show_cursor, + .hide_cursor = radeon_crtc_hide_cursor, +/* .load_cursor_image = i830_crtc_load_cursor_image, */ + .load_cursor_argb = radeon_crtc_load_cursor_argb, + .destroy = NULL, /* XXX */ +}; + +Bool RADEONAllocateControllers(ScrnInfoPtr pScrn) +{ + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + if (pRADEONEnt->Controller[0]) + return TRUE; + + pRADEONEnt->pCrtc[0] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs); + if (!pRADEONEnt->pCrtc[0]) + return FALSE; + + pRADEONEnt->Controller[0] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1); + if (!pRADEONEnt->Controller[0]) + return FALSE; + + pRADEONEnt->pCrtc[0]->driver_private = pRADEONEnt->Controller[0]; + pRADEONEnt->Controller[0]->crtc_id = 0; + + if (!pRADEONEnt->HasCRTC2) + return TRUE; + + pRADEONEnt->pCrtc[1] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs); + if (!pRADEONEnt->pCrtc[1]) + return FALSE; + + pRADEONEnt->Controller[1] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1); + if (!pRADEONEnt->Controller[1]) + { + xfree(pRADEONEnt->Controller[0]); + return FALSE; + } + + pRADEONEnt->pCrtc[1]->driver_private = pRADEONEnt->Controller[1]; + pRADEONEnt->Controller[1]->crtc_id = 1; + return TRUE; +} + +/** + * In the current world order, there are lists of modes per output, which may + * or may not include the mode that was asked to be set by XFree86's mode + * selection. Find the closest one, in the following preference order: + * + * - Equality + * - Closer in size to the requested mode, but no larger + * - Closer in refresh rate to the requested mode. + */ +DisplayModePtr +RADEONCrtcFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + DisplayModePtr pBest = NULL, pScan = NULL; + int i; + + /* Assume that there's only one output connected to the given CRTC. */ + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc && output->probed_modes != NULL) + { + pScan = output->probed_modes; + break; + } + } + + /* If the pipe doesn't have any detected modes, just let the system try to + * spam the desired mode in. + */ + if (pScan == NULL) { + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No crtc mode list for crtc %d," + "continuing with desired mode\n", radeon_crtc->crtc_id); + return pMode; + } + + for (; pScan != NULL; pScan = pScan->next) { + assert(pScan->VRefresh != 0.0); + + /* If there's an exact match, we're done. */ + if (xf86ModesEqual(pScan, pMode)) { + pBest = pMode; + break; + } + + /* Reject if it's larger than the desired mode. */ + if (pScan->HDisplay > pMode->HDisplay || + pScan->VDisplay > pMode->VDisplay) + { + continue; + } + + if (pBest == NULL) { + pBest = pScan; + continue; + } + + /* Find if it's closer to the right size than the current best + * option. + */ + if ((pScan->HDisplay > pBest->HDisplay && + pScan->VDisplay >= pBest->VDisplay) || + (pScan->HDisplay >= pBest->HDisplay && + pScan->VDisplay > pBest->VDisplay)) + { + pBest = pScan; + continue; + } + + /* Find if it's still closer to the right refresh than the current + * best resolution. + */ + if (pScan->HDisplay == pBest->HDisplay && + pScan->VDisplay == pBest->VDisplay && + (fabs(pScan->VRefresh - pMode->VRefresh) < + fabs(pBest->VRefresh - pMode->VRefresh))) { + pBest = pScan; + } + } + + if (pBest == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No suitable mode found to program for the pipe.\n" + " continuing with desired mode %dx%d@%.1f\n", + pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); + } else if (!xf86ModesEqual(pBest, pMode)) { + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + int crtc = radeon_crtc->crtc_id; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 " + "mode %dx%d@%.1f\n", crtc, + pBest->HDisplay, pBest->VDisplay, pBest->VRefresh, + pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); + pMode = pBest; + } + return pMode; +} + +void +RADEONChooseOverlayCRTC(ScrnInfoPtr pScrn, BoxPtr dstBox) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); + int c; + int highx = 0, highy = 0; + int crtc_num; + + for (c = 0; c < xf86_config->num_crtc; c++) + { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + if (!crtc->enabled) + continue; + + if ((dstBox->x1 >= crtc->x) && (dstBox->y1 >= crtc->y)) + crtc_num = c; + } + + if (crtc_num == 1) + info->OverlayOnCRTC2 = TRUE; + else + info->OverlayOnCRTC2 = FALSE; +} + diff --git a/src/radeon_display.c b/src/radeon_display.c index 7ec6c6b..8ce1912 100644 --- a/src/radeon_display.c +++ b/src/radeon_display.c @@ -47,85 +47,8 @@ #include "radeon_probe.h" #include "radeon_version.h" -void RADEONSetOutputType(ScrnInfoPtr pScrn, RADEONOutputPrivatePtr radeon_output); -void radeon_crtc_load_lut(xf86CrtcPtr crtc); extern int getRADEONEntityIndex(void); -const char *MonTypeName[7] = { - "AUTO", - "NONE", - "CRT", - "LVDS", - "TMDS", - "CTV", - "STV" -}; - -const RADEONMonitorType MonTypeID[7] = { - MT_UNKNOWN, /* this is just a dummy value for AUTO DETECTION */ - MT_NONE, /* NONE -> NONE */ - MT_CRT, /* CRT -> CRT */ - MT_LCD, /* Laptop LCDs are driven via LVDS port */ - MT_DFP, /* DFPs are driven via TMDS */ - MT_CTV, /* CTV -> CTV */ - MT_STV, /* STV -> STV */ -}; - -const char *TMDSTypeName[3] = { - "NONE", - "Internal", - "External" -}; - -const char *DDCTypeName[6] = { - "NONE", - "MONID", - "DVI_DDC", - "VGA_DDC", - "CRT2_DDC", - "LCD_DDC" -}; - -const char *DACTypeName[3] = { - "Unknown", - "Primary", - "TVDAC/ExtDAC", -}; - -const char *ConnectorTypeName[8] = { - "None", - "Proprietary", - "VGA", - "DVI-I", - "DVI-D", - "CTV", - "STV", - "Unsupported" -}; - -const char *ConnectorTypeNameATOM[10] = { - "None", - "VGA", - "DVI-I", - "DVI-D", - "DVI-A", - "STV", - "CTV", - "LVDS", - "Digital", - "Unsupported" -}; - -const char *OutputType[10] = { - "None", - "VGA", - "DVI", - "LVDS", - "S-video", - "Composite", -}; - - static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = { {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ @@ -320,7 +243,7 @@ void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) } } -static RADEONMonitorType +RADEONMonitorType RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -566,7 +489,7 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) } -static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, xf86OutputPtr output) +RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, xf86OutputPtr output) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; @@ -661,7 +584,7 @@ static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, xf86Output return MonType; } -static void RADEONGetPanelInfoFromReg (xf86OutputPtr output) +void RADEONGetPanelInfoFromReg (xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); @@ -716,7 +639,7 @@ static void RADEONGetPanelInfoFromReg (xf86OutputPtr output) /* BIOS may not have right panel size, we search through all supported * DDC modes looking for the maximum panel size. */ -static void RADEONUpdatePanelSize(xf86OutputPtr output) +void RADEONUpdatePanelSize(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); @@ -812,7 +735,7 @@ static void RADEONUpdatePanelSize(xf86OutputPtr output) } } -static Bool RADEONGetLVDSInfo (xf86OutputPtr output) +Bool RADEONGetLVDSInfo (xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); @@ -874,7 +797,7 @@ static Bool RADEONGetLVDSInfo (xf86OutputPtr output) return TRUE; } -static void RADEONGetTMDSInfo(xf86OutputPtr output) +void RADEONGetTMDSInfo(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); @@ -908,102 +831,6 @@ void RADEONGetTVDacAdjInfo(xf86OutputPtr output) } } -static void RADEONSwapOutputs(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONBIOSConnector tmp; - - tmp = info->BiosConnector[0]; - info->BiosConnector[0] = info->BiosConnector[1]; - info->BiosConnector[1] = tmp; - -} - -static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONOutputPrivatePtr radeon_output = output->driver_private; - RADEONMonitorType MonType = MT_NONE; - - - if (info->IsMobility) { - if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_LVDS_ATOM) || - radeon_output->ConnectorType == CONNECTOR_PROPRIETARY) { - if (INREG(RADEON_BIOS_4_SCRATCH) & 4) - MonType = MT_LCD; - } - /* non-DDC TMDS panel connected through DVO */ - if (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_ON) - MonType = MT_DFP; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected Monitor Type: %d\n", MonType); - - return MonType; - -} - -/* Primary Head (DVI or Laptop Int. panel)*/ -/* A ddc capable display connected on DVI port */ -/* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ -void RADEONConnectorFindMonitor(ScrnInfoPtr pScrn, xf86OutputPtr output) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - - if (radeon_output->MonType == MT_UNKNOWN) { - if ((radeon_output->MonType = RADEONDisplayDDCConnected(pScrn, output))); - else if((radeon_output->MonType = RADEONPortCheckNonDDC(pScrn, output))); - else if (radeon_output->DACType == DAC_PRIMARY) - radeon_output->MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(radeon_output->DACType)); - } - - if (output->MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on connector: %s ----------------------\n", - info->IsAtomBios ? - ConnectorTypeNameATOM[radeon_output->ConnectorType]: - ConnectorTypeName[radeon_output->ConnectorType] - ); - xf86PrintEDID( output->MonInfo ); - } -} - -Bool RADEONMapControllers(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - RADEONOutputPrivatePtr radeon_output; - xf86OutputPtr output; - int o; - - pRADEONEnt->Controller[0]->binding = 1; - pRADEONEnt->Controller[1]->binding = 1; - - for (o = 0; o < xf86_config->num_output; o++) { - output = xf86_config->output[o]; - radeon_output = output->driver_private; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Port%d:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", - o, - MonTypeName[radeon_output->MonType+1], - info->IsAtomBios ? - ConnectorTypeNameATOM[radeon_output->ConnectorType]: - ConnectorTypeName[radeon_output->ConnectorType], - DACTypeName[radeon_output->DACType+1], - TMDSTypeName[radeon_output->TMDSType+1], - DDCTypeName[radeon_output->DDCType]); - - } - - return TRUE; -} - /* * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant). * @@ -1651,6 +1478,7 @@ void RADEONUnblank(ScrnInfoPtr pScrn) } } +#if 0 static void RADEONDPMSSetOn(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; @@ -1738,818 +1566,4 @@ static void RADEONDPMSSetOff(xf86OutputPtr output) break; } } - - -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; - - mask = radeon_crtc->crtc_id ? (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS) : (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_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_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_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_EXT_CNTL, mask, ~mask); - } - break; - } - - if (mode != DPMSModeOff) - radeon_crtc_load_lut(crtc); -} - -static Bool -radeon_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, - DisplayModePtr adjusted_mode) -{ - return TRUE; -} - -static void -radeon_crtc_mode_prepare(xf86CrtcPtr crtc) -{ - radeon_crtc_dpms(crtc, DPMSModeOff); -} - -static void -radeon_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); - RADEONMonitorType montype; - int i = 0; - double dot_clock = 0; - - 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) { - montype = radeon_output->MonType; - } - } - - ErrorF("init memmap\n"); - RADEONInitMemMapRegisters(pScrn, &info->ModeReg, info); - ErrorF("init common\n"); - RADEONInitCommonRegisters(&info->ModeReg, info); - - switch (radeon_crtc->crtc_id) { - case 0: - ErrorF("init crtc1\n"); - RADEONInitCrtcRegisters(crtc, &info->ModeReg, adjusted_mode, x, y); - dot_clock = adjusted_mode->Clock / 1000.0; - if (dot_clock) { - ErrorF("init pll1\n"); - RADEONInitPLLRegisters(pScrn, info, &info->ModeReg, &info->pll, dot_clock); - } 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, x, y); - dot_clock = adjusted_mode->Clock / 1000.0; - if (dot_clock) { - ErrorF("init pll2\n"); - RADEONInitPLL2Registers(pScrn, &info->ModeReg, &info->pll, dot_clock, montype != MT_CRT); - } - break; - } - - 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; - } - - if (info->DispPriority) - RADEONInitDispBandwidth(pScrn); - -} - -static void -radeon_crtc_mode_commit(xf86CrtcPtr crtc) -{ - radeon_crtc_dpms(crtc, DPMSModeOn); -} - -void radeon_crtc_load_lut(xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int i; - - if (!crtc->enabled) - return; - - PAL_SELECT(radeon_crtc->crtc_id); - - for (i = 0; i < 256; i++) { - OUTPAL(i, radeon_crtc->lut_r[i], radeon_crtc->lut_g[i], radeon_crtc->lut_b[i]); - } -} - - -static void -radeon_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, - CARD16 *blue, int size) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; - RADEONInfoPtr info = RADEONPTR(pScrn); - int i; - - for (i = 0; i < 256; i++) { - radeon_crtc->lut_r[i] = red[i] >> 8; - radeon_crtc->lut_g[i] = green[i] >> 8; - radeon_crtc->lut_b[i] = blue[i] >> 8; - } - - radeon_crtc_load_lut(crtc); -} - -static Bool -radeon_crtc_lock(xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - Bool CPStarted = info->CPStarted; - -#ifdef XF86DRI - if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); -#endif - - if (info->accelOn) - RADEON_SYNC(info, pScrn); - return FALSE; -} - -static void -radeon_crtc_unlock(xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - -#ifdef XF86DRI - if (info->CPStarted && pScrn->pScreen) DRIUnlock(pScrn->pScreen); #endif - - if (info->accelOn) - RADEON_SYNC(info, pScrn); -} - -static const xf86CrtcFuncsRec radeon_crtc_funcs = { - .dpms = radeon_crtc_dpms, - .save = NULL, /* XXX */ - .restore = NULL, /* XXX */ - .mode_fixup = radeon_crtc_mode_fixup, - .prepare = radeon_crtc_mode_prepare, - .mode_set = radeon_crtc_mode_set, - .commit = radeon_crtc_mode_commit, - .gamma_set = radeon_crtc_gamma_set, - .lock = radeon_crtc_lock, - .unlock = radeon_crtc_unlock, - .set_cursor_colors = radeon_crtc_set_cursor_colors, - .set_cursor_position = radeon_crtc_set_cursor_position, - .show_cursor = radeon_crtc_show_cursor, - .hide_cursor = radeon_crtc_hide_cursor, -/* .load_cursor_image = i830_crtc_load_cursor_image, */ - .load_cursor_argb = radeon_crtc_load_cursor_argb, - .destroy = NULL, /* XXX */ -}; - -static void -radeon_dpms(xf86OutputPtr output, int mode) -{ - ScrnInfoPtr pScrn = output->scrn; - - switch(mode) { - case DPMSModeOn: - RADEONEnableDisplay(output, TRUE); - /* RADEONDPMSSetOn(output);*/ - break; - case DPMSModeOff: - case DPMSModeSuspend: - case DPMSModeStandby: - RADEONEnableDisplay(output, FALSE); - /*RADEONDPMSSetOff(output);*/ - break; - } -} - -static void -radeon_save(xf86OutputPtr output) -{ - -} - -static void -radeon_restore(xf86OutputPtr restore) -{ - -} - -static int -radeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - DisplayModePtr m; - - if (radeon_output->type != OUTPUT_LVDS) - return MODE_OK; - - if (pMode->HDisplay > radeon_output->PanelXRes || - pMode->VDisplay > radeon_output->PanelYRes) - return MODE_PANEL; - - return MODE_OK; -} - -static Bool -radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, - DisplayModePtr adjusted_mode) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - - if (radeon_output->type != OUTPUT_LVDS) - return TRUE; - - if (mode->HDisplay < radeon_output->PanelXRes || - mode->VDisplay < radeon_output->PanelYRes) - adjusted_mode->Flags |= RADEON_USE_RMX; - - if (adjusted_mode->Flags & RADEON_USE_RMX) { - adjusted_mode->CrtcHTotal = mode->CrtcHDisplay + radeon_output->HBlank; - adjusted_mode->CrtcHSyncStart = mode->CrtcHDisplay + radeon_output->HOverPlus; - adjusted_mode->CrtcHSyncEnd = mode->CrtcHSyncStart + radeon_output->HSyncWidth; - adjusted_mode->CrtcVTotal = mode->CrtcVDisplay + radeon_output->VBlank; - adjusted_mode->CrtcVSyncStart = mode->CrtcVDisplay + radeon_output->VOverPlus; - adjusted_mode->CrtcVSyncEnd = mode->CrtcVSyncStart + radeon_output->VSyncWidth; - adjusted_mode->Clock = radeon_output->DotClock; - adjusted_mode->Flags = radeon_output->Flags | RADEON_USE_RMX; - /* save these for Xv with RMX */ - info->PanelYRes = radeon_output->PanelYRes; - info->PanelXRes = radeon_output->PanelXRes; - } - - return TRUE; -} - -static void -radeon_mode_prepare(xf86OutputPtr output) -{ -} - -static void -radeon_mode_set(xf86OutputPtr output, DisplayModePtr mode, - DisplayModePtr adjusted_mode) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - - switch(radeon_output->MonType) { - case MT_LCD: - case MT_DFP: - ErrorF("restore FP\n"); - RADEONRestoreFPRegisters(pScrn, &info->ModeReg); - break; - default: - ErrorF("restore dac\n"); - RADEONRestoreDACRegisters(pScrn, &info->ModeReg); - } - - RADEONEnableDisplay(output, TRUE); -} - -static void -radeon_mode_commit(xf86OutputPtr output) -{ -} - -static xf86OutputStatus -radeon_detect(xf86OutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONOutputPrivatePtr radeon_output = output->driver_private; - - radeon_output->MonType = MT_UNKNOWN; - RADEONConnectorFindMonitor(pScrn, output); - if (radeon_output->MonType == MT_UNKNOWN) { - output->subpixel_order = SubPixelUnknown; - return XF86OutputStatusUnknown; - } - else if (radeon_output->MonType == MT_NONE) { - output->subpixel_order = SubPixelUnknown; - return XF86OutputStatusDisconnected; - } else { - - switch(radeon_output->MonType) { - case MT_LCD: - case MT_DFP: output->subpixel_order = SubPixelHorizontalRGB; break; - default: output->subpixel_order = SubPixelNone; break; - } - - return XF86OutputStatusConnected; - } - -} - -static DisplayModePtr -radeon_get_modes(xf86OutputPtr output) -{ - DisplayModePtr modes; - modes = RADEONProbeOutputModes(output); - return modes; -} - -static void -radeon_destroy (xf86OutputPtr output) -{ - if(output->driver_private) - xfree(output->driver_private); -} - -static const xf86OutputFuncsRec radeon_output_funcs = { - .dpms = radeon_dpms, - .save = radeon_save, - .restore = radeon_restore, - .mode_valid = radeon_mode_valid, - .mode_fixup = radeon_mode_fixup, - .prepare = radeon_mode_prepare, - .mode_set = radeon_mode_set, - .commit = radeon_mode_commit, - .detect = radeon_detect, - .get_modes = radeon_get_modes, - .destroy = radeon_destroy -}; - -Bool RADEONAllocateControllers(ScrnInfoPtr pScrn) -{ - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - if (pRADEONEnt->Controller[0]) - return TRUE; - - pRADEONEnt->pCrtc[0] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs); - if (!pRADEONEnt->pCrtc[0]) - return FALSE; - - pRADEONEnt->Controller[0] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1); - if (!pRADEONEnt->Controller[0]) - return FALSE; - - pRADEONEnt->pCrtc[0]->driver_private = pRADEONEnt->Controller[0]; - pRADEONEnt->Controller[0]->crtc_id = 0; - - if (!pRADEONEnt->HasCRTC2) - return TRUE; - - pRADEONEnt->pCrtc[1] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs); - if (!pRADEONEnt->pCrtc[1]) - return FALSE; - - pRADEONEnt->Controller[1] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1); - if (!pRADEONEnt->Controller[1]) - { - xfree(pRADEONEnt->Controller[0]); - return FALSE; - } - - pRADEONEnt->pCrtc[1]->driver_private = pRADEONEnt->Controller[1]; - pRADEONEnt->Controller[1]->crtc_id = 1; - return TRUE; -} - -void RADEONSetOutputType(ScrnInfoPtr pScrn, RADEONOutputPrivatePtr radeon_output) -{ - RADEONInfoPtr info = RADEONPTR (pScrn); - RADEONOutputType output; - if (info->IsAtomBios) { - switch(radeon_output->ConnectorType) { - case 0: output = OUTPUT_NONE; break; - case 1: output = OUTPUT_VGA; break; - case 2: - case 3: - case 4: output = OUTPUT_DVI; break; - case 5: output = OUTPUT_STV; break; - case 6: output = OUTPUT_CTV; break; - case 7: - case 8: output = OUTPUT_LVDS; break; - case 9: - default: - output = OUTPUT_NONE; break; - } - } - else { - switch(radeon_output->ConnectorType) { - case 0: output = OUTPUT_NONE; break; - case 1: output = OUTPUT_LVDS; break; - case 2: output = OUTPUT_VGA; break; - case 3: - case 4: output = OUTPUT_DVI; break; - case 5: output = OUTPUT_STV; break; - case 6: output = OUTPUT_CTV; break; - default: output = OUTPUT_NONE; break; - } - } - radeon_output->type = output; -} - -void RADEONInitConnector(xf86OutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - RADEONOutputPrivatePtr radeon_output = output->driver_private; - int DDCReg = 0; - char* name = OutputType[radeon_output->type]; - - switch(radeon_output->DDCType) { - case DDC_MONID: DDCReg = RADEON_GPIO_MONID; break; - case DDC_DVI : DDCReg = RADEON_GPIO_DVI_DDC; break; - case DDC_VGA: DDCReg = RADEON_GPIO_VGA_DDC; break; - case DDC_CRT2: DDCReg = RADEON_GPIO_CRT2_DDC; break; - default: break; - } - - if (DDCReg) { - radeon_output->DDCReg = DDCReg; - RADEONI2CInit(pScrn, &radeon_output->pI2CBus, DDCReg, name); - } - - if (radeon_output->type == OUTPUT_LVDS) { - RADEONGetLVDSInfo(output); - } - - if (radeon_output->type == OUTPUT_DVI) { - RADEONGetTMDSInfo(output); - - // FIXME - /*if (i == 0) - RADEONGetHardCodedEDIDFromBIOS(output);*/ - - /*RADEONUpdatePanelSize(output);*/ - } - - if (radeon_output->DACType == DAC_TVDAC) { - RADEONGetTVDacAdjInfo(output); - } - -} - -/* - * initialise the static data sos we don't have to re-do at randr change */ -Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - xf86OutputPtr output; - const char *s; - int i = 0, second = 0, max_mt = 5; - - - /* We first get the information about all connectors from BIOS. - * This is how the card is phyiscally wired up. - * The information should be correct even on a OEM card. - * If not, we may have problem -- need to use MonitorLayout option. - */ - for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { - info->BiosConnector[i].DDCType = DDC_NONE_DETECTED; - info->BiosConnector[i].DACType = DAC_UNKNOWN; - info->BiosConnector[i].TMDSType = TMDS_UNKNOWN; - info->BiosConnector[i].ConnectorType = CONNECTOR_NONE; - } - - if (!RADEONGetConnectorInfoFromBIOS(pScrn) || - ((info->BiosConnector[0].DDCType == 0) && - (info->BiosConnector[1].DDCType == 0))) { - if (info->IsMobility) { - /* Below is the most common setting, but may not be true */ - info->BiosConnector[0].DDCType = DDC_LCD; - info->BiosConnector[0].DACType = DAC_UNKNOWN; - info->BiosConnector[0].TMDSType = TMDS_UNKNOWN; - info->BiosConnector[0].ConnectorType = CONNECTOR_PROPRIETARY; - - info->BiosConnector[1].DDCType = DDC_VGA; - info->BiosConnector[1].DACType = DAC_PRIMARY; - info->BiosConnector[1].TMDSType = TMDS_EXT; - info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; - } else { - /* Below is the most common setting, but may not be true */ - info->BiosConnector[0].DDCType = DDC_DVI; - info->BiosConnector[0].DACType = DAC_TVDAC; - info->BiosConnector[0].TMDSType = TMDS_INT; - info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I; - - info->BiosConnector[1].DDCType = DDC_VGA; - info->BiosConnector[1].DACType = DAC_PRIMARY; - info->BiosConnector[1].TMDSType = TMDS_EXT; - info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; - } - - /* Some cards have the DDC lines swapped and we have no way to - * detect it yet (Mac cards) - */ - if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) { - info->BiosConnector[0].DDCType = DDC_VGA; - info->BiosConnector[1].DDCType = DDC_DVI; - } - } - - /* always make TMDS_INT port first*/ - if (info->BiosConnector[1].TMDSType == TMDS_INT) { - RADEONSwapOutputs(pScrn); - } else if ((info->BiosConnector[0].TMDSType != TMDS_INT && - info->BiosConnector[1].TMDSType != TMDS_INT)) { - /* no TMDS_INT port, make primary DAC port first */ - /* On my Inspiron 8600 both internal and external ports are - marked DAC_PRIMARY in BIOS. So be extra careful - only - swap when the first port is not DAC_PRIMARY */ - if ((!(info->BiosConnector[0].ConnectorType == CONNECTOR_PROPRIETARY)) && (info->BiosConnector[1].DACType == DAC_PRIMARY) && - (info->BiosConnector[0].DACType != DAC_PRIMARY)) { - RADEONSwapOutputs(pScrn); - } - } - - if (info->HasSingleDAC) { - /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/ - if (info->BiosConnector[0].ConnectorType == CONNECTOR_CRT) { - info->BiosConnector[0].DACType = DAC_TVDAC; - info->BiosConnector[1].DACType = DAC_PRIMARY; - } else { - info->BiosConnector[1].DACType = DAC_TVDAC; - info->BiosConnector[0].DACType = DAC_PRIMARY; - } - } else if (!pRADEONEnt->HasCRTC2) { - info->BiosConnector[0].DACType = DAC_PRIMARY; - } - - for (i = 0 ; i < RADEON_MAX_BIOS_CONNECTOR; i++) { - RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); - if (!radeon_output) { - return FALSE; - } - radeon_output->MonType = MT_UNKNOWN; - radeon_output->ConnectorType = info->BiosConnector[i].ConnectorType; - if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D_ATOM) || - radeon_output->ConnectorType == CONNECTOR_DVI_D) - radeon_output->DACType = DAC_UNKNOWN; - else - radeon_output->DACType = info->BiosConnector[i].DACType; - radeon_output->DDCType = info->BiosConnector[i].DDCType; - radeon_output->TMDSType = info->BiosConnector[i].TMDSType; - - RADEONSetOutputType(pScrn, radeon_output); - output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); - if (!output) { - return FALSE; - } - output->driver_private = radeon_output; - output->possible_crtcs = 1; - if (radeon_output->type != OUTPUT_LVDS) - output->possible_crtcs |= 2; - - output->possible_clones = 0 /*1|2*/; - - RADEONInitConnector(output); - } - - /* if it's a mobility make sure we have a LVDS port */ - if (info->IsMobility) { - if (info->IsAtomBios) { - if (info->BiosConnector[0].ConnectorType != CONNECTOR_LVDS_ATOM && - info->BiosConnector[1].ConnectorType != CONNECTOR_LVDS_ATOM) { - /* add LVDS port */ - RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); - if (!radeon_output) { - return FALSE; - } - radeon_output->MonType = MT_UNKNOWN; - radeon_output->DDCType = DDC_LCD; - radeon_output->DACType = DAC_UNKNOWN; - radeon_output->TMDSType = TMDS_UNKNOWN; - radeon_output->ConnectorType = CONNECTOR_LVDS_ATOM; - RADEONSetOutputType(pScrn, radeon_output); - output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); - if (!output) { - return FALSE; - } - output->driver_private = radeon_output; - output->possible_crtcs = 1; - output->possible_clones = 0 /*1|2*/; - - RADEONInitConnector(output); - - } - } else { - if (info->BiosConnector[0].ConnectorType != CONNECTOR_PROPRIETARY && - info->BiosConnector[1].ConnectorType != CONNECTOR_PROPRIETARY) { - /* add LVDS port */ - RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); - if (!radeon_output) { - return FALSE; - } - radeon_output->MonType = MT_UNKNOWN; - radeon_output->DDCType = DDC_LCD; - radeon_output->DACType = DAC_UNKNOWN; - radeon_output->TMDSType = TMDS_UNKNOWN; - radeon_output->ConnectorType = CONNECTOR_PROPRIETARY; - RADEONSetOutputType(pScrn, radeon_output); - output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); - if (!output) { - return FALSE; - } - output->driver_private = radeon_output; - output->possible_crtcs = 1; - output->possible_clones = 0 /*1|2*/; - - RADEONInitConnector(output); - } - } - } - return TRUE; -} - -/** - * In the current world order, there are lists of modes per output, which may - * or may not include the mode that was asked to be set by XFree86's mode - * selection. Find the closest one, in the following preference order: - * - * - Equality - * - Closer in size to the requested mode, but no larger - * - Closer in refresh rate to the requested mode. - */ -DisplayModePtr -RADEONCrtcFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - DisplayModePtr pBest = NULL, pScan = NULL; - int i; - - /* Assume that there's only one output connected to the given CRTC. */ - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr output = xf86_config->output[i]; - if (output->crtc == crtc && output->probed_modes != NULL) - { - pScan = output->probed_modes; - break; - } - } - - /* If the pipe doesn't have any detected modes, just let the system try to - * spam the desired mode in. - */ - if (pScan == NULL) { - RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "No crtc mode list for crtc %d," - "continuing with desired mode\n", radeon_crtc->crtc_id); - return pMode; - } - - for (; pScan != NULL; pScan = pScan->next) { - assert(pScan->VRefresh != 0.0); - - /* If there's an exact match, we're done. */ - if (xf86ModesEqual(pScan, pMode)) { - pBest = pMode; - break; - } - - /* Reject if it's larger than the desired mode. */ - if (pScan->HDisplay > pMode->HDisplay || - pScan->VDisplay > pMode->VDisplay) - { - continue; - } - - if (pBest == NULL) { - pBest = pScan; - continue; - } - - /* Find if it's closer to the right size than the current best - * option. - */ - if ((pScan->HDisplay > pBest->HDisplay && - pScan->VDisplay >= pBest->VDisplay) || - (pScan->HDisplay >= pBest->HDisplay && - pScan->VDisplay > pBest->VDisplay)) - { - pBest = pScan; - continue; - } - - /* Find if it's still closer to the right refresh than the current - * best resolution. - */ - if (pScan->HDisplay == pBest->HDisplay && - pScan->VDisplay == pBest->VDisplay && - (fabs(pScan->VRefresh - pMode->VRefresh) < - fabs(pBest->VRefresh - pMode->VRefresh))) { - pBest = pScan; - } - } - - if (pBest == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "No suitable mode found to program for the pipe.\n" - " continuing with desired mode %dx%d@%.1f\n", - pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); - } else if (!xf86ModesEqual(pBest, pMode)) { - RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; - int crtc = radeon_crtc->crtc_id; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 " - "mode %dx%d@%.1f\n", crtc, - pBest->HDisplay, pBest->VDisplay, pBest->VRefresh, - pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); - pMode = pBest; - } - return pMode; -} - -void -RADEONChooseOverlayCRTC(ScrnInfoPtr pScrn, BoxPtr dstBox) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - RADEONInfoPtr info = RADEONPTR(pScrn); - int c; - int highx = 0, highy = 0; - int crtc_num; - - for (c = 0; c < xf86_config->num_crtc; c++) - { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - - if (!crtc->enabled) - continue; - - if ((dstBox->x1 >= crtc->x) && (dstBox->y1 >= crtc->y)) - crtc_num = c; - } - - if (crtc_num == 1) - info->OverlayOnCRTC2 = TRUE; - else - info->OverlayOnCRTC2 = FALSE; -} diff --git a/src/radeon_output.c b/src/radeon_output.c new file mode 100644 index 0000000..18ef16d --- /dev/null +++ b/src/radeon_output.c @@ -0,0 +1,641 @@ +/* + * 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 "fbdevhw.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" + + +const char *MonTypeName[7] = { + "AUTO", + "NONE", + "CRT", + "LVDS", + "TMDS", + "CTV", + "STV" +}; + +const RADEONMonitorType MonTypeID[7] = { + MT_UNKNOWN, /* this is just a dummy value for AUTO DETECTION */ + MT_NONE, /* NONE -> NONE */ + MT_CRT, /* CRT -> CRT */ + MT_LCD, /* Laptop LCDs are driven via LVDS port */ + MT_DFP, /* DFPs are driven via TMDS */ + MT_CTV, /* CTV -> CTV */ + MT_STV, /* STV -> STV */ +}; + +const char *TMDSTypeName[3] = { + "NONE", + "Internal", + "External" +}; + +const char *DDCTypeName[6] = { + "NONE", + "MONID", + "DVI_DDC", + "VGA_DDC", + "CRT2_DDC", + "LCD_DDC" +}; + +const char *DACTypeName[3] = { + "Unknown", + "Primary", + "TVDAC/ExtDAC", +}; + +const char *ConnectorTypeName[8] = { + "None", + "Proprietary", + "VGA", + "DVI-I", + "DVI-D", + "CTV", + "STV", + "Unsupported" +}; + +const char *ConnectorTypeNameATOM[10] = { + "None", + "VGA", + "DVI-I", + "DVI-D", + "DVI-A", + "STV", + "CTV", + "LVDS", + "Digital", + "Unsupported" +}; + +const char *OutputType[10] = { + "None", + "VGA", + "DVI", + "LVDS", + "S-video", + "Composite", +}; + +static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output); + +Bool RADEONMapControllers(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONOutputPrivatePtr radeon_output; + xf86OutputPtr output; + int o; + + pRADEONEnt->Controller[0]->binding = 1; + pRADEONEnt->Controller[1]->binding = 1; + + for (o = 0; o < xf86_config->num_output; o++) { + output = xf86_config->output[o]; + radeon_output = output->driver_private; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Port%d:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + o, + MonTypeName[radeon_output->MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[radeon_output->ConnectorType]: + ConnectorTypeName[radeon_output->ConnectorType], + DACTypeName[radeon_output->DACType+1], + TMDSTypeName[radeon_output->TMDSType+1], + DDCTypeName[radeon_output->DDCType]); + + } + + return TRUE; +} + +/* Primary Head (DVI or Laptop Int. panel)*/ +/* A ddc capable display connected on DVI port */ +/* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ +void RADEONConnectorFindMonitor(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (radeon_output->MonType == MT_UNKNOWN) { + if ((radeon_output->MonType = RADEONDisplayDDCConnected(pScrn, output))); + else if((radeon_output->MonType = RADEONPortCheckNonDDC(pScrn, output))); + else if (radeon_output->DACType == DAC_PRIMARY) + radeon_output->MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(radeon_output->DACType)); + } + + if (output->MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on connector: %s ----------------------\n", + info->IsAtomBios ? + ConnectorTypeNameATOM[radeon_output->ConnectorType]: + ConnectorTypeName[radeon_output->ConnectorType] + ); + xf86PrintEDID( output->MonInfo ); + } +} + +static void RADEONSwapOutputs(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONBIOSConnector tmp; + + tmp = info->BiosConnector[0]; + info->BiosConnector[0] = info->BiosConnector[1]; + info->BiosConnector[1] = tmp; + +} + +static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONMonitorType MonType = MT_NONE; + + + if (info->IsMobility) { + if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_LVDS_ATOM) || + radeon_output->ConnectorType == CONNECTOR_PROPRIETARY) { + if (INREG(RADEON_BIOS_4_SCRATCH) & 4) + MonType = MT_LCD; + } + /* non-DDC TMDS panel connected through DVO */ + if (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_ON) + MonType = MT_DFP; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected Monitor Type: %d\n", MonType); + + return MonType; + +} + +static void +radeon_dpms(xf86OutputPtr output, int mode) +{ + ScrnInfoPtr pScrn = output->scrn; + + switch(mode) { + case DPMSModeOn: + RADEONEnableDisplay(output, TRUE); + /* RADEONDPMSSetOn(output);*/ + break; + case DPMSModeOff: + case DPMSModeSuspend: + case DPMSModeStandby: + RADEONEnableDisplay(output, FALSE); + /*RADEONDPMSSetOff(output);*/ + break; + } +} + +static void +radeon_save(xf86OutputPtr output) +{ + +} + +static void +radeon_restore(xf86OutputPtr restore) +{ + +} + +static int +radeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + DisplayModePtr m; + + if (radeon_output->type != OUTPUT_LVDS) + return MODE_OK; + + if (pMode->HDisplay > radeon_output->PanelXRes || + pMode->VDisplay > radeon_output->PanelYRes) + return MODE_PANEL; + + return MODE_OK; +} + +static Bool +radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (radeon_output->type != OUTPUT_LVDS) + return TRUE; + + if (mode->HDisplay < radeon_output->PanelXRes || + mode->VDisplay < radeon_output->PanelYRes) + adjusted_mode->Flags |= RADEON_USE_RMX; + + if (adjusted_mode->Flags & RADEON_USE_RMX) { + adjusted_mode->CrtcHTotal = mode->CrtcHDisplay + radeon_output->HBlank; + adjusted_mode->CrtcHSyncStart = mode->CrtcHDisplay + radeon_output->HOverPlus; + adjusted_mode->CrtcHSyncEnd = mode->CrtcHSyncStart + radeon_output->HSyncWidth; + adjusted_mode->CrtcVTotal = mode->CrtcVDisplay + radeon_output->VBlank; + adjusted_mode->CrtcVSyncStart = mode->CrtcVDisplay + radeon_output->VOverPlus; + adjusted_mode->CrtcVSyncEnd = mode->CrtcVSyncStart + radeon_output->VSyncWidth; + adjusted_mode->Clock = radeon_output->DotClock; + adjusted_mode->Flags = radeon_output->Flags | RADEON_USE_RMX; + /* save these for Xv with RMX */ + info->PanelYRes = radeon_output->PanelYRes; + info->PanelXRes = radeon_output->PanelXRes; + } + + return TRUE; +} + +static void +radeon_mode_prepare(xf86OutputPtr output) +{ +} + +static void +radeon_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + switch(radeon_output->MonType) { + case MT_LCD: + case MT_DFP: + ErrorF("restore FP\n"); + RADEONRestoreFPRegisters(pScrn, &info->ModeReg); + break; + default: + ErrorF("restore dac\n"); + RADEONRestoreDACRegisters(pScrn, &info->ModeReg); + } + + RADEONEnableDisplay(output, TRUE); +} + +static void +radeon_mode_commit(xf86OutputPtr output) +{ +} + +static xf86OutputStatus +radeon_detect(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + radeon_output->MonType = MT_UNKNOWN; + RADEONConnectorFindMonitor(pScrn, output); + if (radeon_output->MonType == MT_UNKNOWN) { + output->subpixel_order = SubPixelUnknown; + return XF86OutputStatusUnknown; + } + else if (radeon_output->MonType == MT_NONE) { + output->subpixel_order = SubPixelUnknown; + return XF86OutputStatusDisconnected; + } else { + + switch(radeon_output->MonType) { + case MT_LCD: + case MT_DFP: output->subpixel_order = SubPixelHorizontalRGB; break; + default: output->subpixel_order = SubPixelNone; break; + } + + return XF86OutputStatusConnected; + } + +} + +static DisplayModePtr +radeon_get_modes(xf86OutputPtr output) +{ + DisplayModePtr modes; + modes = RADEONProbeOutputModes(output); + return modes; +} + +static void +radeon_destroy (xf86OutputPtr output) +{ + if(output->driver_private) + xfree(output->driver_private); +} + +static const xf86OutputFuncsRec radeon_output_funcs = { + .dpms = radeon_dpms, + .save = radeon_save, + .restore = radeon_restore, + .mode_valid = radeon_mode_valid, + .mode_fixup = radeon_mode_fixup, + .prepare = radeon_mode_prepare, + .mode_set = radeon_mode_set, + .commit = radeon_mode_commit, + .detect = radeon_detect, + .get_modes = radeon_get_modes, + .destroy = radeon_destroy +}; + +void RADEONSetOutputType(ScrnInfoPtr pScrn, RADEONOutputPrivatePtr radeon_output) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + RADEONOutputType output; + if (info->IsAtomBios) { + switch(radeon_output->ConnectorType) { + case 0: output = OUTPUT_NONE; break; + case 1: output = OUTPUT_VGA; break; + case 2: + case 3: + case 4: output = OUTPUT_DVI; break; + case 5: output = OUTPUT_STV; break; + case 6: output = OUTPUT_CTV; break; + case 7: + case 8: output = OUTPUT_LVDS; break; + case 9: + default: + output = OUTPUT_NONE; break; + } + } + else { + switch(radeon_output->ConnectorType) { + case 0: output = OUTPUT_NONE; break; + case 1: output = OUTPUT_LVDS; break; + case 2: output = OUTPUT_VGA; break; + case 3: + case 4: output = OUTPUT_DVI; break; + case 5: output = OUTPUT_STV; break; + case 6: output = OUTPUT_CTV; break; + default: output = OUTPUT_NONE; break; + } + } + radeon_output->type = output; +} + +void RADEONInitConnector(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int DDCReg = 0; + char* name = OutputType[radeon_output->type]; + + switch(radeon_output->DDCType) { + case DDC_MONID: DDCReg = RADEON_GPIO_MONID; break; + case DDC_DVI : DDCReg = RADEON_GPIO_DVI_DDC; break; + case DDC_VGA: DDCReg = RADEON_GPIO_VGA_DDC; break; + case DDC_CRT2: DDCReg = RADEON_GPIO_CRT2_DDC; break; + default: break; + } + + if (DDCReg) { + radeon_output->DDCReg = DDCReg; + RADEONI2CInit(pScrn, &radeon_output->pI2CBus, DDCReg, name); + } + + if (radeon_output->type == OUTPUT_LVDS) { + RADEONGetLVDSInfo(output); + } + + if (radeon_output->type == OUTPUT_DVI) { + RADEONGetTMDSInfo(output); + + // FIXME + /*if (i == 0) + RADEONGetHardCodedEDIDFromBIOS(output);*/ + + /*RADEONUpdatePanelSize(output);*/ + } + + if (radeon_output->DACType == DAC_TVDAC) { + RADEONGetTVDacAdjInfo(output); + } + +} + +/* + * initialise the static data sos we don't have to re-do at randr change */ +Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + xf86OutputPtr output; + const char *s; + int i = 0, second = 0, max_mt = 5; + + + /* We first get the information about all connectors from BIOS. + * This is how the card is phyiscally wired up. + * The information should be correct even on a OEM card. + * If not, we may have problem -- need to use MonitorLayout option. + */ + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + info->BiosConnector[i].DDCType = DDC_NONE_DETECTED; + info->BiosConnector[i].DACType = DAC_UNKNOWN; + info->BiosConnector[i].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[i].ConnectorType = CONNECTOR_NONE; + } + + if (!RADEONGetConnectorInfoFromBIOS(pScrn) || + ((info->BiosConnector[0].DDCType == 0) && + (info->BiosConnector[1].DDCType == 0))) { + if (info->IsMobility) { + /* Below is the most common setting, but may not be true */ + info->BiosConnector[0].DDCType = DDC_LCD; + info->BiosConnector[0].DACType = DAC_UNKNOWN; + info->BiosConnector[0].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[0].ConnectorType = CONNECTOR_PROPRIETARY; + + info->BiosConnector[1].DDCType = DDC_VGA; + info->BiosConnector[1].DACType = DAC_PRIMARY; + info->BiosConnector[1].TMDSType = TMDS_EXT; + info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; + } else { + /* Below is the most common setting, but may not be true */ + info->BiosConnector[0].DDCType = DDC_DVI; + info->BiosConnector[0].DACType = DAC_TVDAC; + info->BiosConnector[0].TMDSType = TMDS_INT; + info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I; + + info->BiosConnector[1].DDCType = DDC_VGA; + info->BiosConnector[1].DACType = DAC_PRIMARY; + info->BiosConnector[1].TMDSType = TMDS_EXT; + info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; + } + + /* Some cards have the DDC lines swapped and we have no way to + * detect it yet (Mac cards) + */ + if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) { + info->BiosConnector[0].DDCType = DDC_VGA; + info->BiosConnector[1].DDCType = DDC_DVI; + } + } + + /* always make TMDS_INT port first*/ + if (info->BiosConnector[1].TMDSType == TMDS_INT) { + RADEONSwapOutputs(pScrn); + } else if ((info->BiosConnector[0].TMDSType != TMDS_INT && + info->BiosConnector[1].TMDSType != TMDS_INT)) { + /* no TMDS_INT port, make primary DAC port first */ + /* On my Inspiron 8600 both internal and external ports are + marked DAC_PRIMARY in BIOS. So be extra careful - only + swap when the first port is not DAC_PRIMARY */ + if ((!(info->BiosConnector[0].ConnectorType == CONNECTOR_PROPRIETARY)) && (info->BiosConnector[1].DACType == DAC_PRIMARY) && + (info->BiosConnector[0].DACType != DAC_PRIMARY)) { + RADEONSwapOutputs(pScrn); + } + } + + if (info->HasSingleDAC) { + /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/ + if (info->BiosConnector[0].ConnectorType == CONNECTOR_CRT) { + info->BiosConnector[0].DACType = DAC_TVDAC; + info->BiosConnector[1].DACType = DAC_PRIMARY; + } else { + info->BiosConnector[1].DACType = DAC_TVDAC; + info->BiosConnector[0].DACType = DAC_PRIMARY; + } + } else if (!pRADEONEnt->HasCRTC2) { + info->BiosConnector[0].DACType = DAC_PRIMARY; + } + + for (i = 0 ; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); + if (!radeon_output) { + return FALSE; + } + radeon_output->MonType = MT_UNKNOWN; + radeon_output->ConnectorType = info->BiosConnector[i].ConnectorType; + if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D_ATOM) || + radeon_output->ConnectorType == CONNECTOR_DVI_D) + radeon_output->DACType = DAC_UNKNOWN; + else + radeon_output->DACType = info->BiosConnector[i].DACType; + radeon_output->DDCType = info->BiosConnector[i].DDCType; + radeon_output->TMDSType = info->BiosConnector[i].TMDSType; + + RADEONSetOutputType(pScrn, radeon_output); + output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); + if (!output) { + return FALSE; + } + output->driver_private = radeon_output; + output->possible_crtcs = 1; + if (radeon_output->type != OUTPUT_LVDS) + output->possible_crtcs |= 2; + + output->possible_clones = 0 /*1|2*/; + + RADEONInitConnector(output); + } + + /* if it's a mobility make sure we have a LVDS port */ + if (info->IsMobility) { + if (info->IsAtomBios) { + if (info->BiosConnector[0].ConnectorType != CONNECTOR_LVDS_ATOM && + info->BiosConnector[1].ConnectorType != CONNECTOR_LVDS_ATOM) { + /* add LVDS port */ + RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); + if (!radeon_output) { + return FALSE; + } + radeon_output->MonType = MT_UNKNOWN; + radeon_output->DDCType = DDC_LCD; + radeon_output->DACType = DAC_UNKNOWN; + radeon_output->TMDSType = TMDS_UNKNOWN; + radeon_output->ConnectorType = CONNECTOR_LVDS_ATOM; + RADEONSetOutputType(pScrn, radeon_output); + output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); + if (!output) { + return FALSE; + } + output->driver_private = radeon_output; + output->possible_crtcs = 1; + output->possible_clones = 0 /*1|2*/; + + RADEONInitConnector(output); + + } + } else { + if (info->BiosConnector[0].ConnectorType != CONNECTOR_PROPRIETARY && + info->BiosConnector[1].ConnectorType != CONNECTOR_PROPRIETARY) { + /* add LVDS port */ + RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); + if (!radeon_output) { + return FALSE; + } + radeon_output->MonType = MT_UNKNOWN; + radeon_output->DDCType = DDC_LCD; + radeon_output->DACType = DAC_UNKNOWN; + radeon_output->TMDSType = TMDS_UNKNOWN; + radeon_output->ConnectorType = CONNECTOR_PROPRIETARY; + RADEONSetOutputType(pScrn, radeon_output); + output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); + if (!output) { + return FALSE; + } + output->driver_private = radeon_output; + output->possible_crtcs = 1; + output->possible_clones = 0 /*1|2*/; + + RADEONInitConnector(output); + } + } + } + return TRUE; +} + |