diff options
-rw-r--r-- | src/i830.h | 13 | ||||
-rw-r--r-- | src/i830_crt.c | 17 | ||||
-rw-r--r-- | src/i830_display.c | 6 | ||||
-rw-r--r-- | src/i830_driver.c | 145 | ||||
-rw-r--r-- | src/i830_dvo.c | 5 | ||||
-rw-r--r-- | src/i830_lvds.c | 5 | ||||
-rw-r--r-- | src/i830_modes.c | 239 | ||||
-rw-r--r-- | src/i830_randr.c | 548 | ||||
-rw-r--r-- | src/i830_sdvo.c | 14 | ||||
-rw-r--r-- | src/i830_tv.c | 8 | ||||
-rw-r--r-- | src/i830_xf86Crtc.c | 502 | ||||
-rw-r--r-- | src/i830_xf86Crtc.h | 47 |
12 files changed, 701 insertions, 848 deletions
@@ -192,12 +192,6 @@ struct _I830DVODriver { extern const char *i830_output_type_names[]; -enum detect_status { - OUTPUT_STATUS_CONNECTED, - OUTPUT_STATUS_DISCONNECTED, - OUTPUT_STATUS_UNKNOWN -}; - typedef struct _I830CrtcPrivateRec { int pipe; Bool gammaEnabled; @@ -606,6 +600,9 @@ extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem); extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name); +/* return a mask of output indices matching outputs against type_mask */ +int i830_output_clones (ScrnInfoPtr pScrn, int type_mask); + /* i830_display.c */ Bool i830PipeHasType (xf86CrtcPtr crtc, int type); @@ -627,10 +624,6 @@ Bool I830BindAGPMemory(ScrnInfoPtr pScrn); Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn); /* i830_modes.c */ -int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time); -void i830_reprobe_output_modes(ScrnInfoPtr pScrn); -void i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn); -void i830_set_default_screen_size(ScrnInfoPtr pScrn); DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output); /* i830_tv.c */ diff --git a/src/i830_crt.c b/src/i830_crt.c index bf23f9eb..1bb52d41 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -272,7 +272,7 @@ i830_crt_detect_ddc(xf86OutputPtr output) * @param allow_disturb enables detection methods that may cause flickering * on active displays. */ -static enum detect_status +static xf86OutputStatus i830_crt_detect(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; @@ -281,13 +281,13 @@ i830_crt_detect(xf86OutputPtr output) if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830)) { if (i830_crt_detect_hotplug(output)) - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; else - return OUTPUT_STATUS_DISCONNECTED; + return XF86OutputStatusDisconnected; } if (i830_crt_detect_ddc(output)) - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; /* Use the load-detect method if we have no other way of telling. */ crtc = i830GetLoadDetectPipe (output); @@ -318,12 +318,12 @@ i830_crt_detect(xf86OutputPtr output) i830ReleaseLoadDetectPipe (output); if (connected) - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; else - return OUTPUT_STATUS_DISCONNECTED; + return XF86OutputStatusDisconnected; } - return OUTPUT_STATUS_UNKNOWN; + return XF86OutputStatusUnknown; } static DisplayModePtr @@ -337,7 +337,7 @@ i830_crt_get_modes(xf86OutputPtr output) if (modes != NULL) return modes; - if ((*output->funcs->detect)(output) == OUTPUT_STATUS_DISCONNECTED) + if ((*output->funcs->detect)(output) == XF86OutputStatusDisconnected) return NULL; /* We've got a potentially-connected monitor that we can't DDC. Return a @@ -393,6 +393,7 @@ i830_crt_init(ScrnInfoPtr pScrn) return; } i830_output->type = I830_OUTPUT_ANALOG; + output->driver_private = i830_output; /* Set up the DDC bus. */ diff --git a/src/i830_display.c b/src/i830_display.c index ac56528a..1f41cc31 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -912,15 +912,15 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) { + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); Bool ok = TRUE; - int i; + xf86CrtcPtr crtc = config->output[config->compat_output]->crtc; DPRINTF(PFX, "i830SetMode\n"); - for (i = 0; i < pI830->xf86_config.num_crtc; i++) + if (crtc && crtc->enabled) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; ok = i830PipeSetMode(crtc, i830PipeFindClosestMode(crtc, pMode), TRUE); diff --git a/src/i830_driver.c b/src/i830_driver.c index 73af1471..ad25a77e 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -686,6 +686,23 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, pI830->CursorInfoRec->ShowCursor(pScrn); } +int +i830_output_clones (ScrnInfoPtr pScrn, int type_mask) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); + int o; + int index_mask = 0; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + I830OutputPrivatePtr intel_output = output->driver_private; + if (type_mask & (1 << intel_output->type)) + index_mask |= (1 << o); + } + return index_mask; +} + /** * Set up the outputs according to what type of chip we are. * @@ -695,7 +712,9 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, static void I830SetupOutputs(ScrnInfoPtr pScrn) { - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); + I830Ptr pI830 = I830PTR(pScrn); + int o; /* everyone has at least a single analog output */ i830_crt_init(pScrn); @@ -712,6 +731,44 @@ I830SetupOutputs(ScrnInfoPtr pScrn) } if (IS_I915GM(pI830) || IS_I945GM(pI830)) i830_tv_init(pScrn); + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + I830OutputPrivatePtr intel_output = output->driver_private; + int crtc_mask = 0, clone_mask = 0; + + /* + * Valid crtcs + */ + switch (intel_output->type) { + case I830_OUTPUT_DVO: + case I830_OUTPUT_SDVO: + crtc_mask = ((1 << 0)| + (1 << 1)); + clone_mask = ((1 << I830_OUTPUT_ANALOG) | + (1 << I830_OUTPUT_DVO) | + (1 << I830_OUTPUT_SDVO)); + break; + case I830_OUTPUT_ANALOG: + crtc_mask = ((1 << 0)); + clone_mask = ((1 << I830_OUTPUT_ANALOG) | + (1 << I830_OUTPUT_DVO) | + (1 << I830_OUTPUT_SDVO)); + break; + case I830_OUTPUT_LVDS: + crtc_mask = (1 << 1); + clone_mask = (1 << I830_OUTPUT_LVDS); + break; + case I830_OUTPUT_TVOUT: + crtc_mask = ((1 << 0) | + (1 << 1)); + clone_mask = (1 << I830_OUTPUT_TVOUT); + break; + } + output->possible_crtcs = crtc_mask; + output->possible_clones = i830_output_clones (pScrn, clone_mask); + } } /** @@ -883,7 +940,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) #ifdef XF86DRI unsigned long savedMMSize; #endif - enum detect_status output_status[MAX_OUTPUTS]; if (pScrn->numEntities != 1) return FALSE; @@ -1375,64 +1431,20 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) { xf86OutputPtr output = pI830->xf86_config.output[i]; - output_status[i] = (*output->funcs->detect) (output); + output->status = (*output->funcs->detect) (output); } #if 0 RestoreHWState (pScrn); #endif - - for (i = 0; i < pI830->xf86_config.num_output; i++) - { - xf86OutputPtr output = pI830->xf86_config.output[i]; - I830OutputPrivatePtr intel_output = output->driver_private; - xf86CrtcPtr crtc; - int p; - - output->crtc = NULL; - - if (output_status[i] == OUTPUT_STATUS_DISCONNECTED) - continue; - - switch (intel_output->type) { - case I830_OUTPUT_LVDS: - /* LVDS must live on pipe B for two-pipe devices */ - crtc = pI830->xf86_config.crtc[pI830->xf86_config.num_crtc - 1]; - if (!i830PipeInUse (crtc)) - output->crtc = crtc; - break; - case I830_OUTPUT_ANALOG: - case I830_OUTPUT_DVO: - case I830_OUTPUT_SDVO: - for (p = 0; p < pI830->xf86_config.num_crtc; p++) - { - crtc = pI830->xf86_config.crtc[p]; - if (!i830PipeInUse(crtc)) - { - output->crtc = crtc; - break; - } - } - break; - case I830_OUTPUT_TVOUT: - crtc = pI830->xf86_config.crtc[0]; - if (!i830PipeInUse(crtc)) - { - output->crtc = crtc; - } - break; - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n"); - break; - } - } - - for (i = 0; i < pI830->xf86_config.num_crtc; i++) + if (!xf86InitialConfiguration (pScrn)) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; - crtc->enabled = i830PipeInUse(crtc); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + PreInitCleanup(pScrn); + return FALSE; } - + pScrn->displayWidth = (pScrn->virtualX + 63) & ~63; + pI830->rotation = RR_Rotate_0; if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) { pI830->InitialRotation = 0; @@ -1677,7 +1689,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) if (!xf86RandR12PreInit (pScrn)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); PreInitCleanup(pScrn); return FALSE; } @@ -3398,23 +3410,21 @@ static void i830AdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); - int i; + xf86CrtcPtr crtc = config->output[config->compat_output]->crtc; DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", x, pI830->xoffset, y, pI830->yoffset); - /* Sync the engine before adjust frame */ - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - } - - for (i = 0; i < pI830->xf86_config.num_crtc; i++) + if (crtc && crtc->enabled) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; - if (crtc->enabled) - i830PipeSetBase(crtc, x, y); + /* Sync the engine before adjust frame */ + if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { + (*pI830->AccelInfoRec->Sync)(pScrn); + pI830->AccelInfoRec->NeedToSync = FALSE; + } + i830PipeSetBase(crtc, x, y); } } @@ -3815,7 +3825,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) DPRINTF(PFX, "\nUnmapping memory\n"); I830UnmapMem(pScrn); vgaHWUnmapMem(pScrn); - xf86CrtcCloseScreen (pScreen); if (pI830->ScanlineColorExpandBuffers) { xfree(pI830->ScanlineColorExpandBuffers); @@ -4017,7 +4026,9 @@ I830CheckDevicesTimer(OsTimerPtr timer, CARD32 now, pointer arg) * implements a sensible policy using RandR-1.2. For now, all we get * is this. */ - I830ValidateXF86ModeList(pScrn, FALSE); + + xf86ProbeOutputModes (pScrn); + xf86SetScrnInfoModes (pScrn); xf86SwitchMode(pScrn->pScreen, pScrn->currentMode); /* Clear the BIOS's hotkey press flags */ diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 6fe31575..ccd08468 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -164,10 +164,10 @@ i830_dvo_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode) * * Unimplemented. */ -static enum detect_status +static xf86OutputStatus i830_dvo_detect(xf86OutputPtr output) { - return OUTPUT_STATUS_UNKNOWN; + return XF86OutputStatusUnknown; } static Bool @@ -248,6 +248,7 @@ i830_dvo_init(ScrnInfoPtr pScrn) } intel_output->type = I830_OUTPUT_DVO; output->driver_private = intel_output; + output->subpixel_order = SubPixelHorizontalRGB; /* Set up the I2C and DDC buses */ ret = I830I2CInit(pScrn, &intel_output->pI2CBus, GPIOE, "DVOI2C_E"); diff --git a/src/i830_lvds.c b/src/i830_lvds.c index cf709569..5f0c01bb 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -180,10 +180,10 @@ i830_lvds_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode) * This always returns OUTPUT_STATUS_CONNECTED. This output should only have * been set up if the LVDS was actually connected anyway. */ -static enum detect_status +static xf86OutputStatus i830_lvds_detect(xf86OutputPtr output) { - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; } /** @@ -293,6 +293,7 @@ i830_lvds_init(ScrnInfoPtr pScrn) } intel_output->type = I830_OUTPUT_LVDS; output->driver_private = intel_output; + output->subpixel_order = SubPixelHorizontalRGB; /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. diff --git a/src/i830_modes.c b/src/i830_modes.c index a0d79db9..34f6cd52 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -57,245 +57,6 @@ #define DEBUG_REPROBE 1 -static DisplayModePtr -i830GetModeListTail(DisplayModePtr pModeList) -{ - DisplayModePtr last; - - if (pModeList == NULL) - return NULL; - - for (last = pModeList; last->next != NULL; last = last->next) - ; - - return last; -} - -/** - * This function removes a mode from a list of modes. It should probably be - * moved to xf86Mode.c. - * - * There are different types of mode lists: - * - * - singly linked linear lists, ending in NULL - * - doubly linked linear lists, starting and ending in NULL - * - doubly linked circular lists - * - */ - -static void -I830xf86DeleteModeFromList(DisplayModePtr *modeList, DisplayModePtr mode) -{ - /* Catch the easy/insane cases */ - if (modeList == NULL || *modeList == NULL || mode == NULL) - return; - - /* If the mode is at the start of the list, move the start of the list */ - if (*modeList == mode) - *modeList = mode->next; - - /* If mode is the only one on the list, set the list to NULL */ - if ((mode == mode->prev) && (mode == mode->next)) { - *modeList = NULL; - } else { - if ((mode->prev != NULL) && (mode->prev->next == mode)) - mode->prev->next = mode->next; - if ((mode->next != NULL) && (mode->next->prev == mode)) - mode->next->prev = mode->prev; - } -} - -void -i830_reprobe_output_modes(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - Bool properties_set = FALSE; - int i; - - /* Re-probe the list of modes for each output. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) - { - xf86OutputPtr output = pI830->xf86_config.output[i]; - DisplayModePtr mode; - - while (output->probed_modes != NULL) - xf86DeleteMode(&output->probed_modes, output->probed_modes); - - output->probed_modes = (*output->funcs->get_modes) (output); - - /* Set the DDC properties to whatever first output has DDC information. - */ - if (output->MonInfo != NULL && !properties_set) { - xf86SetDDCproperties(pScrn, output->MonInfo); - properties_set = TRUE; - } - - if (output->probed_modes != NULL) - { - /* silently prune modes down to ones matching the user's - * configuration. - */ - i830xf86ValidateModesUserConfig(pScrn, output->probed_modes); - i830xf86PruneInvalidModes(pScrn, &output->probed_modes, FALSE); - } - -#ifdef DEBUG_REPROBE - if (output->probed_modes != NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Printing probed modes for output %s\n", - output->name); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No remaining probed modes for output %s\n", - output->name); - } -#endif - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - { - /* The code to choose the best mode per pipe later on will require - * VRefresh to be set. - */ - mode->VRefresh = xf86ModeVRefresh(mode); - xf86SetModeCrtc(mode, INTERLACE_HALVE_V); - -#ifdef DEBUG_REPROBE - xf86PrintModeline(pScrn->scrnIndex, mode); -#endif - } - } -} - -/** - * Constructs pScrn->modes from the output mode lists. - * - * Currently it only takes one output's mode list and stuffs it into the - * XFree86 DDX mode list while trimming it for root window size. - * - * This should be obsoleted by RandR 1.2 hopefully. - */ -void -i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr saved_mode, last; - int originalVirtualX, originalVirtualY; - int i; - - /* Remove the current mode from the modelist if we're re-validating, so we - * can find a new mode to map ourselves to afterwards. - */ - saved_mode = pI830->currentMode; - if (saved_mode != NULL) { - I830xf86DeleteModeFromList(&pScrn->modes, saved_mode); - } - - /* Clear any existing modes from pScrn->modes */ - while (pScrn->modes != NULL) - xf86DeleteMode(&pScrn->modes, pScrn->modes); - - /* Set pScrn->modes to the mode list for an arbitrary output. - * pScrn->modes should only be used for XF86VidMode now, which we don't - * care about enough to make some sort of unioned list. - */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; - if (output->probed_modes != NULL) { - pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes); - break; - } - } - - xf86RandR12GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY); - - /* Disable modes in the XFree86 DDX list that are larger than the current - * virtual size. - */ - i830xf86ValidateModesSize(pScrn, pScrn->modes, - originalVirtualX, originalVirtualY, - pScrn->displayWidth); - - /* Strip out anything that we threw out for virtualX/Y. */ - i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE); - - if (pScrn->modes == NULL) { - FatalError("No modes left for XFree86 DDX\n"); - } - - /* For some reason, pScrn->modes is circular, unlike the other mode lists. - * How great is that? - */ - last = i830GetModeListTail(pScrn->modes); - last->next = pScrn->modes; - pScrn->modes->prev = last; - - /* Save a pointer to the previous current mode. We can't reset - * pScrn->currentmode, because we rely on xf86SwitchMode's shortcut not - * happening so we can hot-enable devices at SwitchMode. We'll notice this - * case at SwitchMode and free the saved mode. - */ - pI830->savedCurrentMode = saved_mode; -} - -/** - * Takes the output mode lists and decides the default root window size - * and framebuffer pitch. - */ -void -i830_set_default_screen_size(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int maxX = -1, maxY = -1; - int i; - - /* Set up a virtual size that will cover any clone mode we'd want to - * set for the currently-connected outputs. - */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; - DisplayModePtr mode; - - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - { - if (mode->HDisplay > maxX) - maxX = mode->HDisplay; - if (mode->VDisplay > maxY) - maxY = mode->VDisplay; - } - } - /* let the user specify a bigger virtual size if they like */ - if (pScrn->display->virtualX > maxX) - maxX = pScrn->display->virtualX; - if (pScrn->display->virtualY > maxY) - maxY = pScrn->display->virtualY; - pScrn->virtualX = maxX; - pScrn->virtualY = maxY; - pScrn->displayWidth = (maxX + 63) & ~63; -} - -/** - * Probes for video modes on attached otuputs, and assembles a list to insert - * into pScrn. - * - * \param first_time indicates that the memory layout has already been set up, - * so displayWidth, virtualX, and virtualY shouldn't be touched. - * - * A SetMode must follow this call in order for operatingDevices to match the - * hardware's state, in case we detect a new output device. - */ -int -I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) -{ - i830_reprobe_output_modes(pScrn); - - if (first_time) { - i830_set_default_screen_size(pScrn); - } - - i830_set_xf86_modes_from_outputs(pScrn); - - return 1; /* XXX */ -} - #ifdef RANDR_12_INTERFACE #define EDID_ATOM_NAME "EDID_DATA" diff --git a/src/i830_randr.c b/src/i830_randr.c index 00770201..94d2221b 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -94,7 +94,8 @@ xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations) } /* Re-probe the outputs for new monitors or modes */ - I830ValidateXF86ModeList(scrp, FALSE); + xf86ProbeOutputModes (scrp); + xf86SetScrnInfoModes (scrp); for (mode = scrp->modes; ; mode = mode->next) { @@ -246,13 +247,13 @@ xf86RandR12SetConfig (ScreenPtr pScreen, int rate, RRScreenSizePtr pSize) { - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - DisplayModePtr mode; - int px, py; - Bool useVirtual = FALSE; - int maxX = 0, maxY = 0; - Rotation oldRotation = randrp->rotation; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int px, py; + Bool useVirtual = FALSE; + int maxX = 0, maxY = 0; + Rotation oldRotation = randrp->rotation; randrp->rotation = rotation; @@ -487,15 +488,15 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) { ScreenPtr pScreen = randr_crtc->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); RRModePtr randr_mode = NULL; int x; int y; Rotation rotation; int numOutputs; - RROutputPtr randr_outputs[MAX_OUTPUTS]; + RROutputPtr randr_outputs[XF86_MAX_OUTPUT]; RROutputPtr randr_output; - xf86CrtcPtr crtc = randr_crtc->devPrivate; + xf86CrtcPtr crtc = randr_crtc->devPrivate; xf86OutputPtr output; int i, j; DisplayModePtr curMode = &crtc->curMode; @@ -505,9 +506,9 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) rotation = RR_Rotate_0; numOutputs = 0; randr_mode = NULL; - for (i = 0; i < pI830->xf86_config.num_output; i++) + for (i = 0; i < config->num_output; i++) { - output = pI830->xf86_config.output[i]; + output = config->output[i]; if (output->crtc == crtc) { randr_output = output->randr_output; @@ -542,12 +543,13 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, RROutputPtr *randr_outputs) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); - xf86CrtcPtr crtc = randr_crtc->devPrivate; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc = randr_crtc->devPrivate; DisplayModePtr mode = randr_mode ? randr_mode->devPrivate : NULL; Bool changed = FALSE; + Bool pos_changed; int o, ro; - xf86CrtcPtr save_crtcs[MAX_OUTPUTS]; + xf86CrtcPtr save_crtcs[XF86_MAX_OUTPUT]; Bool save_enabled = crtc->enabled; if ((mode != NULL) != crtc->enabled) @@ -555,9 +557,12 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, else if (mode && !xf86ModesEqual (&crtc->curMode, mode)) changed = TRUE; - for (o = 0; o < pI830->xf86_config.num_output; o++) + pos_changed = changed; + if (x != crtc->x || y != crtc->y) + pos_changed = TRUE; + for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = pI830->xf86_config.output[o]; + xf86OutputPtr output = config->output[o]; xf86CrtcPtr new_crtc; save_crtcs[o] = output->crtc; @@ -578,10 +583,12 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, output->crtc = new_crtc; } } + /* XXX need device-independent mode setting code through an API */ if (changed) { + I830Ptr pI830 = I830PTR(pScrn); crtc->enabled = mode != NULL; - + /* Sync the engine before adjust mode */ if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { (*pI830->AccelInfoRec->Sync)(pScrn); @@ -593,18 +600,19 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, if (!i830PipeSetMode (crtc, mode, TRUE)) { crtc->enabled = save_enabled; - for (o = 0; o < pI830->xf86_config.num_output; o++) + for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = pI830->xf86_config.output[o]; + xf86OutputPtr output = config->output[o]; output->crtc = save_crtcs[o]; } return FALSE; } crtc->desiredMode = *mode; - i830PipeSetBase(crtc, x, y); } i830DisableUnusedFunctions (pScrn); } + if (pos_changed && mode) + i830PipeSetBase(crtc, x, y); return xf86RandR12CrtcNotify (randr_crtc); } @@ -620,7 +628,7 @@ xf86RandR12CrtcSetGamma (ScreenPtr pScreen, * RandR modes and assign them to the output */ static Bool -I830xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) +xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) { DisplayModePtr mode; RRModePtr *rrmodes = NULL; @@ -660,8 +668,8 @@ I830xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) modeInfo.modeFlags = mode->Flags; rrmode = RRModeGet (&modeInfo, mode->name); - rrmode->devPrivate = mode; if (rrmode) { + rrmode->devPrivate = mode; rrmodes[nmode++] = rrmode; npreferred += pref; } @@ -679,64 +687,25 @@ I830xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) * Mirror the current mode configuration to RandR */ static Bool -xf86RandR12SetInfo12 (ScrnInfoPtr pScrn) +xf86RandR12SetInfo12 (ScreenPtr pScreen) { - I830Ptr pI830 = I830PTR(pScrn); - RROutputPtr clones[MAX_OUTPUTS]; - RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; - int ncrtc; - int o, c, p; - int clone_types; - int crtc_types; - int subpixel; - RRCrtcPtr randr_crtc; - int nclone; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + RROutputPtr clones[XF86_MAX_OUTPUT]; + RRCrtcPtr crtcs[XF86_MAX_CRTC]; + int ncrtc; + int o, c, l; + RRCrtcPtr randr_crtc; + int nclone; - for (o = 0; o < pI830->xf86_config.num_output; o++) + for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = pI830->xf86_config.output[o]; - I830OutputPrivatePtr intel_output = output->driver_private; - /* - * Valid crtcs - */ - switch (intel_output->type) { - case I830_OUTPUT_DVO: - case I830_OUTPUT_SDVO: - crtc_types = ((1 << 0)| - (1 << 1)); - clone_types = ((1 << I830_OUTPUT_ANALOG) | - (1 << I830_OUTPUT_DVO) | - (1 << I830_OUTPUT_SDVO)); - subpixel = SubPixelHorizontalRGB; - break; - case I830_OUTPUT_ANALOG: - crtc_types = ((1 << 0)); - clone_types = ((1 << I830_OUTPUT_ANALOG) | - (1 << I830_OUTPUT_DVO) | - (1 << I830_OUTPUT_SDVO)); - subpixel = SubPixelNone; - break; - case I830_OUTPUT_LVDS: - crtc_types = (1 << 1); - clone_types = (1 << I830_OUTPUT_LVDS); - subpixel = SubPixelHorizontalRGB; - break; - case I830_OUTPUT_TVOUT: - crtc_types = ((1 << 0) | - (1 << 1)); - clone_types = (1 << I830_OUTPUT_TVOUT); - subpixel = SubPixelNone; - break; - default: - crtc_types = 0; - clone_types = 0; - subpixel = SubPixelUnknown; - break; - } + xf86OutputPtr output = config->output[o]; + ncrtc = 0; - for (p = 0; p < pI830->xf86_config.num_crtc; p++) - if (crtc_types & (1 << p)) - crtcs[ncrtc++] = pI830->xf86_config.crtc[p]->randr_crtc; + for (c = 0; c < config->num_crtc; c++) + if (output->possible_crtcs & (1 << c)) + crtcs[ncrtc++] = config->crtc[c]->randr_crtc; if (output->crtc) randr_crtc = output->crtc->randr_crtc; @@ -750,32 +719,31 @@ xf86RandR12SetInfo12 (ScrnInfoPtr pScrn) RROutputSetPhysicalSize(output->randr_output, output->mm_width, output->mm_height); - I830xf86RROutputSetModes (output->randr_output, output->probed_modes); + xf86RROutputSetModes (output->randr_output, output->probed_modes); - switch ((*output->funcs->detect)(output)) { - case OUTPUT_STATUS_CONNECTED: + switch (output->status = (*output->funcs->detect)(output)) { + case XF86OutputStatusConnected: RROutputSetConnection (output->randr_output, RR_Connected); break; - case OUTPUT_STATUS_DISCONNECTED: + case XF86OutputStatusDisconnected: RROutputSetConnection (output->randr_output, RR_Disconnected); break; - case OUTPUT_STATUS_UNKNOWN: + case XF86OutputStatusUnknown: RROutputSetConnection (output->randr_output, RR_UnknownConnection); break; } - RROutputSetSubpixelOrder (output->randr_output, subpixel); + RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order); /* * Valid clones */ nclone = 0; - for (c = 0; c < pI830->xf86_config.num_output; c++) + for (l = 0; l < config->num_output; l++) { - xf86OutputPtr clone = pI830->xf86_config.output[c]; - I830OutputPrivatePtr intel_clone = clone->driver_private; + xf86OutputPtr clone = config->output[l]; - if (o != c && ((1 << intel_clone->type) & clone_types)) + if (l != o && (output->possible_clones & (1 << l))) clones[nclone++] = clone->randr_output; } if (!RROutputSetClones (output->randr_output, clones, nclone)) @@ -793,15 +761,18 @@ xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - i830_reprobe_output_modes(pScrn); - return xf86RandR12SetInfo12 (pScrn); + xf86ProbeOutputModes (pScrn); + xf86SetScrnInfoModes (pScrn); + return xf86RandR12SetInfo12 (pScreen); } static Bool -xf86RandR12CreateObjects12 (ScrnInfoPtr pScrn) +xf86RandR12CreateObjects12 (ScreenPtr pScreen) { - I830Ptr pI830 = I830PTR(pScrn); - int p; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + int o; if (!RRInit ()) return FALSE; @@ -809,45 +780,47 @@ xf86RandR12CreateObjects12 (ScrnInfoPtr pScrn) /* * Configure crtcs */ - for (p = 0; p < pI830->xf86_config.num_crtc; p++) + for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[p]; + xf86CrtcPtr crtc = config->crtc[c]; + crtc->randr_crtc = RRCrtcCreate (crtc); + RRCrtcAttachScreen (crtc->randr_crtc, pScreen); RRCrtcGammaSetSize (crtc->randr_crtc, 256); } + /* + * Configure outputs + */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + output->randr_output = RROutputCreate (output->name, + strlen (output->name), + output); + RROutputAttachScreen (output->randr_output, pScreen); + } return TRUE; } static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) { - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - I830Ptr pI830 = I830PTR(pScrn); - int p, o; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int c; int width, height; /* - * Attach RandR objects to screen - */ - for (p = 0; p < pI830->xf86_config.num_crtc; p++) - if (!RRCrtcAttachScreen (pI830->xf86_config.crtc[p]->randr_crtc, pScreen)) - return FALSE; - - for (o = 0; o < pI830->xf86_config.num_output; o++) - if (!RROutputAttachScreen (pI830->xf86_config.output[o]->randr_output, pScreen)) - return FALSE; - - /* * Compute width of screen */ width = 0; height = 0; - for (p = 0; p < pI830->xf86_config.num_crtc; p++) + for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[p]; - int crtc_width = crtc->x + crtc->curMode.HDisplay; - int crtc_height = crtc->y + crtc->curMode.VDisplay; + xf86CrtcPtr crtc = config->crtc[c]; + int crtc_width = crtc->x + crtc->curMode.HDisplay; + int crtc_height = crtc->y + crtc->curMode.VDisplay; if (crtc->enabled && crtc_width > width) width = crtc_width; @@ -869,14 +842,14 @@ xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) "Setting screen physical size to %d x %d\n", mmWidth, mmHeight); xf86RandR12ScreenSetSize (pScreen, - width, - height, - mmWidth, - mmHeight); + width, + height, + mmWidth, + mmHeight); } - for (p = 0; p < pI830->xf86_config.num_crtc; p++) - xf86RandR12CrtcNotify (pI830->xf86_config.crtc[p]->randr_crtc); + for (c = 0; c < config->num_crtc; c++) + xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); if (randrp->virtualX == -1 || randrp->virtualY == -1) { @@ -900,356 +873,27 @@ xf86RandR12Init12 (ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; rrScrPrivPtr rp = rrGetScrPriv(pScreen); - if (xf86CrtcScreenInit (pScreen)) - return FALSE; - rp->rrGetInfo = xf86RandR12GetInfo12; rp->rrScreenSetSize = xf86RandR12ScreenSetSize; rp->rrCrtcSet = xf86RandR12CrtcSet; rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma; rp->rrSetConfig = NULL; pScrn->PointerMoved = xf86RandR12PointerMoved; - return TRUE; -} - -static RRModePtr -I830RRDefaultMode (RROutputPtr output) -{ - RRModePtr target_mode = NULL; - int target_diff = 0; - int mmHeight; - int num_modes; - int m; - - num_modes = output->numPreferred ? output->numPreferred : output->numModes; - mmHeight = output->mmHeight; - if (!mmHeight) - mmHeight = 203; /* 768 pixels at 96dpi */ - /* - * Pick a mode closest to 96dpi - */ - for (m = 0; m < num_modes; m++) - { - RRModePtr mode = output->modes[m]; - int dpi; - int diff; - - dpi = (mode->mode.height * 254) / (mmHeight * 10); - diff = dpi - 96; - diff = diff < 0 ? -diff : diff; - if (target_mode == NULL || diff < target_diff) - { - target_mode = mode; - target_diff = diff; - } - } - return target_mode; -} - -static RRModePtr -I830ClosestMode (RROutputPtr output, RRModePtr match) -{ - RRModePtr target_mode = NULL; - int target_diff = 0; - int m; - - /* - * Pick a mode closest to the specified mode - */ - for (m = 0; m < output->numModes; m++) - { - RRModePtr mode = output->modes[m]; - int dx, dy; - int diff; - - /* exact matches are preferred */ - if (mode == match) - return mode; - - dx = match->mode.width - mode->mode.width; - dy = match->mode.height - mode->mode.height; - diff = dx * dx + dy * dy; - if (target_mode == NULL || diff < target_diff) - { - target_mode = mode; - target_diff = diff; - } - } - return target_mode; -} - -static int -I830RRPickCrtcs (RROutputPtr *outputs, - RRCrtcPtr *best_crtcs, - RRModePtr *modes, - int num_output, - int n) -{ - int c, o, l; - RROutputPtr output; - RRCrtcPtr crtc; - RRCrtcPtr *crtcs; - RRCrtcPtr best_crtc; - int best_score; - int score; - int my_score; - - if (n == num_output) - return 0; - output = outputs[n]; - - /* - * Compute score with this output disabled - */ - best_crtcs[n] = NULL; - best_crtc = NULL; - best_score = I830RRPickCrtcs (outputs, best_crtcs, modes, num_output, n+1); - if (modes[n] == NULL) - return best_score; - - crtcs = xalloc (num_output * sizeof (RRCrtcPtr)); - if (!crtcs) - return best_score; - - my_score = 1; - /* Score outputs that are known to be connected higher */ - if (output->connection == RR_Connected) - my_score++; - /* Score outputs with preferred modes higher */ - if (output->numPreferred) - my_score++; - /* - * Select a crtc for this output and - * then attempt to configure the remaining - * outputs - */ - for (c = 0; c < output->numCrtcs; c++) - { - crtc = output->crtcs[c]; - /* - * Check to see if some other output is - * using this crtc - */ - for (o = 0; o < n; o++) - if (best_crtcs[o] == crtc) - break; - if (o < n) - { - /* - * If the two outputs desire the same mode, - * see if they can be cloned - */ - if (modes[o] == modes[n]) - { - for (l = 0; l < output->numClones; l++) - if (output->clones[l] == outputs[o]) - break; - if (l == output->numClones) - continue; /* nope, try next CRTC */ - } - else - continue; /* different modes, can't clone */ - } - crtcs[n] = crtc; - memcpy (crtcs, best_crtcs, n * sizeof (RRCrtcPtr)); - score = my_score + I830RRPickCrtcs (outputs, crtcs, modes, - num_output, n+1); - if (score >= best_score) - { - best_crtc = crtc; - best_score = score; - memcpy (best_crtcs, crtcs, num_output * sizeof (RRCrtcPtr)); - } - } - xfree (crtcs); - return best_score; -} - -static Bool -I830RRInitialConfiguration (RROutputPtr *outputs, - RRCrtcPtr *crtcs, - RRModePtr *modes, - int num_output) -{ - int o; - RRModePtr target_mode = NULL; + if (!xf86RandR12CreateObjects12 (pScreen)) + return FALSE; - for (o = 0; o < num_output; o++) - modes[o] = NULL; - /* - * Let outputs with preferred modes drive screen size + * Configure output modes */ - for (o = 0; o < num_output; o++) - { - RROutputPtr output = outputs[o]; - - if (output->connection != RR_Disconnected && output->numPreferred) - { - target_mode = I830RRDefaultMode (output); - if (target_mode) - { - modes[o] = target_mode; - break; - } - } - } - if (!target_mode) - { - for (o = 0; o < num_output; o++) - { - RROutputPtr output = outputs[o]; - if (output->connection != RR_Disconnected) - { - target_mode = I830RRDefaultMode (output); - if (target_mode) - { - modes[o] = target_mode; - break; - } - } - } - } - for (o = 0; o < num_output; o++) - { - RROutputPtr output = outputs[o]; - - if (output->connection != RR_Disconnected && !modes[o]) - modes[o] = I830ClosestMode (output, target_mode); - } - - if (!I830RRPickCrtcs (outputs, crtcs, modes, num_output, 0)) + if (!xf86RandR12SetInfo12 (pScreen)) return FALSE; - return TRUE; } -/* - * Compute the virtual size necessary to place all of the available - * crtcs in a panorama configuration - */ - -static void -I830RRDefaultScreenLimits (RROutputPtr *outputs, int num_output, - RRCrtcPtr *crtcs, int num_crtc, - int *widthp, int *heightp) -{ - int width = 0, height = 0; - int o; - int c; - int m; - int s; - - for (c = 0; c < num_crtc; c++) - { - RRCrtcPtr crtc = crtcs[c]; - int crtc_width = 1600, crtc_height = 1200; - - for (o = 0; o < num_output; o++) - { - RROutputPtr output = outputs[o]; - - for (s = 0; s < output->numCrtcs; s++) - if (output->crtcs[s] == crtc) - { - for (m = 0; m < output->numModes; m++) - { - RRModePtr mode = output->modes[m]; - if (mode->mode.width > crtc_width) - crtc_width = mode->mode.width; - if (mode->mode.height > crtc_width) - crtc_height = mode->mode.height; - } - } - } - if (crtc_width > width) - width = crtc_width; - if (crtc_height > height) - height = crtc_height; - } - *widthp = width; - *heightp = height; -} - #endif Bool xf86RandR12PreInit (ScrnInfoPtr pScrn) { - I830Ptr pI830 = I830PTR(pScrn); -#if RANDR_12_INTERFACE - RROutputPtr outputs[MAX_OUTPUTS]; - RRCrtcPtr output_crtcs[MAX_OUTPUTS]; - RRModePtr output_modes[MAX_OUTPUTS]; - RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; - int width, height; - int o; - int c; -#endif - - if (pI830->xf86_config.num_output <= 0) - return FALSE; - - i830_reprobe_output_modes(pScrn); - -#if RANDR_12_INTERFACE - if (!xf86RandR12CreateObjects12 (pScrn)) - return FALSE; - - /* - * Configure output modes - */ - if (!xf86RandR12SetInfo12 (pScrn)) - return FALSE; - /* - * With RandR info set up, let RandR choose - * the initial configuration - */ - for (o = 0; o < pI830->xf86_config.num_output; o++) - outputs[o] = pI830->xf86_config.output[o]->randr_output; - for (c = 0; c < pI830->xf86_config.num_crtc; c++) - crtcs[c] = pI830->xf86_config.crtc[c]->randr_crtc; - - if (!I830RRInitialConfiguration (outputs, output_crtcs, output_modes, - pI830->xf86_config.num_output)) - return FALSE; - - I830RRDefaultScreenLimits (outputs, pI830->xf86_config.num_output, - crtcs, pI830->xf86_config.num_crtc, - &width, &height); - - if (width > pScrn->virtualX) - pScrn->virtualX = width; - if (width > pScrn->display->virtualX) - pScrn->display->virtualX = width; - if (height > pScrn->virtualY) - pScrn->virtualY = height; - if (height > pScrn->display->virtualY) - pScrn->display->virtualY = height; - - /* XXX override xf86 common frame computation code */ - pScrn->display->frameX0 = 0; - pScrn->display->frameY0 = 0; - for (o = 0; o < pI830->xf86_config.num_output; o++) - { - xf86OutputPtr output = pI830->xf86_config.output[o]; - RRModePtr randr_mode = output_modes[o]; - RRCrtcPtr randr_crtc = output_crtcs[o]; - DisplayModePtr mode; - - if (randr_mode && randr_crtc) - { - xf86CrtcPtr crtc = randr_crtc->devPrivate; - - mode = (DisplayModePtr) randr_mode->devPrivate; - crtc->desiredMode = *mode; - output->crtc = crtc; - } - } -#endif - i830_set_xf86_modes_from_outputs (pScrn); - - i830_set_default_screen_size(pScrn); - return TRUE; } diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index c75800d4..a2030b72 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -975,7 +975,7 @@ i830_sdvo_dump(ScrnInfoPtr pScrn) * * Takes 14ms on average on my i945G. */ -static enum detect_status +static xf86OutputStatus i830_sdvo_detect(xf86OutputPtr output) { CARD8 response[2]; @@ -985,12 +985,12 @@ i830_sdvo_detect(xf86OutputPtr output) status = i830_sdvo_read_response(output, &response, 2); if (status != SDVO_CMD_STATUS_SUCCESS) - return OUTPUT_STATUS_UNKNOWN; + return XF86OutputStatusUnknown; if (response[0] != 0 || response[1] != 0) - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; else - return OUTPUT_STATUS_DISCONNECTED; + return XF86OutputStatusDisconnected; } static void @@ -1132,9 +1132,15 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) memset(&dev_priv->active_outputs, 0, sizeof(dev_priv->active_outputs)); if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) + { dev_priv->active_outputs = SDVO_OUTPUT_TMDS0; + output->subpixel_order = SubPixelHorizontalRGB; + } else if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) + { dev_priv->active_outputs = SDVO_OUTPUT_TMDS1; + output->subpixel_order = SubPixelHorizontalRGB; + } else { unsigned char bytes[2]; diff --git a/src/i830_tv.c b/src/i830_tv.c index f5716f8b..e05bc4cb 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -544,7 +544,7 @@ i830_tv_detect_type (xf86CrtcPtr crtc, * Currently this always returns OUTPUT_STATUS_UNKNOWN, as we need to be sure * we have a pipe programmed in order to probe the TV. */ -static enum detect_status +static xf86OutputStatus i830_tv_detect(xf86OutputPtr output) { xf86CrtcPtr crtc; @@ -567,11 +567,11 @@ i830_tv_detect(xf86OutputPtr output) switch (dev_priv->type) { case TV_TYPE_NONE: - return OUTPUT_STATUS_DISCONNECTED; + return XF86OutputStatusDisconnected; case TV_TYPE_UNKNOWN: - return OUTPUT_STATUS_UNKNOWN; + return XF86OutputStatusUnknown; default: - return OUTPUT_STATUS_CONNECTED; + return XF86OutputStatusConnected; } } diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 7eb581c9..5378b34f 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -31,6 +31,7 @@ #include <stdio.h> #include "xf86.h" +#include "xf86DDC.h" #include "i830_xf86Crtc.h" /* @@ -49,12 +50,7 @@ xf86CrtcCreate (ScrnInfoPtr scrn, crtc->scrn = scrn; crtc->funcs = funcs; #ifdef RANDR_12_INTERFACE - crtc->randr_crtc = RRCrtcCreate (crtc); - if (!crtc->randr_crtc) - { - xfree (crtc); - return NULL; - } + crtc->randr_crtc = NULL; #endif xf86_config->crtc[xf86_config->num_crtc++] = crtc; return crtc; @@ -67,10 +63,6 @@ xf86CrtcDestroy (xf86CrtcPtr crtc) int c; (*crtc->funcs->destroy) (crtc); -#ifdef RANDR_12_INTERFACE - if (crtc->randr_crtc) - RRCrtcDestroy (crtc->randr_crtc); -#endif for (c = 0; c < xf86_config->num_crtc; c++) if (xf86_config->crtc[c] == crtc) { @@ -101,14 +93,10 @@ xf86OutputCreate (ScrnInfoPtr scrn, output->scrn = scrn; output->funcs = funcs; output->name = (char *) (output + 1); + output->subpixel_order = SubPixelUnknown; strcpy (output->name, name); #ifdef RANDR_12_INTERFACE - output->randr_output = RROutputCreate (name, strlen (name), output); - if (!output->randr_output) - { - xfree (output); - return NULL; - } + output->randr_output = NULL; #endif xf86_config->output[xf86_config->num_output++] = output; return output; @@ -122,10 +110,6 @@ xf86OutputDestroy (xf86OutputPtr output) int o; (*output->funcs->destroy) (output); -#ifdef RANDR_12_INTERFACE - if (output->randr_output) - RROutputDestroy (output->randr_output); -#endif while (output->probed_modes) xf86DeleteMode (&output->probed_modes, output->probed_modes); for (o = 0; o < xf86_config->num_output; o++) @@ -140,55 +124,467 @@ xf86OutputDestroy (xf86OutputPtr output) xfree (output); } -Bool -xf86CrtcScreenInit (ScreenPtr pScreen) +static DisplayModePtr +xf86DefaultMode (xf86OutputPtr output) { -#ifdef RANDR_12_INTERFACE - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; + DisplayModePtr target_mode = NULL; + DisplayModePtr mode; + int target_diff = 0; + int target_preferred = 0; + int mm_height; + + mm_height = output->mm_height; + if (!mm_height) + mm_height = 203; /* 768 pixels at 96dpi */ + /* + * Pick a mode closest to 96dpi + */ + for (mode = output->probed_modes; mode; mode = mode->next) + { + int dpi; + int preferred = (mode->type & M_T_PREFERRED) != 0; + int diff; - for (i = 0; i < xf86_config->num_crtc; i++) + dpi = (mode->HDisplay * 254) / (mm_height * 10); + diff = dpi - 96; + diff = diff < 0 ? -diff : diff; + if (target_mode == NULL || (preferred > target_preferred) || + (preferred == target_preferred && diff < target_diff)) + { + target_mode = mode; + target_diff = diff; + target_preferred = preferred; + } + } + return target_mode; +} + +static DisplayModePtr +xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match) +{ + DisplayModePtr target_mode = NULL; + DisplayModePtr mode; + int target_diff = 0; + + /* + * Pick a mode closest to the specified mode + */ + for (mode = output->probed_modes; mode; mode = mode->next) { - xf86CrtcPtr crtc = xf86_config->crtc[i]; + int dx, dy; + int diff; - if (!crtc->randr_crtc) - crtc->randr_crtc = RRCrtcCreate (crtc); - if (!crtc->randr_crtc) - return FALSE; + /* exact matches are preferred */ + if (xf86ModesEqual (mode, match)) + return mode; + + dx = match->HDisplay - mode->HDisplay; + dy = match->VDisplay - mode->VDisplay; + diff = dx * dx + dy * dy; + if (target_mode == NULL || diff < target_diff) + { + target_mode = mode; + target_diff = diff; + } } - for (i = 0; i < xf86_config->num_output; i++) + return target_mode; +} + +static Bool +xf86OutputHasPreferredMode (xf86OutputPtr output) +{ + DisplayModePtr mode; + + for (mode = output->probed_modes; mode; mode = mode->next) + if (mode->type & M_T_PREFERRED) + return TRUE; + return FALSE; +} + +static int +xf86PickCrtcs (ScrnInfoPtr pScrn, + xf86CrtcPtr *best_crtcs, + DisplayModePtr *modes, + int n) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c, o, l; + xf86OutputPtr output; + xf86CrtcPtr crtc; + xf86CrtcPtr *crtcs; + xf86CrtcPtr best_crtc; + int best_score; + int score; + int my_score; + + if (n == config->num_output) + return 0; + output = config->output[n]; + + /* + * Compute score with this output disabled + */ + best_crtcs[n] = NULL; + best_crtc = NULL; + best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1); + if (modes[n] == NULL) + return best_score; + + crtcs = xalloc (config->num_output * sizeof (xf86CrtcPtr)); + if (!crtcs) + return best_score; + + my_score = 1; + /* Score outputs that are known to be connected higher */ + if (output->status == XF86OutputStatusConnected) + my_score++; + /* Score outputs with preferred modes higher */ + if (xf86OutputHasPreferredMode (output)) + my_score++; + /* + * Select a crtc for this output and + * then attempt to configure the remaining + * outputs + */ + for (c = 0; c < config->num_crtc; c++) { - xf86OutputPtr output = xf86_config->output[i]; + if ((output->possible_crtcs & (1 << c)) == 0) + continue; - if (!output->randr_output) - output->randr_output = RROutputCreate (output->name, - strlen (output->name), - output); - if (!output->randr_output) - return FALSE; + crtc = config->crtc[c]; + /* + * Check to see if some other output is + * using this crtc + */ + for (o = 0; o < n; o++) + if (best_crtcs[o] == crtc) + break; + if (o < n) + { + /* + * If the two outputs desire the same mode, + * see if they can be cloned + */ + if (xf86ModesEqual (modes[o], modes[n])) + { + for (l = 0; l < config->num_output; l++) + if (output->possible_clones & (1 << l)) + break; + if (l == config->num_output) + continue; /* nope, try next CRTC */ + } + else + continue; /* different modes, can't clone */ + } + crtcs[n] = crtc; + memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); + score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1); + if (score >= best_score) + { + best_crtc = crtc; + best_score = score; + memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr)); + } } + xfree (crtcs); + return best_score; +} + + +/* + * Compute the virtual size necessary to place all of the available + * crtcs in a panorama configuration + */ + +static void +xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int width = 0, height = 0; + int o; + int c; + int s; + + for (c = 0; c < config->num_crtc; c++) + { + int crtc_width = 1600, crtc_height = 1200; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + for (s = 0; s < config->num_crtc; s++) + if (output->possible_crtcs & (1 << s)) + { + DisplayModePtr mode; + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (mode->HDisplay > crtc_width) + crtc_width = mode->HDisplay; + if (mode->VDisplay > crtc_width) + crtc_height = mode->VDisplay; + } + } + } + if (crtc_width > width) + width = crtc_width; + if (crtc_height > height) + height = crtc_height; + } + *widthp = width; + *heightp = height; +} + +void +xf86ProbeOutputModes (ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + Bool properties_set = FALSE; + int o; + + /* Probe the list of modes for each output. */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode; + + while (output->probed_modes != NULL) + xf86DeleteMode(&output->probed_modes, output->probed_modes); + + output->probed_modes = (*output->funcs->get_modes) (output); + + /* Set the DDC properties to whatever first output has DDC information. + */ + if (output->MonInfo != NULL && !properties_set) { + xf86SetDDCproperties(pScrn, output->MonInfo); + properties_set = TRUE; + } + +#ifdef DEBUG_REPROBE + if (output->probed_modes != NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Printing probed modes for output %s\n", + output->name); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No remaining probed modes for output %s\n", + output->name); + } #endif - return TRUE; + for (mode = output->probed_modes; mode != NULL; mode = mode->next) + { + /* The code to choose the best mode per pipe later on will require + * VRefresh to be set. + */ + mode->VRefresh = xf86ModeVRefresh(mode); + xf86SetModeCrtc(mode, INTERLACE_HALVE_V); + +#ifdef DEBUG_REPROBE + xf86PrintModeline(pScrn->scrnIndex, mode); +#endif + } + } } + +/** + * Copy one of the output mode lists to the ScrnInfo record + */ + +/* XXX where does this function belong? Here? */ void -xf86CrtcCloseScreen (ScreenPtr pScreen) +xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y); + +void +xf86SetScrnInfoModes (ScrnInfoPtr pScrn) { -#ifdef RANDR_12_INTERFACE - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + DisplayModePtr last, mode; + int originalVirtualX, originalVirtualY; - for (i = 0; i < xf86_config->num_crtc; i++) + output = config->output[config->compat_output]; + if (!output->crtc) { - xf86CrtcPtr crtc = xf86_config->crtc[i]; - crtc->randr_crtc = NULL; + int o; + + output = NULL; + for (o = 0; o < config->num_output; o++) + if (config->output[o]->crtc) + { + config->compat_output = o; + output = config->output[o]; + break; + } + /* no outputs are active, punt and leave things as they are */ + if (!output) + return; } - for (i = 0; i < xf86_config->num_output; i++) + crtc = output->crtc; + + /* Clear any existing modes from pScrn->modes */ + while (pScrn->modes != NULL) + xf86DeleteMode(&pScrn->modes, pScrn->modes); + + /* Set pScrn->modes to the mode list for the 'compat' output */ + pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes); + + xf86RandR12GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY); + + /* Disable modes in the XFree86 DDX list that are larger than the current + * virtual size. + */ + i830xf86ValidateModesSize(pScrn, pScrn->modes, + originalVirtualX, originalVirtualY, + pScrn->displayWidth); + + /* Strip out anything that we threw out for virtualX/Y. */ + i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE); + + for (mode = pScrn->modes; mode; mode = mode->next) + if (xf86ModesEqual (mode, &crtc->desiredMode)) + break; + + /* For some reason, pScrn->modes is circular, unlike the other mode lists. + * How great is that? + */ + for (last = pScrn->modes; last && last->next; last = last->next); + last->next = pScrn->modes; + pScrn->modes->prev = last; + if (mode) + while (pScrn->modes != mode) + pScrn->modes = pScrn->modes->next; + pScrn->currentMode = pScrn->modes; +} + +/** + * Construct default screen configuration + * + * Given auto-detected (and, eventually, configured) values, + * construct a usable configuration for the system + */ + +Bool +xf86InitialConfiguration (ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int o, c; + DisplayModePtr target_mode = NULL; + xf86CrtcPtr *crtcs; + DisplayModePtr *modes; + int width, height; + + xf86ProbeOutputModes (pScrn); + + crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); + modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); + + for (o = 0; o < config->num_output; o++) + modes[o] = NULL; + + /* + * Let outputs with preferred modes drive screen size + */ + for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = xf86_config->output[i]; - output->randr_output = NULL; + xf86OutputPtr output = config->output[o]; + + if (output->status != XF86OutputStatusDisconnected && + xf86OutputHasPreferredMode (output)) + { + target_mode = xf86DefaultMode (output); + if (target_mode) + { + modes[o] = target_mode; + config->compat_output = o; + break; + } + } } -#endif + if (!target_mode) + { + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + if (output->status != XF86OutputStatusDisconnected) + { + target_mode = xf86DefaultMode (output); + if (target_mode) + { + modes[o] = target_mode; + config->compat_output = o; + break; + } + } + } + } + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + if (output->status != XF86OutputStatusDisconnected && !modes[o]) + modes[o] = xf86ClosestMode (output, target_mode); + } + + if (!xf86PickCrtcs (pScrn, crtcs, modes, 0)) + { + xfree (crtcs); + xfree (modes); + return FALSE; + } + + xf86DefaultScreenLimits (pScrn, &width, &height); + + /* + * Expand virtual size to cover potential mode switches + */ + if (width > pScrn->virtualX) + pScrn->virtualX = width; + if (width > pScrn->display->virtualX) + pScrn->display->virtualX = width; + if (height > pScrn->virtualY) + pScrn->virtualY = height; + if (height > pScrn->display->virtualY) + pScrn->display->virtualY = height; + + /* XXX override xf86 common frame computation code */ + + pScrn->display->frameX0 = 0; + pScrn->display->frameY0 = 0; + + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + + crtc->enabled = FALSE; + memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); + } + + /* + * Set initial configuration + */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode = modes[o]; + xf86CrtcPtr crtc = crtcs[o]; + + if (mode && crtc) + { + crtc->desiredMode = *mode; + crtc->enabled = TRUE; + crtc->x = 0; + crtc->y = 0; + output->crtc = crtc; + /* XXX set position; for now, we clone */ + } + } + + /* Mirror output modes to pScrn mode list */ + xf86SetScrnInfoModes (pScrn); + + xfree (crtcs); + xfree (modes); + return TRUE; } diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 21ba1fcf..9b7f788c 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -28,6 +28,12 @@ typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr; +typedef enum _xf86OutputStatus { + XF86OutputStatusConnected, + XF86OutputStatusDisconnected, + XF86OutputStatusUnknown, +} xf86OutputStatus; + typedef struct _xf86CrtcFuncs { /** * Turns the crtc on/off, or sets intermediate power levels if available. @@ -186,7 +192,7 @@ typedef struct _xf86OutputFuncs { /** * Probe for a connected output, and return detect_status. */ - enum detect_status + xf86OutputStatus (*detect)(xf86OutputPtr output); /** @@ -211,12 +217,23 @@ struct _xf86Output { * Associated ScrnInfo */ ScrnInfoPtr scrn; + /** * Currently connected crtc (if any) * * If this output is not in use, this field will be NULL. */ xf86CrtcPtr crtc; + + /** + * Possible CRTCs for this output as a mask of crtc indices + */ + CARD32 possible_crtcs; + + /** + * Possible outputs to share the same CRTC as a mask of output indices + */ + CARD32 possible_clones; /** * List of available modes on this output. * @@ -225,9 +242,20 @@ struct _xf86Output { */ DisplayModePtr probed_modes; + /** + * Current connection status + * + * This indicates whether a monitor is known to be connected + * to this output or not, or whether there is no way to tell + */ + xf86OutputStatus status; + /** EDID monitor information */ xf86MonPtr MonInfo; + /** subpixel order */ + int subpixel_order; + /** Physical size of the currently attached output device. */ int mm_width, mm_height; @@ -253,12 +281,20 @@ struct _xf86Output { #endif }; +/* XXX yes, static allocation is a kludge */ #define XF86_MAX_CRTC 4 #define XF86_MAX_OUTPUT 16 typedef struct _xf86CrtcConfig { int num_output; xf86OutputPtr output[XF86_MAX_OUTPUT]; + /** + * compat_output is used whenever we deal + * with legacy code that only understands a single + * output. pScrn->modes will be loaded from this output, + * adjust frame will whack this output, etc. + */ + int compat_output; int num_crtc; xf86CrtcPtr crtc[XF86_MAX_CRTC]; @@ -307,10 +343,13 @@ xf86OutputCreate (ScrnInfoPtr scrn, void xf86OutputDestroy (xf86OutputPtr output); -Bool -xf86CrtcScreenInit (ScreenPtr pScreen); +void +xf86ProbeOutputModes (ScrnInfoPtr pScrn); void -xf86CrtcCloseScreen (ScreenPtr pScreen); +xf86SetScrnInfoModes (ScrnInfoPtr pScrn); + +Bool +xf86InitialConfiguration (ScrnInfoPtr pScrn); #endif /* _XF86CRTC_H_ */ |