diff options
author | Dave Airlie <airlied@linux.ie> | 2007-01-04 16:23:39 +1100 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2007-01-04 16:23:39 +1100 |
commit | 4f8a7cafdc77e98dc44f9eced876560b1ee01117 (patch) | |
tree | 465d5b5db01cc1c955155605d928933e7343a409 /src | |
parent | 52f749c8a613ee316044abe82156ee270412ced8 (diff) |
hook up crtc modesetting
Diffstat (limited to 'src')
-rw-r--r-- | src/radeon_display.c | 234 | ||||
-rw-r--r-- | src/radeon_driver.c | 167 | ||||
-rw-r--r-- | src/radeon_probe.h | 1 | ||||
-rw-r--r-- | src/radeon_randr.c | 27 |
4 files changed, 349 insertions, 80 deletions
diff --git a/src/radeon_display.c b/src/radeon_display.c index 7e8f76e..44848ef 100644 --- a/src/radeon_display.c +++ b/src/radeon_display.c @@ -2079,7 +2079,7 @@ void RADEONBlank(ScrnInfoPtr pScrn) (info->IsSwitching && (!info->IsSecondary))) { pPort = RADEONGetCrtcConnector(pScrn, 1); if (pPort) - RADEONBlankSet(pScrn, pPort); + RADEONBlankSet(pScrn, pPort); OUTREGP (RADEON_CRTC_EXT_CNTL, RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS | @@ -2159,11 +2159,11 @@ void RADEONUnblank(ScrnInfoPtr pScrn) pPort = RADEONGetCrtcConnector(pScrn, 1); if (pPort) RADEONUnblankSet(pScrn, pPort); - OUTREGP(RADEON_CRTC_EXT_CNTL, - 0, - ~(RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS)); + OUTREGP(RADEON_CRTC_EXT_CNTL, + 0, + ~(RADEON_CRTC_DISPLAY_DIS | + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS)); if (!pRADEONEnt->HasCRTC2) return; @@ -2407,6 +2407,17 @@ radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, { ScrnInfoPtr pScrn = crtc->scrn; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + + switch (radeon_crtc->crtc_id) { + case 0: + RADEONInit2(pScrn, mode, NULL, 1, &info->ModeReg); + break; + case 1: + RADEONInit2(pScrn, NULL, mode, 2, &info->ModeReg); + break; + } } static const xf86CrtcFuncsRec radeon_crtc_funcs = { @@ -2455,8 +2466,6 @@ static void radeon_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) { - - } static xf86OutputStatus @@ -2555,6 +2564,7 @@ Bool RADEONAllocatePortInfo(ScrnInfoPtr pScrn) if (!pRADEONEnt->PortInfo[i]) return FALSE; } + return TRUE; } void RADEONSetOutputType(ScrnInfoPtr pScrn, RADEONOutputPrivatePtr pRPort) @@ -2633,3 +2643,211 @@ xf86OutputPtr RADEONGetCrtcConnector(ScrnInfoPtr pScrn, int crtc_num) return pRADEONEnt->pOutput[1]; return NULL; } + + +void +RADEONCrtcSetBase(xf86CrtcPtr crtc, int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + int crtc_id = radeon_crtc->crtc_id; + unsigned long Start; + + RADEONDoAdjustFrame(pScrn, x, y, crtc_id); + + crtc->x = x; + crtc->y = y; +} + +Bool +RADEONCrtcInUse(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + for (i = 0; i < xf86_config->num_output; i++) + if (xf86_config->output[i]->crtc == crtc) + return TRUE; + return FALSE; +} + +Bool +RADEONCrtcSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + DisplayModePtr adjusted_mode; + RADEONInfoPtr info = RADEONPTR(pScrn); + int i , ret; + /* XXX: curMode */ + + adjusted_mode = xf86DuplicateMode(pMode); + + crtc->enabled = RADEONCrtcInUse (crtc); + + if (!crtc->enabled) { + return TRUE; + } + + /* Pass our mode to the outputs and the CRTC to give them a chance to + * adjust it according to limitations or output properties, and also + * a chance to reject the mode entirely. + */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + if (!output->funcs->mode_fixup(output, pMode, adjusted_mode)) { + ret = FALSE; + goto done; + } + } + + if (!crtc->funcs->mode_fixup(crtc, pMode, adjusted_mode)) { + ret = FALSE; + goto done; + } + + /* Disable the outputs and CRTCs before setting the mode. */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + /* Disable the output as the first thing we do. */ + output->funcs->dpms(output, DPMSModeOff); + } + + crtc->funcs->dpms(crtc, DPMSModeOff); + + /* Set up the DPLL and any output state that needs to adjust or depend + * on the DPLL. + */ + crtc->funcs->mode_set(crtc, pMode, adjusted_mode); + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc) + output->funcs->mode_set(output, pMode, adjusted_mode); + } + + /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ + crtc->funcs->dpms(crtc, DPMSModeOn); + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc) + output->funcs->dpms(output, DPMSModeOn); + } + + crtc->curMode = *pMode; + + /* XXX free adjustedmode */ + ret = TRUE; + + done: + return ret; +} + +/** + * 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; +} diff --git a/src/radeon_driver.c b/src/radeon_driver.c index d8eba3a..245f216 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -116,7 +116,7 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode); static void RADEONSave(ScrnInfoPtr pScrn); -static void RADEONRestore(ScrnInfoPtr pScrn); +//static void RADEONRestore(ScrnInfoPtr pScrn); static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); static void RADEONGetMergedFBOptions(ScrnInfoPtr pScrn); @@ -128,6 +128,8 @@ static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); #endif +DisplayModePtr +RADEONCrtcFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode); /* psuedo xinerama support */ extern Bool RADEONnoPanoramiXExtension; @@ -3827,6 +3829,7 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int hasDRI = 0; #ifdef RENDER int subPixelOrder = SubPixelUnknown; @@ -4126,7 +4129,25 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); info->ModeReg.surface_cntl &= ~RADEON_SURF_TRANSLATION_DIS; } else { - if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; + int i; + for (i = 0; i < xf86_config->num_crtc; i++) + { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + /* Mark that we'll need to re-set the mode for sure */ + memset(&crtc->curMode, 0, sizeof(crtc->curMode)); + if (!crtc->desiredMode.CrtcHDisplay) + crtc->desiredMode = *RADEONCrtcFindClosestMode (crtc, pScrn->currentMode); + + if (!RADEONCrtcSetMode (crtc, &crtc->desiredMode, TRUE)) + return FALSE; + + } + RADEONBlank(pScrn); + RADEONRestoreMode(pScrn, &info->ModeReg); + RADEONUnblank(pScrn); + + //if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; } RADEONSaveScreen(pScreen, SCREEN_SAVER_ON); @@ -5516,7 +5537,7 @@ static void RADEONSave(ScrnInfoPtr pScrn) } /* Restore the original (text) mode */ -static void RADEONRestore(ScrnInfoPtr pScrn) +void RADEONRestore(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; @@ -6388,60 +6409,63 @@ Bool RADEONInit2(ScrnInfoPtr pScrn, DisplayModePtr crtc1, { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - double dot_clock = crtc1->Clock/1000.0; + double dot_clock = 0; RADEONInfoPtr info0 = NULL; ScrnInfoPtr pScrn0 = NULL; #if RADEON_DEBUG - ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", - crtc1->name, - dot_clock, - - crtc1->HDisplay, - crtc1->HSyncStart, - crtc1->HSyncEnd, - crtc1->HTotal, - - crtc1->VDisplay, - crtc1->VSyncStart, - crtc1->VSyncEnd, - crtc1->VTotal, - pScrn->depth, - pScrn->bitsPerPixel); - if (crtc1->Flags & V_DBLSCAN) ErrorF(" D"); - if (crtc1->Flags & V_CSYNC) ErrorF(" C"); - if (crtc1->Flags & V_INTERLACE) ErrorF(" I"); - if (crtc1->Flags & V_PHSYNC) ErrorF(" +H"); - if (crtc1->Flags & V_NHSYNC) ErrorF(" -H"); - if (crtc1->Flags & V_PVSYNC) ErrorF(" +V"); - if (crtc1->Flags & V_NVSYNC) ErrorF(" -V"); - ErrorF("\n"); - ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", - crtc1->name, - dot_clock, - - crtc1->CrtcHDisplay, - crtc1->CrtcHSyncStart, - crtc1->CrtcHSyncEnd, - crtc1->CrtcHTotal, - - crtc1->CrtcVDisplay, - crtc1->CrtcVSyncStart, - crtc1->CrtcVSyncEnd, - crtc1->CrtcVTotal, - pScrn->depth, - pScrn->bitsPerPixel); - if (crtc1->Flags & V_DBLSCAN) ErrorF(" D"); - if (crtc1->Flags & V_CSYNC) ErrorF(" C"); - if (crtc1->Flags & V_INTERLACE) ErrorF(" I"); - if (crtc1->Flags & V_PHSYNC) ErrorF(" +H"); - if (crtc1->Flags & V_NHSYNC) ErrorF(" -H"); - if (crtc1->Flags & V_PVSYNC) ErrorF(" +V"); - if (crtc1->Flags & V_NVSYNC) ErrorF(" -V"); - ErrorF("\n"); + if (crtc1) { + ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", + crtc1->name, + dot_clock, + + crtc1->HDisplay, + crtc1->HSyncStart, + crtc1->HSyncEnd, + crtc1->HTotal, + + crtc1->VDisplay, + crtc1->VSyncStart, + crtc1->VSyncEnd, + crtc1->VTotal, + pScrn->depth, + pScrn->bitsPerPixel); + if (crtc1->Flags & V_DBLSCAN) ErrorF(" D"); + if (crtc1->Flags & V_CSYNC) ErrorF(" C"); + if (crtc1->Flags & V_INTERLACE) ErrorF(" I"); + if (crtc1->Flags & V_PHSYNC) ErrorF(" +H"); + if (crtc1->Flags & V_NHSYNC) ErrorF(" -H"); + if (crtc1->Flags & V_PVSYNC) ErrorF(" +V"); + if (crtc1->Flags & V_NVSYNC) ErrorF(" -V"); + ErrorF("\n"); + ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", + crtc1->name, + dot_clock, + + crtc1->CrtcHDisplay, + crtc1->CrtcHSyncStart, + crtc1->CrtcHSyncEnd, + crtc1->CrtcHTotal, + + crtc1->CrtcVDisplay, + crtc1->CrtcVSyncStart, + crtc1->CrtcVSyncEnd, + crtc1->CrtcVTotal, + pScrn->depth, + pScrn->bitsPerPixel); + if (crtc1->Flags & V_DBLSCAN) ErrorF(" D"); + if (crtc1->Flags & V_CSYNC) ErrorF(" C"); + if (crtc1->Flags & V_INTERLACE) ErrorF(" I"); + if (crtc1->Flags & V_PHSYNC) ErrorF(" +H"); + if (crtc1->Flags & V_NHSYNC) ErrorF(" -H"); + if (crtc1->Flags & V_PVSYNC) ErrorF(" +V"); + if (crtc1->Flags & V_NVSYNC) ErrorF(" -V"); + ErrorF("\n"); + info->Flags = crtc1->Flags; + } #endif - info->Flags = crtc1->Flags; + RADEONInitMemMapRegisters(pScrn, save, info); RADEONInitCommonRegisters(save, info); @@ -6469,14 +6493,20 @@ Bool RADEONInit2(ScrnInfoPtr pScrn, DisplayModePtr crtc1, /* if (!info->PaletteSavedOnVT) RADEONInitPalette(save); */ break; case 2: - pScrn0 = pRADEONEnt->pPrimaryScrn; - info0 = RADEONPTR(pScrn0); + if (pRADEONEnt->HasSecondary) { + pScrn0 = pRADEONEnt->pPrimaryScrn; + info0 = RADEONPTR(pScrn0); + } else { + pScrn0 = pScrn; + info0 = info; + } dot_clock = crtc2->Clock/1000.0; if (!RADEONInitCrtc2Registers(pScrn, save, crtc2, info)) return FALSE; RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->DisplayType != MT_CRT); /* Make sure primary has the same copy */ - memcpy(&info0->ModeReg, save, sizeof(RADEONSaveRec)); + if (pRADEONEnt->HasSecondary) + memcpy(&info0->ModeReg, save, sizeof(RADEONSaveRec)); break; case 3: if (!RADEONInitCrtcRegisters(pScrn, save, @@ -6498,7 +6528,7 @@ Bool RADEONInit2(ScrnInfoPtr pScrn, DisplayModePtr crtc1, return FALSE; } - RADEONTRACE(("RADEONInit returns %p\n", save)); + RADEONTRACE(("RADEONInit2 %d returns %p\n", crtc_mask, save)); return TRUE; } @@ -6850,6 +6880,7 @@ _X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); RADEONTRACE(("RADEONEnterVT\n")); @@ -6875,8 +6906,28 @@ _X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg); - } else - if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; + } else { + int i; + for (i = 0; i < xf86_config->num_crtc; i++) + { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + /* Mark that we'll need to re-set the mode for sure */ + memset(&crtc->curMode, 0, sizeof(crtc->curMode)); + if (!crtc->desiredMode.CrtcHDisplay) + crtc->desiredMode = *RADEONCrtcFindClosestMode (crtc, pScrn->currentMode); + + if (!RADEONCrtcSetMode (crtc, &crtc->desiredMode, TRUE)) + return FALSE; + + } + RADEONBlank(pScrn); + RADEONRestoreMode(pScrn, &info->ModeReg); + RADEONUnblank(pScrn); + } +#if 0 + if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; +#endif if (!info->IsSecondary) RADEONRestoreSurfaces(pScrn, &info->ModeReg); @@ -7293,7 +7344,7 @@ RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) } /* xf86SetDDCproperties(info->CRT2pScrn, pRADEONEnt->MonInfo2); */ - if (pOutput = RADEONGetCrtcConnector(pScrn, 2)) + if ((pOutput = RADEONGetCrtcConnector(pScrn, 2))) info->CRT2pScrn->monitor->DDC = pOutput->MonInfo; else info->CRT2pScrn->monitor->DDC = NULL; diff --git a/src/radeon_probe.h b/src/radeon_probe.h index 977790c..817a40b 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -116,7 +116,6 @@ typedef enum } RADEONOutputType; typedef struct _RADEONCrtcPrivateRec { - int crtc; int crtc_id; int binding; Bool IsActive; diff --git a/src/radeon_randr.c b/src/radeon_randr.c index fef3667..29af262 100644 --- a/src/radeon_randr.c +++ b/src/radeon_randr.c @@ -636,31 +636,32 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, RADEON_SYNC(info, pScrn); if (mode) { - if (pRcrtc->crtc_id == 0) - ret = RADEONInit2(pScrn, mode, NULL, 1, &info->ModeReg); - else if (pRcrtc->crtc_id == 1) - ret = RADEONInit2(pScrn, NULL, mode, 2, &info->ModeReg); - - if (!ret) { + + if (!RADEONCrtcSetMode (crtc, mode, TRUE)) + { crtc->enabled = save_enabled; - for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = config->output[o]; + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; output->crtc = save_crtcs[o]; } DEALLOCATE_LOCAL(save_crtcs); return FALSE; } crtc->desiredMode = *mode; - - pScrn->vtSema = TRUE; + + RADEONBlank(pScrn); RADEONRestoreMode(pScrn, &info->ModeReg); RADEONUnblank(pScrn); - - if (info->DispPriority) - RADEONInitDispBandwidth(pScrn); + } + // if (info->DispPriority) + // RADEONInitDispBandwidth(pScrn); + } + if (pos_changed && mode) + RADEONCrtcSetBase(crtc, x, y); DEALLOCATE_LOCAL(save_crtcs); return xf86RandR12CrtcNotify (randr_crtc); } |