diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/i830.h | 36 | ||||
-rw-r--r-- | src/i830_crt.c | 166 | ||||
-rw-r--r-- | src/i830_cursor.c | 90 | ||||
-rw-r--r-- | src/i830_display.c | 246 | ||||
-rw-r--r-- | src/i830_display.h | 12 | ||||
-rw-r--r-- | src/i830_dri.c | 8 | ||||
-rw-r--r-- | src/i830_driver.c | 111 | ||||
-rw-r--r-- | src/i830_dvo.c | 145 | ||||
-rw-r--r-- | src/i830_lvds.c | 93 | ||||
-rw-r--r-- | src/i830_modes.c | 67 | ||||
-rw-r--r-- | src/i830_randr.c | 223 | ||||
-rw-r--r-- | src/i830_sdvo.c | 272 | ||||
-rw-r--r-- | src/i830_tv.c | 111 | ||||
-rw-r--r-- | src/i830_video.c | 2 | ||||
-rw-r--r-- | src/i830_xf86Crtc.c | 126 | ||||
-rw-r--r-- | src/i830_xf86Crtc.h | 296 | ||||
-rw-r--r-- | src/i830_xf86Modes.h | 5 |
18 files changed, 1312 insertions, 699 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 0fce5e4f..0a14d1a4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -80,6 +80,8 @@ i810_drv_la_SOURCES = \ i830_tv.c \ i830_xf86Modes.h \ i830_xf86Modes.c \ + i830_xf86Crtc.h \ + i830_xf86Crtc.c \ i915_3d.c \ i915_3d.h \ i915_reg.h \ @@ -59,6 +59,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "vbe.h" #include "vgaHW.h" #include "randrstr.h" +#include "i830_xf86Crtc.h" #ifdef XF86DRI #include "xf86drm.h" @@ -188,6 +189,25 @@ enum detect_status { OUTPUT_STATUS_UNKNOWN }; +typedef struct _I830CrtcPrivateRec { + int pipe; + Bool gammaEnabled; +} I830CrtcPrivateRec, *I830CrtcPrivatePtr; + +#define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private) + +typedef struct _I830OutputPrivateRec { + int type; + I2CBusPtr pI2CBus; + I2CBusPtr pDDCBus; + struct _I830DVODriver *i2c_drv; + Bool load_detect_temp; + /** Output-private structure. Should replace i2c_drv */ + void *dev_priv; +} I830OutputPrivateRec, *I830OutputPrivatePtr; + +#define I830OutputPrivate(o) ((I830OutputPrivatePtr) (o)->driver_private) + struct _I830OutputRec { int type; int pipe; @@ -467,10 +487,16 @@ typedef struct _I830Rec { Bool checkDevices; + /* XXX outputs and crtcs need to move to ScrnInfoRec */ + int num_outputs; +/* struct _I830OutputRec output[MAX_OUTPUTS]; */ + I830_xf86OutputPtr xf86_output[MAX_OUTPUTS]; + /* [0] is Pipe A, [1] is Pipe B. */ int num_pipes; /* [0] is display plane A, [1] is display plane B. */ - I830PipeRec pipes[MAX_DISPLAY_PIPES]; +/* I830PipeRec pipes[MAX_DISPLAY_PIPES]; */ + I830_xf86CrtcPtr xf86_crtc[MAX_DISPLAY_PIPES]; /* Driver phase/state information */ Bool preinit; @@ -488,8 +514,6 @@ typedef struct _I830Rec { OsTimerPtr devicesTimer; int ddc2; - int num_outputs; - struct _I830OutputRec output[MAX_OUTPUTS]; /* Panel size pulled from the BIOS */ int PanelXRes, PanelYRes; @@ -580,7 +604,7 @@ extern void I830PrintErrorState(ScrnInfoPtr pScrn); extern void I965PrintErrorState(ScrnInfoPtr pScrn); extern void I830Sync(ScrnInfoPtr pScrn); extern void I830InitHWCursor(ScrnInfoPtr pScrn); -extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force); +extern void I830SetPipeCursor (I830_xf86CrtcPtr crtc, Bool force); extern Bool I830CursorInit(ScreenPtr pScreen); extern void IntelEmitInvarientState(ScrnInfoPtr pScrn); extern void I830EmitInvarientState(ScrnInfoPtr pScrn); @@ -661,7 +685,7 @@ extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, /* i830_display.c */ Bool -i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type); +i830PipeHasType (I830_xf86CrtcPtr crtc, int type); /* i830_crt.c */ void i830_crt_init(ScrnInfoPtr pScrn); @@ -685,7 +709,7 @@ 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(ScrnInfoPtr pScrn, I830OutputPtr output); +DisplayModePtr i830_ddc_get_modes(I830_xf86OutputPtr output); /* i830_randr.c */ Bool I830RandRCreateScreenResources (ScreenPtr pScreen); diff --git a/src/i830_crt.c b/src/i830_crt.c index f067260d..615e96a3 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -35,10 +35,11 @@ #include "i830_display.h" static void -i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +i830_crt_dpms(I830_xf86OutputPtr output, int mode) { - I830Ptr pI830 = I830PTR(pScrn); - CARD32 temp; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; temp = INREG(ADPA); temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); @@ -63,24 +64,25 @@ i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) } static void -i830_crt_save(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_crt_save (I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); pI830->saveADPA = INREG(ADPA); } static void -i830_crt_restore(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_crt_restore (I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); OUTREG(ADPA, pI830->saveADPA); } static int -i830_crt_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_crt_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode) { if (pMode->Flags & V_DBLSCAN) return MODE_NO_DBLESCAN; @@ -92,19 +94,24 @@ i830_crt_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, } static void -i830_crt_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_crt_pre_set_mode (I830_xf86OutputPtr output, DisplayModePtr pMode) { } static void -i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_crt_post_set_mode (I830_xf86OutputPtr output, DisplayModePtr pMode) { - I830Ptr pI830 = I830PTR(pScrn); - int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; - CARD32 adpa, dpll_md; - + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830_xf86CrtcPtr crtc = output->crtc; + I830CrtcPrivatePtr i830_crtc = crtc->driver_private; + int dpll_md_reg; + CARD32 adpa, dpll_md; + + if (i830_crtc->pipe == 0) + dpll_md_reg = DPLL_A_MD; + else + dpll_md_reg = DPLL_B_MD; /* * Disable separate mode multiplier used when cloning SDVO to CRT * XXX this needs to be adjusted when we really are cloning @@ -122,7 +129,7 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, if (pMode->Flags & V_PVSYNC) adpa |= ADPA_VSYNC_ACTIVE_HIGH; - if (output->pipe == 0) + if (i830_crtc->pipe == 0) adpa |= ADPA_PIPE_A_SELECT; else adpa |= ADPA_PIPE_B_SELECT; @@ -139,12 +146,13 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, * \return FALSE if CRT is disconnected. */ static Bool -i830_crt_detect_hotplug(ScrnInfoPtr pScrn) +i830_crt_detect_hotplug(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); - CARD32 temp; - const int timeout_ms = 1000; - int starttime, curtime; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; + const int timeout_ms = 1000; + int starttime, curtime; temp = INREG(PORT_HOTPLUG_EN); @@ -177,20 +185,25 @@ i830_crt_detect_hotplug(ScrnInfoPtr pScrn) * \return FALSE if CRT is disconnected. */ static Bool -i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_crt_detect_load (I830_xf86CrtcPtr crtc, + I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); - CARD32 save_adpa, adpa, pipeconf, bclrpat; - CARD8 st00; - int pipeconf_reg, bclrpat_reg, dpll_reg; - int pipe; - - pipe = output->pipe; - if (pipe == 0) { + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr i830_crtc = I830CrtcPrivate(crtc); + CARD32 save_adpa, adpa, pipeconf, bclrpat; + CARD8 st00; + int pipeconf_reg, bclrpat_reg, dpll_reg; + int pipe = i830_crtc->pipe; + + if (pipe == 0) + { bclrpat_reg = BCLRPAT_A; pipeconf_reg = PIPEACONF; dpll_reg = DPLL_A; - } else { + } + else + { bclrpat_reg = BCLRPAT_B; pipeconf_reg = PIPEBCONF; dpll_reg = DPLL_B; @@ -244,17 +257,15 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output) * \return FALSE if no DDC response was detected. */ static Bool -i830_crt_detect_ddc(ScrnInfoPtr pScrn) +i830_crt_detect_ddc(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); - struct _I830OutputRec *output; + I830OutputPrivatePtr i830_output = output->driver_private; - output = &pI830->output[0]; /* CRT should always be at 0, but check anyway */ - if (output->type != I830_OUTPUT_ANALOG) + if (i830_output->type != I830_OUTPUT_ANALOG) return FALSE; - return xf86I2CProbeAddress(output->pDDCBus, 0x00A0); + return xf86I2CProbeAddress(i830_output->pDDCBus, 0x00A0); } /** @@ -264,25 +275,30 @@ i830_crt_detect_ddc(ScrnInfoPtr pScrn) * on active displays. */ static enum detect_status -i830_crt_detect(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_crt_detect(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830_xf86CrtcPtr crtc; if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830)) { - if (i830_crt_detect_hotplug(pScrn)) + if (i830_crt_detect_hotplug(output)) return OUTPUT_STATUS_CONNECTED; else return OUTPUT_STATUS_DISCONNECTED; } - if (i830_crt_detect_ddc(pScrn)) + if (i830_crt_detect_ddc(output)) return OUTPUT_STATUS_CONNECTED; /* Use the load-detect method if we have no other way of telling. */ - if (i830GetLoadDetectPipe(pScrn, output) != -1) { - Bool connected = i830_crt_detect_load(pScrn, output); + crtc = i830xf86AllocCrtc (output); + + if (crtc) + { + Bool connected = i830_crt_detect_load(crtc, output); - i830ReleaseLoadDetectPipe(pScrn, output); + i830xf86FreeCrtc (crtc); if (connected) return OUTPUT_STATUS_CONNECTED; else @@ -293,16 +309,17 @@ i830_crt_detect(ScrnInfoPtr pScrn, I830OutputPtr output) } static DisplayModePtr -i830_crt_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_crt_get_modes(I830_xf86OutputPtr output) { - DisplayModePtr modes; + ScrnInfoPtr pScrn = output->scrn; + DisplayModePtr modes; MonRec fixed_mon; - modes = i830_ddc_get_modes(pScrn, output); + modes = i830_ddc_get_modes(output); if (modes != NULL) return modes; - if (output->detect(pScrn, output) == OUTPUT_STATUS_DISCONNECTED) + if ((*output->funcs->detect)(output) == OUTPUT_STATUS_DISCONNECTED) return NULL; /* We've got a potentially-connected monitor that we can't DDC. Return a @@ -323,24 +340,43 @@ i830_crt_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) return modes; } +static void +i830_crt_destroy (I830_xf86OutputPtr output) +{ + if (output->driver_private) + xfree (output->driver_private); +} + +static const I830_xf86OutputFuncsRec i830_crt_output_funcs = { + .dpms = i830_crt_dpms, + .save = i830_crt_save, + .restore = i830_crt_restore, + .mode_valid = i830_crt_mode_valid, + .pre_set_mode = i830_crt_pre_set_mode, + .post_set_mode = i830_crt_post_set_mode, + .detect = i830_crt_detect, + .get_modes = i830_crt_get_modes, + .destroy = i830_crt_destroy +}; + void i830_crt_init(ScrnInfoPtr pScrn) { - I830Ptr pI830 = I830PTR(pScrn); - - pI830->output[pI830->num_outputs].type = I830_OUTPUT_ANALOG; - pI830->output[pI830->num_outputs].dpms = i830_crt_dpms; - pI830->output[pI830->num_outputs].save = i830_crt_save; - pI830->output[pI830->num_outputs].restore = i830_crt_restore; - pI830->output[pI830->num_outputs].mode_valid = i830_crt_mode_valid; - pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode; - pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode; - pI830->output[pI830->num_outputs].detect = i830_crt_detect; - pI830->output[pI830->num_outputs].get_modes = i830_crt_get_modes; + I830_xf86OutputPtr output; + I830OutputPrivatePtr i830_output; + + output = i830xf86OutputCreate (pScrn, &i830_crt_output_funcs, "VGA"); + if (!output) + return; + i830_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1); + if (!i830_output) + { + i830xf86OutputDestroy (output); + return; + } + i830_output->type = I830_OUTPUT_ANALOG; + output->driver_private = i830_output; /* Set up the DDC bus. */ - I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus, - GPIOA, "CRTDDC_A"); - - pI830->num_outputs++; + I830I2CInit(pScrn, &i830_output->pDDCBus, GPIOA, "CRTDDC_A"); } diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 517bd3e0..a3526f87 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -80,11 +80,14 @@ static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs); #endif static void -I830SetPipeCursorBase (ScrnInfoPtr pScrn, int pipe) +I830SetPipeCursorBase (I830_xf86CrtcPtr crtc) { - I830Ptr pI830 = I830PTR(pScrn); - int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE); - I830MemRange *cursor_mem; + ScrnInfoPtr pScrn = crtc->scrn; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + I830Ptr pI830 = I830PTR(pScrn); + int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE); + I830MemRange *cursor_mem; if (pipe >= pI830->num_pipes) FatalError("Bad pipe number for cursor base setting\n"); @@ -102,18 +105,20 @@ I830SetPipeCursorBase (ScrnInfoPtr pScrn, int pipe) } void -I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) +I830SetPipeCursor (I830_xf86CrtcPtr crtc, Bool force) { - I830Ptr pI830 = I830PTR(pScrn); - I830PipePtr pI830Pipe = &pI830->pipes[pipe]; - CARD32 temp; - Bool show; + ScrnInfoPtr pScrn = crtc->scrn; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; + Bool show; - if (!pI830Pipe->enabled) + if (!crtc->enabled) return; - show = pI830->cursorOn && pI830Pipe->cursorInRange; - if (show && (force || !pI830Pipe->cursorShown)) + show = pI830->cursorOn && crtc->cursorInRange; + if (show && (force || !crtc->cursorShown)) { if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { int cursor_control; @@ -125,7 +130,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); if (pI830->CursorIsARGB) { temp |= CURSOR_MODE_64_ARGB_AX; - if (pI830Pipe->gammaEnabled) + if (intel_crtc->gammaEnabled) temp |= MCURSOR_GAMMA_ENABLE; } else temp |= CURSOR_MODE_64_4C_AX; @@ -139,15 +144,15 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) temp |= CURSOR_ENABLE; if (pI830->CursorIsARGB) { temp |= CURSOR_FORMAT_ARGB; - if (pI830Pipe->gammaEnabled) + if (intel_crtc->gammaEnabled) temp |= CURSOR_GAMMA_ENABLE; } else temp |= CURSOR_FORMAT_3C; OUTREG(CURSOR_CONTROL, temp); } - pI830Pipe->cursorShown = TRUE; + crtc->cursorShown = TRUE; } - else if (!show && (force || pI830Pipe->cursorShown)) + else if (!show && (force || crtc->cursorShown)) { if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { @@ -165,11 +170,11 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force) temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE); OUTREG(CURSOR_CONTROL, temp); } - pI830Pipe->cursorShown = FALSE; + crtc->cursorShown = FALSE; } /* Flush cursor changes. */ - I830SetPipeCursorBase(pScrn, pipe); + I830SetPipeCursorBase(crtc); } void @@ -181,7 +186,8 @@ I830InitHWCursor(ScrnInfoPtr pScrn) DPRINTF(PFX, "I830InitHWCursor\n"); for (i = 0; i < pI830->num_pipes; i++) - pI830->pipes[i].cursorShown = FALSE; + pI830->xf86_crtc[i]->cursorShown = FALSE; + /* Initialise the HW cursor registers, leaving the cursor hidden. */ if (IS_MOBILE(pI830) || IS_I9XX(pI830)) { for (i = 0; i < pI830->num_pipes; i++) @@ -198,7 +204,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn) temp |= CURSOR_MODE_64_4C_AX; /* Need to set control, then address. */ OUTREG(cursor_control, temp); - I830SetPipeCursorBase(pScrn, i); + I830SetPipeCursorBase(pI830->xf86_crtc[i]); } } else { temp = INREG(CURSOR_CONTROL); @@ -211,7 +217,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn) /* This initialises the format and leave the cursor disabled. */ OUTREG(CURSOR_CONTROL, temp); /* Need to set address and size after disabling. */ - I830SetPipeCursorBase(pScrn, 0); + I830SetPipeCursorBase(pI830->xf86_crtc[0]); temp = ((I810_CURSOR_X & CURSOR_SIZE_MASK) << CURSOR_SIZE_HSHIFT) | ((I810_CURSOR_Y & CURSOR_SIZE_MASK) << CURSOR_SIZE_VSHIFT); OUTREG(CURSOR_SIZE, temp); @@ -486,12 +492,12 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) for (pipe = 0; pipe < pI830->num_pipes; pipe++) { - I830PipePtr pI830Pipe = &pI830->pipes[pipe]; - DisplayModePtr mode = &pI830Pipe->curMode; - int thisx = x - pI830Pipe->x; - int thisy = y - pI830Pipe->y; + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[pipe]; + DisplayModePtr mode = &crtc->curMode; + int thisx = x - crtc->x; + int thisy = y - crtc->y; - if (!pI830Pipe->enabled) + if (!crtc->enabled) continue; /* @@ -527,9 +533,9 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) if (pipe == 1) OUTREG(CURSOR_B_POSITION, temp); - pI830Pipe->cursorInRange = inrange; + crtc->cursorInRange = inrange; - I830SetPipeCursor (pScrn, pipe, FALSE); + I830SetPipeCursor (crtc, FALSE); } } @@ -551,7 +557,7 @@ I830ShowCursor(ScrnInfoPtr pScrn) pI830->cursorOn = TRUE; for (pipe = 0; pipe < pI830->num_pipes; pipe++) - I830SetPipeCursor (pScrn, pipe, TRUE); + I830SetPipeCursor (pI830->xf86_crtc[pipe], TRUE); } static void @@ -564,13 +570,14 @@ I830HideCursor(ScrnInfoPtr pScrn) pI830->cursorOn = FALSE; for (pipe = 0; pipe < pI830->num_pipes; pipe++) - I830SetPipeCursor (pScrn, pipe, TRUE); + I830SetPipeCursor (pI830->xf86_crtc[pipe], TRUE); } static void I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) { I830Ptr pI830 = I830PTR(pScrn); + int pipe; #ifdef ARGB_CURSOR /* Don't recolour cursors set with SetCursorARGB. */ @@ -580,18 +587,17 @@ I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) DPRINTF(PFX, "I830SetCursorColors\n"); - if (pI830->pipes[0].enabled) + for (pipe = 0; pipe < pI830->num_pipes; pipe++) { - OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff); - OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff); - OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff); - OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff); - } - if (pI830->pipes[1].enabled) - { - OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff); - OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff); - OUTREG(CURSOR_B_PALETTE2, fg & 0x00ffffff); - OUTREG(CURSOR_B_PALETTE3, bg & 0x00ffffff); + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[pipe]; + int pal0 = pipe == 0 ? CURSOR_A_PALETTE0 : CURSOR_B_PALETTE0; + + if (crtc->enabled) + { + OUTREG(pal0 + 0, bg & 0x00ffffff); + OUTREG(pal0 + 4, fg & 0x00ffffff); + OUTREG(pal0 + 8, fg & 0x00ffffff); + OUTREG(pal0 + 12, bg & 0x00ffffff); + } } } diff --git a/src/i830_display.c b/src/i830_display.c index 04f85cc2..9baa39ba 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -61,20 +61,25 @@ i830PrintPll(char *prefix, int refclk, int m1, int m2, int n, int p1, int p2) } /** - * Returns whether any output on the specified pipe is an LVDS output + * Returns whether any output on the specified pipe is of the specified type */ Bool -i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type) +i830PipeHasType (I830_xf86CrtcPtr crtc, int type) { - I830Ptr pI830 = I830PTR(pScrn); - int i; + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + int i; for (i = 0; i < pI830->num_outputs; i++) - if (pI830->output[i].enabled && pI830->output[i].pipe == pipe) + { + I830_xf86OutputPtr output = pI830->xf86_output[i]; + if (output->crtc == crtc) { - if (pI830->output[i].type == type) + I830OutputPrivatePtr intel_output = output->driver_private; + if (intel_output->type == type) return TRUE; } + } return FALSE; } @@ -86,9 +91,10 @@ i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type) * clk = refclk * (5 * m1 + m2) / n / (p1 * p2) */ static Bool -i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2, +i830PllIsValid(I830_xf86CrtcPtr crtc, int refclk, int m1, int m2, int n, int p1, int p2) { + ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); int p, m, vco, dotclock; int min_m1, max_m1, min_m2, max_m2, min_m, max_m, min_n, max_n; @@ -105,7 +111,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2, max_n = 8; min_p1 = 1; max_p1 = 8; - if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) { + if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) { min_p = 7; max_p = 98; } else { @@ -171,9 +177,10 @@ i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2, * clk = refclk * (5 * m1 + m2) / n / (p1 * p2) */ static Bool -i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk, +i830FindBestPLL(I830_xf86CrtcPtr crtc, int target, int refclk, int *outm1, int *outm2, int *outn, int *outp1, int *outp2) { + ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); int m1, m2, n, p1, p2; int err = target; @@ -188,7 +195,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk, max_n = 8; min_p1 = 1; max_p1 = 8; - if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) { + if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) { /* The single-channel range is 25-112Mhz, and dual-channel * is 80-224Mhz. Prefer single channel as much as possible. */ @@ -224,7 +231,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk, for (p1 = min_p1; p1 <= max_p1; p1++) { int clock, this_err; - if (!i830PllIsValid(pScrn, pipe, refclk, m1, m2, n, + if (!i830PllIsValid(crtc, refclk, m1, m2, n, p1, p2)) { continue; } @@ -255,10 +262,12 @@ i830WaitForVblank(ScrnInfoPtr pScreen) } void -i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) +i830PipeSetBase(I830_xf86CrtcPtr crtc, int x, int y) { + ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); - I830PipePtr pI830Pipe = &pI830->pipes[pipe]; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; unsigned long Start; int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); @@ -277,8 +286,8 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); } - pI830Pipe->x = x; - pI830Pipe->y = y; + crtc->x = x; + crtc->y = y; } /** @@ -291,19 +300,21 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y) * - Closer in refresh rate to the requested mode. */ DisplayModePtr -i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode) +i830PipeFindClosestMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode) { + ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); DisplayModePtr pBest = NULL, pScan = NULL; int i; /* Assume that there's only one output connected to the given CRTC. */ - for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].pipe == pipe && - pI830->output[i].enabled && - pI830->output[i].probed_modes != NULL) + for (i = 0; i < pI830->num_outputs; i++) + { + I830_xf86OutputPtr output = pI830->xf86_output[i]; + if (output->crtc == crtc && output->probed_modes != NULL) { - pScan = pI830->output[i].probed_modes; + pScan = output->probed_modes; + break; } } @@ -311,9 +322,10 @@ i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode) * spam the desired mode in. */ if (pScan == NULL) { + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No pipe mode list for pipe %d," - "continuing with desired mode\n", pipe); + "continuing with desired mode\n", intel_crtc->pipe); return pMode; } @@ -367,6 +379,8 @@ i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode) " continuing with desired mode %dx%d@%.1f\n", pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); } else if (!I830ModesEqual(pBest, pMode)) { + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 " "mode %dx%d@%.1f\n", pipe, @@ -382,13 +396,14 @@ i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode) */ Bool -i830PipeInUse (ScrnInfoPtr pScrn, int pipe) +i830PipeInUse (I830_xf86CrtcPtr crtc) { + ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); int i; for (i = 0; i < pI830->num_outputs; i++) - if (pI830->output[i].enabled && pI830->output[i].pipe == pipe) + if (pI830->xf86_output[i]->crtc == crtc) return TRUE; return FALSE; } @@ -402,11 +417,13 @@ i830PipeInUse (ScrnInfoPtr pScrn, int pipe) * display data. */ Bool -i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, +i830PipeSetMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode, Bool plane_enable) { + ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); - I830PipePtr pI830Pipe = &pI830->pipes[pipe]; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0; CARD32 dpll = 0, fp = 0, temp; CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; @@ -434,28 +451,34 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, Bool didLock = FALSE; #endif - if (I830ModesEqual(&pI830Pipe->curMode, pMode)) + if (I830ModesEqual(&crtc->curMode, pMode)) return TRUE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n", pMode->Clock); - pI830->pipes[pipe].enabled = i830PipeInUse (pScrn, pipe); + crtc->enabled = i830PipeInUse (crtc); - if (!pI830->pipes[pipe].enabled) + if (!crtc->enabled) + { + /* XXX disable crtc? */ return TRUE; + } #ifdef XF86DRI didLock = I830DRILock(pScrn); #endif - for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].pipe != pipe || !pI830->output[i].enabled) + for (i = 0; i < pI830->num_outputs; i++) + { + I830_xf86OutputPtr output = pI830->xf86_output[i]; + I830OutputPrivatePtr intel_output = output->driver_private; + if (output->crtc != crtc) continue; - pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode); + (*output->funcs->pre_set_mode)(output, pMode); - switch (pI830->output[i].type) { + switch (intel_output->type) { case I830_OUTPUT_LVDS: is_lvds = TRUE; break; @@ -549,7 +572,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, } else { refclk = 48000; } - ok = i830FindBestPLL(pScrn, pipe, pixel_clock, refclk, &m1, &m2, &n, + ok = i830FindBestPLL(crtc, pixel_clock, refclk, &m1, &m2, &n, &p1, &p2); if (!ok) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -636,7 +659,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, FatalError("unknown display bpp\n"); } - if (pI830Pipe->gammaEnabled) { + if (intel_crtc->gammaEnabled) { dspcntr |= DISPPLANE_GAMMA_ENABLE; } @@ -672,8 +695,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, } for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].pipe == pipe) - pI830->output[i].post_set_mode(pScrn, &pI830->output[i], pMode); + I830_xf86OutputPtr output = pI830->xf86_output[i]; + if (output->crtc == crtc) + (*output->funcs->post_set_mode)(output, pMode); } OUTREG(htot_reg, htot); @@ -685,7 +709,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp); OUTREG(dspsize_reg, dspsize); OUTREG(dsppos_reg, 0); - i830PipeSetBase(pScrn, pipe, pI830Pipe->x, pI830Pipe->y); + i830PipeSetBase(crtc, crtc->x, crtc->y); OUTREG(pipesrc_reg, pipesrc); /* Then, turn the pipe on first */ @@ -697,7 +721,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, OUTREG(dspcntr_reg, dspcntr); } - pI830Pipe->curMode = *pMode; + crtc->curMode = *pMode; ret = TRUE; done: @@ -712,28 +736,33 @@ void i830DisableUnusedFunctions(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - int output, pipe; + int o, pipe; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n"); - for (output = 0; output < pI830->num_outputs; output++) { - if (!pI830->output[output].enabled) - pI830->output[output].dpms(pScrn, &pI830->output[output], DPMSModeOff); + for (o = 0; o < pI830->num_outputs; o++) + { + I830_xf86OutputPtr output = pI830->xf86_output[o]; + if (!output->crtc) + (*output->funcs->dpms)(output, DPMSModeOff); } /* Now, any unused plane, pipe, and DPLL (FIXME: except for DVO, i915 * internal TV) should have no outputs trying to pull data out of it, so * we're ready to turn those off. */ - for (pipe = 0; pipe < pI830->num_pipes; pipe++) { - I830PipePtr pI830Pipe = &pI830->pipes[pipe]; + for (pipe = 0; pipe < pI830->num_pipes; pipe++) + { + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[pipe]; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; int dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR; int pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF; int dpll_reg = pipe == 0 ? DPLL_A : DPLL_B; CARD32 dspcntr, pipeconf, dpll; char *pipe_name = pipe == 0 ? "A" : "B"; - if (pI830Pipe->enabled) + if (crtc->enabled) continue; dspcntr = INREG(dspcntr_reg); @@ -761,7 +790,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE); } - memset(&pI830Pipe->curMode, 0, sizeof(pI830Pipe->curMode)); + memset(&crtc->curMode, 0, sizeof(crtc->curMode)); } } @@ -780,9 +809,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) for (i = 0; i < pI830->num_pipes; i++) { - ok = i830PipeSetMode(pScrn, - i830PipeFindClosestMode(pScrn, i, pMode), - i, TRUE); + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[i]; + ok = i830PipeSetMode(crtc, + i830PipeFindClosestMode(crtc, pMode), + TRUE); if (!ok) goto done; } @@ -802,7 +832,9 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) /* If we might have enabled/disabled some pipes, we need to reset * cloning mode support. */ - if (pI830->pipes[0].enabled && pI830->pipes[1].enabled) + if (pI830->num_pipes >= 2 && + pI830->xf86_crtc[0]->enabled && + pI830->xf86_crtc[1]->enabled) pI830->Clone = TRUE; else pI830->Clone = FALSE; @@ -834,6 +866,7 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n"); for (i = 0; i < pI830->num_pipes; i++) { + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[i]; CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i); CARD32 pipeconf = INREG(PIPEACONF + (PIPEBCONF - PIPEACONF) * i); Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0; @@ -841,53 +874,37 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, " Pipe %c is %s\n", - 'A' + i, pI830->pipes[i].enabled ? "on" : "off"); + 'A' + i, crtc->enabled ? "on" : "off"); xf86DrvMsg(pScrn->scrnIndex, X_INFO, " Display plane %c is now %s and connected to pipe %c.\n", 'A' + i, - pI830->pipes[i].enabled ? "enabled" : "disabled", + crtc->enabled ? "enabled" : "disabled", dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A'); - if (hw_pipe_enable != pI830->pipes[i].enabled) { + if (hw_pipe_enable != crtc->enabled) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, " Hardware claims pipe %c is %s while software " "believes it is %s\n", 'A' + i, hw_pipe_enable ? "on" : "off", - pI830->pipes[i].enabled ? "on" : "off"); + crtc->enabled ? "on" : "off"); } - if (hw_plane_enable != pI830->pipes[i].enabled) { + if (hw_plane_enable != crtc->enabled) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, " Hardware claims plane %c is %s while software " "believes it is %s\n", 'A' + i, hw_plane_enable ? "on" : "off", - pI830->pipes[i].enabled ? "on" : "off"); + crtc->enabled ? "on" : "off"); } } for (i = 0; i < pI830->num_outputs; i++) { - const char *name = NULL; - - switch (pI830->output[i].type) { - case I830_OUTPUT_ANALOG: - name = "CRT"; - break; - case I830_OUTPUT_LVDS: - name = "LVDS"; - break; - case I830_OUTPUT_SDVO: - name = "SDVO"; - break; - case I830_OUTPUT_DVO: - name = "DVO"; - break; - case I830_OUTPUT_TVOUT: - name = "TV"; - break; - } - + I830_xf86OutputPtr output = pI830->xf86_output[i]; + I830_xf86CrtcPtr crtc = output->crtc; + I830CrtcPrivatePtr intel_crtc = crtc ? crtc->driver_private : NULL; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, - " Output %s is %sabled and connected to pipe %c\n", - name, pI830->output[i].enabled ? "en" : "dis", - pI830->output[i].pipe == 0 ? 'A' : 'B'); + " Output %s is connected to pipe %s\n", + output->name, intel_crtc == NULL ? "none" : + (intel_crtc->pipe == 0 ? "A" : "B")); } } @@ -902,15 +919,19 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) * configured for it. In the future, it could choose to temporarily disable * some outputs to free up a pipe for its use. * - * \return monitor number, or -1 if no pipes are available. + * \return crtc, or NULL if no pipes are available. */ -int -i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output) + +I830_xf86CrtcPtr +i830GetLoadDetectPipe(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); - int i; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830OutputPrivatePtr intel_output = output->driver_private; + I830_xf86CrtcPtr crtc; + int i; /* VESA 640x480x72Hz mode to set on the pipe */ - DisplayModeRec mode = { + static DisplayModeRec mode = { NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT, 31500, 640, 664, 704, 832, 0, @@ -922,54 +943,37 @@ i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output) FALSE, FALSE, 0, NULL, 0, 0.0, 0.0 }; - /* If the output is not marked disabled, check if it's already assigned - * to an active pipe, and is alone on that pipe. If so, we're done. - */ - if (output->enabled) { - int pipeconf_reg = (output->pipe == 0) ? PIPEACONF : PIPEBCONF; - - if (INREG(pipeconf_reg) & PIPEACONF_ENABLE) { - /* Actually, maybe we don't need to be all alone on the pipe. - * The worst that should happen is false positives. Need to test, - * but actually fixing this during server startup is messy. - */ -#if 0 - for (i = 0; i < pI830->num_outputs; i++) { - if (&pI830->output[i] != output && - pI830->output[i].pipe == output->pipe) - { - return -1; - } - } -#endif - return output->pipe; - } - } + if (output->crtc) + return output->crtc; for (i = 0; i < pI830->num_pipes; i++) - if (!i830PipeInUse(pScrn, i)) + if (!i830PipeInUse(pI830->xf86_crtc[i])) break; if (i == pI830->num_pipes) - return -1; + return NULL; - output->load_detect_temp = TRUE; - output->pipe = i; - output->enabled = TRUE; + crtc = pI830->xf86_crtc[i]; - I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V); + output->crtc = crtc; + intel_output->load_detect_temp = TRUE; - i830PipeSetMode(pScrn, &mode, i, FALSE); + I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V); + i830PipeSetMode(crtc, &mode, FALSE); - return i; + return crtc; } void -i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output) +i830ReleaseLoadDetectPipe(I830_xf86OutputPtr output) { - if (output->load_detect_temp) { - output->enabled = FALSE; + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; + + if (intel_output->load_detect_temp) + { + output->crtc = NULL; + intel_output->load_detect_temp = FALSE; i830DisableUnusedFunctions(pScrn); - output->load_detect_temp = FALSE; } } diff --git a/src/i830_display.h b/src/i830_display.h index 361a3c67..4409728d 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -27,14 +27,14 @@ /* i830_display.c */ DisplayModePtr -i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode); -Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe, +i830PipeFindClosestMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode); +Bool i830PipeSetMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode, Bool plane_enable); void i830DisableUnusedFunctions(ScrnInfoPtr pScrn); Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); -void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y); +void i830PipeSetBase(I830_xf86CrtcPtr crtc, int x, int y); void i830WaitForVblank(ScrnInfoPtr pScrn); void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn); -int i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output); -void i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output); -Bool i830PipeInUse(ScrnInfoPtr pScrn, int pipe); +I830_xf86CrtcPtr i830GetLoadDetectPipe(I830_xf86OutputPtr output); +void i830ReleaseLoadDetectPipe(I830_xf86OutputPtr output); +Bool i830PipeInUse(I830_xf86CrtcPtr crtc); diff --git a/src/i830_dri.c b/src/i830_dri.c index 3b029185..af34afc5 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -1513,13 +1513,9 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on) if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) { if (on) { - if (pI830->pipes[1].enabled) { - if (pI830->drmMinor >= 6) - pipe.pipe = DRM_I830_VBLANK_PIPE_A | DRM_I830_VBLANK_PIPE_B; - else - pipe.pipe = DRM_I830_VBLANK_PIPE_B; + if (pI830->num_pipes > 1 && pI830->xf86_crtc[1]->enabled) pipe.pipe = DRM_I830_VBLANK_PIPE_B; - } else + else pipe.pipe = DRM_I830_VBLANK_PIPE_A; } else { pipe.pipe = 0; diff --git a/src/i830_driver.c b/src/i830_driver.c index 0ae1ee6a..d4d5fbc3 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -548,8 +548,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors); pI830 = I830PTR(pScrn); - for(p=0; p < pI830->num_pipes; p++) { - I830PipePtr pI830Pipe = &pI830->pipes[p]; + for(p=0; p < pI830->num_pipes; p++) + { + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[p]; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; if (p == 0) { palreg = PALETTE_A; @@ -563,10 +565,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, dspsurf = DSPBSURF; } - if (pI830Pipe->enabled == 0) + if (crtc->enabled == 0) continue; - pI830Pipe->gammaEnabled = 1; + intel_crtc->gammaEnabled = 1; /* To ensure gamma is enabled we need to turn off and on the plane */ temp = INREG(dspreg); @@ -1261,33 +1263,44 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) /* Perform the pipe assignment of outputs. This is a kludge until * we have better configuration support in the generic RandR code */ - for (i = 0; i < pI830->num_outputs; i++) { - pI830->output[i].enabled = FALSE; + for (i = 0; i < pI830->num_outputs; i++) + { + I830_xf86OutputPtr output = pI830->xf86_output[i]; + I830OutputPrivatePtr intel_output = output->driver_private; + I830_xf86CrtcPtr crtc; + int p; - switch (pI830->output[i].type) { + output->crtc = NULL; + + switch (intel_output->type) { case I830_OUTPUT_LVDS: /* LVDS must live on pipe B for two-pipe devices */ - pI830->output[i].pipe = pI830->num_pipes - 1; - pI830->output[i].enabled = TRUE; + crtc = pI830->xf86_crtc[pI830->num_pipes - 1]; + if (!i830PipeInUse (crtc)) + output->crtc = crtc; break; case I830_OUTPUT_ANALOG: case I830_OUTPUT_DVO: case I830_OUTPUT_SDVO: - if (pI830->output[i].detect(pScrn, &pI830->output[i]) != - OUTPUT_STATUS_DISCONNECTED) { - if (!i830PipeInUse(pScrn, 0)) { - pI830->output[i].pipe = 0; - pI830->output[i].enabled = TRUE; - } else if (!i830PipeInUse(pScrn, 1)) { - pI830->output[i].pipe = 1; - pI830->output[i].enabled = TRUE; + if ((*output->funcs->detect)(output) != OUTPUT_STATUS_DISCONNECTED) + { + for (p = 0; p < pI830->num_pipes; p++) + { + crtc = pI830->xf86_crtc[p]; + if (!i830PipeInUse(crtc)) + { + output->crtc = crtc; + break; + } } } break; case I830_OUTPUT_TVOUT: - if (!i830PipeInUse(pScrn, 0)) { - pI830->output[i].pipe = 0; - pI830->output[i].enabled = TRUE; + crtc = pI830->xf86_crtc[0]; + if ((*output->funcs->detect)(output) != OUTPUT_STATUS_DISCONNECTED && + !i830PipeInUse(crtc)) + { + output->crtc = crtc; } break; default: @@ -1296,10 +1309,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) } } - for (i = 0; i < pI830->num_pipes; i++) { - pI830->pipes[i].enabled = i830PipeInUse(pScrn, i); + for (i = 0; i < pI830->num_pipes; i++) + { + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[i]; + crtc->enabled = i830PipeInUse(crtc); } - + pI830->rotation = RR_Rotate_0; if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) { pI830->InitialRotation = 0; @@ -2108,8 +2123,9 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL); for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].save != NULL) - pI830->output[i].save(pScrn, &pI830->output[i]); + I830_xf86OutputPtr output = pI830->xf86_output[i]; + if (output->funcs->save) + (*output->funcs->save) (output); } vgaHWUnlock(hwp); @@ -2149,7 +2165,8 @@ RestoreHWState(ScrnInfoPtr pScrn) /* Disable outputs if necessary */ for (i = 0; i < pI830->num_outputs; i++) { - pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], NULL); + I830_xf86OutputPtr output = pI830->xf86_output[i]; + (*output->funcs->pre_set_mode) (output, NULL); } i830WaitForVblank(pScrn); @@ -2199,7 +2216,8 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); for (i = 0; i < pI830->num_outputs; i++) { - pI830->output[i].restore(pScrn, &pI830->output[i]); + I830_xf86OutputPtr output = pI830->xf86_output[i]; + (*output->funcs->restore) (output); } if (IS_I965G(pI830)) { @@ -3235,8 +3253,11 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) } for (i = 0; i < pI830->num_pipes; i++) - if (pI830->pipes[i].enabled) - i830PipeSetBase(pScrn, i, x, y); + { + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[i]; + if (crtc->enabled) + i830PipeSetBase(crtc, x, y); + } } static void @@ -3349,17 +3370,17 @@ I830EnterVT(int scrnIndex, int flags) for (i = 0; i < pI830->num_pipes; i++) { - I830PipePtr pipe = &pI830->pipes[i]; + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[i]; + /* Mark that we'll need to re-set the mode for sure */ - memset(&pipe->curMode, 0, sizeof(pipe->curMode)); - if (!pipe->desiredMode.CrtcHDisplay) - { - pipe->desiredMode = *i830PipeFindClosestMode (pScrn, i, - pScrn->currentMode); - } - if (!i830PipeSetMode (pScrn, &pipe->desiredMode, i, TRUE)) + memset(&crtc->curMode, 0, sizeof(crtc->curMode)); + if (!crtc->desiredMode.CrtcHDisplay) + crtc->desiredMode = *i830PipeFindClosestMode (crtc, pScrn->currentMode); + + if (!i830PipeSetMode (crtc, &crtc->desiredMode, TRUE)) return FALSE; - i830PipeSetBase(pScrn, i, pipe->x, pipe->y); + + i830PipeSetBase(crtc, crtc->x, crtc->y); } i830DisableUnusedFunctions(pScrn); @@ -3527,7 +3548,7 @@ I830SaveScreen(ScreenPtr pScreen, int mode) base = DSPBADDR; surf = DSPBSURF; } - if (pI830->pipes[i].enabled) { + if (pI830->xf86_crtc[i]->enabled) { temp = INREG(ctrl); if (on) temp |= DISPLAY_PLANE_ENABLE; @@ -3565,10 +3586,15 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, CARD32 temp, ctrl, base; for (i = 0; i < pI830->num_outputs; i++) { - pI830->output[i].dpms(pScrn, &pI830->output[i], PowerManagementMode); + I830_xf86OutputPtr output = pI830->xf86_output[i]; + + (*output->funcs->dpms) (output, PowerManagementMode); } - for (i = 0; i < pI830->num_pipes; i++) { + for (i = 0; i < pI830->num_pipes; i++) + { + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[i]; + if (i == 0) { ctrl = DSPACNTR; base = DSPABASE; @@ -3576,7 +3602,8 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, ctrl = DSPBCNTR; base = DSPBADDR; } - if (pI830->pipes[i].enabled) { + /* XXX pipe disable too? */ + if (crtc->enabled) { temp = INREG(ctrl); if (PowerManagementMode == DPMSModeOn) temp |= DISPLAY_PLANE_ENABLE; diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 31fb76ba..b2921902 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -57,18 +57,21 @@ struct _I830DVODriver i830_dvo_drivers[] = #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver)) static void -i830_dvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +i830_dvo_dpms(I830_xf86OutputPtr output, int mode) { + I830OutputPrivatePtr intel_output = output->driver_private; if (mode == DPMSModeOn) - output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, TRUE); + (*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, TRUE); else - output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, FALSE); + (*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, FALSE); } static void -i830_dvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_dvo_save(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830OutputPrivatePtr intel_output = output->driver_private; /* Each output should probably just save the registers it touches, but for * now, use more overkill. @@ -77,61 +80,68 @@ i830_dvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) pI830->saveDVOB = INREG(DVOB); pI830->saveDVOC = INREG(DVOC); - output->i2c_drv->vid_rec->SaveRegs(output->i2c_drv->dev_priv); + (*intel_output->i2c_drv->vid_rec->SaveRegs)(intel_output->i2c_drv->dev_priv); } static void -i830_dvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_dvo_restore(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830OutputPrivatePtr intel_output = output->driver_private; OUTREG(DVOA, pI830->saveDVOA); OUTREG(DVOB, pI830->saveDVOB); OUTREG(DVOC, pI830->saveDVOC); - output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv); + (*intel_output->i2c_drv->vid_rec->RestoreRegs)(intel_output->i2c_drv->dev_priv); } static int -i830_dvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_dvo_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode) { + I830OutputPrivatePtr intel_output = output->driver_private; + if (pMode->Flags & V_DBLSCAN) return MODE_NO_DBLESCAN; /* XXX: Validate clock range */ - if (output->i2c_drv->vid_rec->ModeValid(output->i2c_drv->dev_priv, pMode)) + if ((*intel_output->i2c_drv->vid_rec->ModeValid)(intel_output->i2c_drv->dev_priv, pMode)) return MODE_OK; else return MODE_BAD; } static void -i830_dvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_dvo_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode) { - I830Ptr pI830 = I830PTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830OutputPrivatePtr intel_output = output->driver_private; - output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, pMode); + (*intel_output->i2c_drv->vid_rec->Mode)(intel_output->i2c_drv->dev_priv, pMode); OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE); } static void -i830_dvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_dvo_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode) { - I830Ptr pI830 = I830PTR(pScrn); - CARD32 dvo; - int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830_xf86CrtcPtr crtc = output->crtc; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + int pipe = intel_crtc->pipe; + CARD32 dvo; + int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; /* Save the data order, since I don't know what it should be set to. */ dvo = INREG(DVOC) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); dvo |= DVO_ENABLE; dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH; - if (output->pipe == 1) + if (pipe == 1) dvo |= DVO_PIPE_B_SELECT; if (pMode->Flags & V_PHSYNC) @@ -155,7 +165,7 @@ i830_dvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, * Unimplemented. */ static enum detect_status -i830_dvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_dvo_detect(I830_xf86OutputPtr output) { return OUTPUT_STATUS_UNKNOWN; } @@ -191,46 +201,81 @@ I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, return FALSE; } +static void +i830_dvo_destroy (I830_xf86OutputPtr output) +{ + I830OutputPrivatePtr intel_output = output->driver_private; + + if (intel_output) + { + if (intel_output->pI2CBus) + xf86DestroyI2CBusRec (intel_output->pI2CBus, TRUE, TRUE); + if (intel_output->pDDCBus) + xf86DestroyI2CBusRec (intel_output->pDDCBus, TRUE, TRUE); + /* XXX sub module cleanup? */ + xfree (intel_output); + } +} + +static const I830_xf86OutputFuncsRec i830_dvo_output_funcs = { + .dpms = i830_dvo_dpms, + .save = i830_dvo_save, + .restore = i830_dvo_restore, + .mode_valid = i830_dvo_mode_valid, + .pre_set_mode = i830_dvo_pre_set_mode, + .post_set_mode = i830_dvo_post_set_mode, + .detect = i830_dvo_detect, + .get_modes = i830_ddc_get_modes, + .destroy = i830_dvo_destroy +}; + void i830_dvo_init(ScrnInfoPtr pScrn) { - I830Ptr pI830 = I830PTR(pScrn); - Bool ret; - int i = pI830->num_outputs; - - pI830->output[i].type = I830_OUTPUT_DVO; - pI830->output[i].dpms = i830_dvo_dpms; - pI830->output[i].save = i830_dvo_save; - pI830->output[i].restore = i830_dvo_restore; - pI830->output[i].mode_valid = i830_dvo_mode_valid; - pI830->output[i].pre_set_mode = i830_dvo_pre_set_mode; - pI830->output[i].post_set_mode = i830_dvo_post_set_mode; - pI830->output[i].detect = i830_dvo_detect; - pI830->output[i].get_modes = i830_ddc_get_modes; + I830_xf86OutputPtr output; + I830OutputPrivatePtr intel_output; + int ret; + output = i830xf86OutputCreate (pScrn, &i830_dvo_output_funcs, + "ADD AGP card"); + if (!output) + return; + intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1); + if (!intel_output) + { + i830xf86OutputDestroy (output); + return; + } + intel_output->type = I830_OUTPUT_DVO; + output->driver_private = intel_output; + /* Set up the I2C and DDC buses */ - ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E"); + ret = I830I2CInit(pScrn, &intel_output->pI2CBus, GPIOE, "DVOI2C_E"); if (!ret) + { + i830xf86OutputDestroy (output); return; + } - ret = I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D"); - if (!ret) { - xf86DestroyI2CBusRec(pI830->output[i].pI2CBus, TRUE, TRUE); + ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D"); + if (!ret) + { + i830xf86OutputDestroy (output); return; } /* Now, try to find a controller */ - ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus, - &pI830->output[i].i2c_drv); - if (ret) { + ret = I830I2CDetectDVOControllers(pScrn, intel_output->pI2CBus, + &intel_output->i2c_drv); + if (ret) + { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n", - pI830->output[i].i2c_drv->modulename, - pI830->output[i].pI2CBus->DriverPrivate.uval); - } else { - xf86DestroyI2CBusRec(pI830->output[i].pI2CBus, TRUE, TRUE); - xf86DestroyI2CBusRec(pI830->output[i].pDDCBus, TRUE, TRUE); + intel_output->i2c_drv->modulename, + intel_output->pI2CBus->DriverPrivate.uval); + } + else + { + i830xf86OutputDestroy (output); return; } - - pI830->num_outputs++; } diff --git a/src/i830_lvds.c b/src/i830_lvds.c index ea45420f..e72b9e87 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -73,8 +73,10 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn, Bool on) } static void -i830_lvds_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +i830_lvds_dpms (I830_xf86OutputPtr output, int mode) { + ScrnInfoPtr pScrn = output->scrn; + if (mode == DPMSModeOn) i830SetLVDSPanelPower(pScrn, TRUE); else @@ -82,9 +84,10 @@ i830_lvds_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) } static void -i830_lvds_save(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_lvds_save (I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); pI830->savePP_ON = INREG(LVDSPP_ON); pI830->savePP_OFF = INREG(LVDSPP_OFF); @@ -106,9 +109,10 @@ i830_lvds_save(ScrnInfoPtr pScrn, I830OutputPtr output) } static void -i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_lvds_restore(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL); OUTREG(LVDSPP_ON, pI830->savePP_ON); @@ -123,16 +127,15 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output) } static int -i830_lvds_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_lvds_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode) { return MODE_OK; } static void -i830_lvds_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_lvds_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode) { + ScrnInfoPtr pScrn = output->scrn; /* Always make sure the LVDS is off before we play with DPLLs and pipe * configuration. We can skip this in some cases (for example, going * between hi-res modes with automatic panel scaling are fine), but be @@ -142,11 +145,11 @@ i830_lvds_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, } static void -i830_lvds_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_lvds_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode) { - I830Ptr pI830 = I830PTR(pScrn); - CARD32 pfit_control; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + CARD32 pfit_control; /* Enable automatic panel scaling so that non-native modes fill the * screen. Should be enabled before the pipe is enabled, according to @@ -182,7 +185,7 @@ i830_lvds_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, * been set up if the LVDS was actually connected anyway. */ static enum detect_status -i830_lvds_detect(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_lvds_detect(I830_xf86OutputPtr output) { return OUTPUT_STATUS_CONNECTED; } @@ -191,13 +194,14 @@ i830_lvds_detect(ScrnInfoPtr pScrn, I830OutputPtr output) * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. */ static DisplayModePtr -i830_lvds_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_lvds_get_modes(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); - DisplayModePtr modes, new; - char stmp[32]; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr modes, new; + char stmp[32]; - modes = i830_ddc_get_modes(pScrn, output); + modes = i830_ddc_get_modes(output); if (modes != NULL) return modes; @@ -220,10 +224,34 @@ i830_lvds_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) return new; } +static void +i830_lvds_destroy (I830_xf86OutputPtr output) +{ + I830OutputPrivatePtr intel_output = output->driver_private; + + if (intel_output) + xfree (intel_output); +} + +static const I830_xf86OutputFuncsRec i830_lvds_output_funcs = { + .dpms = i830_lvds_dpms, + .save = i830_lvds_save, + .restore = i830_lvds_restore, + .mode_valid = i830_lvds_mode_valid, + .pre_set_mode = i830_lvds_pre_set_mode, + .post_set_mode = i830_lvds_post_set_mode, + .detect = i830_lvds_detect, + .get_modes = i830_lvds_get_modes, + .destroy = i830_lvds_destroy +}; + void i830_lvds_init(ScrnInfoPtr pScrn) { - I830Ptr pI830 = I830PTR(pScrn); + I830Ptr pI830 = I830PTR(pScrn); + I830_xf86OutputPtr output; + I830OutputPrivatePtr intel_output; + /* Get the LVDS fixed mode out of the BIOS. We should support LVDS with * the BIOS being unavailable or broken, but lack the configuration options @@ -258,21 +286,20 @@ i830_lvds_init(ScrnInfoPtr pScrn) } } - pI830->output[pI830->num_outputs].type = I830_OUTPUT_LVDS; - pI830->output[pI830->num_outputs].dpms = i830_lvds_dpms; - pI830->output[pI830->num_outputs].save = i830_lvds_save; - pI830->output[pI830->num_outputs].restore = i830_lvds_restore; - pI830->output[pI830->num_outputs].mode_valid = i830_lvds_mode_valid; - pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode; - pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode; - pI830->output[pI830->num_outputs].detect = i830_lvds_detect; - pI830->output[pI830->num_outputs].get_modes = i830_lvds_get_modes; + output = i830xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "Built-in LCD panel"); + if (!output) + return; + intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1); + if (!intel_output) + { + i830xf86OutputDestroy (output); + return; + } + intel_output->type = I830_OUTPUT_LVDS; + output->driver_private = intel_output; /* Set up the LVDS DDC channel. Most panels won't support it, but it can * be useful if available. */ - I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus, - GPIOC, "LVDSDDC_C"); - - pI830->num_outputs++; + I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C"); } diff --git a/src/i830_modes.c b/src/i830_modes.c index 7fdd40ed..7d4bcbae 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -427,47 +427,44 @@ i830_reprobe_output_modes(ScrnInfoPtr pScrn) int i; /* Re-probe the list of modes for each output. */ - for (i = 0; i < pI830->num_outputs; i++) { + for (i = 0; i < pI830->num_outputs; i++) + { + I830_xf86OutputPtr output = pI830->xf86_output[i]; DisplayModePtr mode; - while (pI830->output[i].probed_modes != NULL) { - xf86DeleteMode(&pI830->output[i].probed_modes, - pI830->output[i].probed_modes); - } + while (output->probed_modes != NULL) + xf86DeleteMode(&output->probed_modes, output->probed_modes); - pI830->output[i].probed_modes = - pI830->output[i].get_modes(pScrn, &pI830->output[i]); + output->probed_modes = (*output->funcs->get_modes) (output); /* Set the DDC properties to whatever first output has DDC information. */ - if (pI830->output[i].MonInfo != NULL && !properties_set) { - xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo); + if (output->MonInfo != NULL && !properties_set) { + xf86SetDDCproperties(pScrn, output->MonInfo); properties_set = TRUE; } - if (pI830->output[i].probed_modes != NULL) { + if (output->probed_modes != NULL) + { /* silently prune modes down to ones matching the user's * configuration. */ - i830xf86ValidateModesUserConfig(pScrn, - pI830->output[i].probed_modes); - i830xf86PruneInvalidModes(pScrn, &pI830->output[i].probed_modes, - FALSE); + i830xf86ValidateModesUserConfig(pScrn, output->probed_modes); + i830xf86PruneInvalidModes(pScrn, &output->probed_modes, FALSE); } #ifdef DEBUG_REPROBE - if (pI830->output[i].probed_modes != NULL) { + if (output->probed_modes != NULL) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing probed modes for output %s\n", - i830_output_type_names[pI830->output[i].type]); + output->name); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No remaining probed modes for output %s\n", - i830_output_type_names[pI830->output[i].type]); + output->name); } #endif - for (mode = pI830->output[i].probed_modes; mode != NULL; - mode = mode->next) + 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. @@ -515,9 +512,9 @@ i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn) * care about enough to make some sort of unioned list. */ for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].probed_modes != NULL) { - pScrn->modes = - i830xf86DuplicateModes(pScrn, pI830->output[i].probed_modes); + I830_xf86OutputPtr output = pI830->xf86_output[i]; + if (output->probed_modes != NULL) { + pScrn->modes = i830xf86DuplicateModes(pScrn, output->probed_modes); break; } } @@ -568,10 +565,10 @@ i830_set_default_screen_size(ScrnInfoPtr pScrn) * set for the currently-connected outputs. */ for (i = 0; i < pI830->num_outputs; i++) { + I830_xf86OutputPtr output = pI830->xf86_output[i]; DisplayModePtr mode; - for (mode = pI830->output[i].probed_modes; mode != NULL; - mode = mode->next) + for (mode = output->probed_modes; mode != NULL; mode = mode->next) { if (mode->HDisplay > maxX) maxX = mode->HDisplay; @@ -618,8 +615,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time) #define EDID_ATOM_NAME "EDID_DATA" static void -i830_ddc_set_edid_property(ScrnInfoPtr pScrn, I830OutputPtr output, - void *data, int data_len) +i830_ddc_set_edid_property(I830_xf86OutputPtr output, void *data, int data_len) { Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE); @@ -640,16 +636,18 @@ i830_ddc_set_edid_property(ScrnInfoPtr pScrn, I830OutputPtr output, * Generic get_modes function using DDC, used by many outputs. */ DisplayModePtr -i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_ddc_get_modes(I830_xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; xf86MonPtr ddc_mon; DisplayModePtr ddc_modes, mode; int i; - ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus); + ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, intel_output->pDDCBus); if (ddc_mon == NULL) { #ifdef RANDR_12_INTERFACE - i830_ddc_set_edid_property(pScrn, output, NULL, 0); + i830_ddc_set_edid_property(output, NULL, 0); #endif return NULL; } @@ -660,24 +658,23 @@ i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) #ifdef RANDR_12_INTERFACE if (output->MonInfo->ver.version == 1) { - i830_ddc_set_edid_property(pScrn, output, ddc_mon->rawData, 128); + i830_ddc_set_edid_property(output, ddc_mon->rawData, 128); } else if (output->MonInfo->ver.version == 2) { - i830_ddc_set_edid_property(pScrn, output, ddc_mon->rawData, 256); + i830_ddc_set_edid_property(output, ddc_mon->rawData, 256); } else { - i830_ddc_set_edid_property(pScrn, output, NULL, 0); + i830_ddc_set_edid_property(output, NULL, 0); } #endif /* Debug info for now, at least */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", - i830_output_type_names[output->type]); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name); xf86PrintEDID(output->MonInfo); ddc_modes = i830GetDDCModes(pScrn, ddc_mon); /* Strip out any modes that can't be supported on this output. */ for (mode = ddc_modes; mode != NULL; mode = mode->next) { - int status = output->mode_valid(pScrn, output, mode); + int status = (*output->funcs->mode_valid)(output, mode); if (status != MODE_OK) mode->status = status; diff --git a/src/i830_randr.c b/src/i830_randr.c index a530ffbf..d6a3131c 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -52,9 +52,6 @@ typedef struct _i830RandRInfo { int maxY; Rotation rotation; /* current mode */ Rotation supported_rotations; /* driver supported */ -#ifdef RANDR_12_INTERFACE - DisplayModePtr modes[MAX_DISPLAY_PIPES]; -#endif } XF86RandRInfoRec, *XF86RandRInfoPtr; #ifdef RANDR_12_INTERFACE @@ -472,151 +469,127 @@ I830RandRScreenSetSize (ScreenPtr pScreen, } static Bool -I830RandRCrtcNotify (RRCrtcPtr crtc) +I830RandRCrtcNotify (RRCrtcPtr randr_crtc) { - ScreenPtr pScreen = crtc->pScreen; + ScreenPtr pScreen = randr_crtc->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); - RRModePtr mode = NULL; + RRModePtr randr_mode = NULL; int x; int y; Rotation rotation; int numOutputs; - RROutputPtr outputs[MAX_OUTPUTS]; - struct _I830OutputRec *output; - RROutputPtr rrout; - int pipe = (int) crtc->devPrivate; - I830PipePtr pI830Pipe = &pI830->pipes[pipe]; + RROutputPtr randr_outputs[MAX_OUTPUTS]; + RROutputPtr randr_output; + I830_xf86CrtcPtr crtc = randr_crtc->devPrivate; + I830_xf86OutputPtr output; int i, j; - DisplayModePtr pipeMode = &pI830Pipe->curMode; + DisplayModePtr curMode = &crtc->curMode; - x = pI830Pipe->x; - y = pI830Pipe->y; + x = crtc->x; + y = crtc->y; rotation = RR_Rotate_0; numOutputs = 0; - mode = NULL; + randr_mode = NULL; for (i = 0; i < pI830->num_outputs; i++) { - output = &pI830->output[i]; - if (output->enabled && output->pipe == pipe) + output = pI830->xf86_output[i]; + if (output->crtc == crtc) { - rrout = output->randr_output; - outputs[numOutputs++] = rrout; + randr_output = output->randr_output; + randr_outputs[numOutputs++] = randr_output; /* * We make copies of modes, so pointer equality * isn't sufficient */ - for (j = 0; j < rrout->numModes; j++) + for (j = 0; j < randr_output->numModes; j++) { - DisplayModePtr outMode = rrout->modes[j]->devPrivate; - if (I830ModesEqual(pipeMode, outMode)) + DisplayModePtr outMode = randr_output->modes[j]->devPrivate; + if (I830ModesEqual(curMode, outMode)) { - mode = rrout->modes[j]; + randr_mode = randr_output->modes[j]; break; } } } } - return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs); + return RRCrtcNotify (randr_crtc, randr_mode, x, y, + rotation, numOutputs, randr_outputs); } static Bool I830RandRCrtcSet (ScreenPtr pScreen, - RRCrtcPtr crtc, - RRModePtr mode, + RRCrtcPtr randr_crtc, + RRModePtr randr_mode, int x, int y, Rotation rotation, int num_randr_outputs, RROutputPtr *randr_outputs) { - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); - int pipe = (int) (crtc->devPrivate); - I830PipePtr pI830Pipe = &pI830->pipes[pipe]; - DisplayModePtr display_mode = mode ? mode->devPrivate : NULL; + I830_xf86CrtcPtr crtc = randr_crtc->devPrivate; + DisplayModePtr mode = randr_mode ? randr_mode->devPrivate : NULL; Bool changed = FALSE; - Bool disable = FALSE; int o, ro; - struct { - int pipe; - int enabled; - } save_output[MAX_OUTPUTS]; - Bool save_enabled = pI830Pipe->enabled; + I830_xf86CrtcPtr save_crtcs[MAX_OUTPUTS]; + Bool save_enabled = crtc->enabled; - if (display_mode != randrp->modes[pipe]) - { + if (!I830ModesEqual (&crtc->curMode, mode)) changed = TRUE; - if (!display_mode) - disable = TRUE; - } for (o = 0; o < pI830->num_outputs; o++) { - I830OutputPtr output = &pI830->output[o]; - RROutputPtr randr_output = NULL; + I830_xf86OutputPtr output = pI830->xf86_output[o]; + I830_xf86CrtcPtr new_crtc; + + save_crtcs[o] = output->crtc; - save_output[o].enabled = output->enabled; - save_output[o].pipe = output->pipe; + if (output->crtc == crtc) + new_crtc = NULL; + else + new_crtc = output->crtc; for (ro = 0; ro < num_randr_outputs; ro++) - { if (output->randr_output == randr_outputs[ro]) { - randr_output = randr_outputs[ro]; + new_crtc = crtc; break; } - } - if (randr_output) - { - if (output->pipe != pipe || !output->enabled) - { - output->pipe = pipe; - output->enabled = TRUE; - changed = TRUE; - } - } - else + if (new_crtc != output->crtc) { - /* Disable outputs which were on this pipe */ - if (output->enabled && output->pipe == pipe) - { - output->enabled = FALSE; - changed = TRUE; - disable = TRUE; - } + changed = TRUE; + output->crtc = new_crtc; } } if (changed) { - pI830Pipe->enabled = mode != NULL; + crtc->enabled = mode != NULL; + /* Sync the engine before adjust mode */ if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { (*pI830->AccelInfoRec->Sync)(pScrn); pI830->AccelInfoRec->NeedToSync = FALSE; } - if (display_mode) + if (mode) { - if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE)) + if (!i830PipeSetMode (crtc, mode, TRUE)) { - pI830Pipe->enabled = save_enabled; + crtc->enabled = save_enabled; for (o = 0; o < pI830->num_outputs; o++) { - I830OutputPtr output = &pI830->output[o]; - output->enabled = save_output[o].enabled; - output->pipe = save_output[o].pipe; + I830_xf86OutputPtr output = pI830->xf86_output[o]; + output->crtc = save_crtcs[o]; } return FALSE; } - pI830Pipe->desiredMode = *display_mode; - i830PipeSetBase(pScrn, pipe, x, y); + crtc->desiredMode = *mode; + i830PipeSetBase(crtc, x, y); } - randrp->modes[pipe] = display_mode; - if (disable) - i830DisableUnusedFunctions (pScrn); + i830DisableUnusedFunctions (pScrn); } - return I830RandRCrtcNotify (crtc); + return I830RandRCrtcNotify (randr_crtc); } static Bool @@ -696,23 +669,21 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn) RROutputPtr clones[MAX_OUTPUTS]; RRCrtcPtr crtcs[MAX_DISPLAY_PIPES]; int ncrtc; - I830OutputPtr output; int o, c, p; int clone_types; int crtc_types; int subpixel; RRCrtcPtr randr_crtc; - RROutputPtr randr_output; int nclone; for (o = 0; o < pI830->num_outputs; o++) { - output = &pI830->output[o]; - randr_output = output->randr_output; + I830_xf86OutputPtr output = pI830->xf86_output[o]; + I830OutputPrivatePtr intel_output = output->driver_private; /* * Valid crtcs */ - switch (output->type) { + switch (intel_output->type) { case I830_OUTPUT_DVO: case I830_OUTPUT_SDVO: crtc_types = ((1 << 0)| @@ -749,10 +720,10 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn) ncrtc = 0; for (p = 0; p < pI830->num_pipes; p++) if (crtc_types & (1 << p)) - crtcs[ncrtc++] = pI830->pipes[p].randr_crtc; + crtcs[ncrtc++] = pI830->xf86_crtc[p]->randr_crtc; - if (output->enabled) - randr_crtc = pI830->pipes[output->pipe].randr_crtc; + if (output->crtc) + randr_crtc = output->crtc->randr_crtc; else randr_crtc = NULL; @@ -765,7 +736,7 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn) output->mm_height); I830xf86RROutputSetModes (output->randr_output, output->probed_modes); - switch (output->detect(pScrn, output)) { + switch ((*output->funcs->detect)(output)) { case OUTPUT_STATUS_CONNECTED: RROutputSetConnection (output->randr_output, RR_Connected); break; @@ -785,8 +756,11 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn) nclone = 0; for (c = 0; c < pI830->num_outputs; c++) { - if (o != c && ((1 << pI830->output[c].type) & clone_types)) - clones[nclone++] = pI830->output[c].randr_output; + I830_xf86OutputPtr clone = pI830->xf86_output[c]; + I830OutputPrivatePtr intel_clone = clone->driver_private; + + if (o != c && ((1 << intel_clone->type) & clone_types)) + clones[nclone++] = clone->randr_output; } if (!RROutputSetClones (output->randr_output, clones, nclone)) return FALSE; @@ -812,35 +786,20 @@ I830RandRCreateObjects12 (ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); int p; - int o; if (!RRInit ()) return FALSE; /* - * Create RandR resources, then probe them + * Configure crtcs */ for (p = 0; p < pI830->num_pipes; p++) { - I830PipePtr pipe = &pI830->pipes[p]; - RRCrtcPtr randr_crtc = RRCrtcCreate ((void *) p); + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[p]; - if (!randr_crtc) - return FALSE; - RRCrtcGammaSetSize (randr_crtc, 256); - pipe->randr_crtc = randr_crtc; + RRCrtcGammaSetSize (crtc->randr_crtc, 256); } - for (o = 0; o < pI830->num_outputs; o++) - { - I830OutputPtr output = &pI830->output[o]; - const char *name = i830_output_type_names[output->type]; - RROutputPtr randr_output = RROutputCreate (name, strlen (name), - (void *) o); - if (!randr_output) - return FALSE; - output->randr_output = randr_output; - } return TRUE; } @@ -857,11 +816,11 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) * Attach RandR objects to screen */ for (p = 0; p < pI830->num_pipes; p++) - if (!RRCrtcAttachScreen (pI830->pipes[p].randr_crtc, pScreen)) + if (!RRCrtcAttachScreen (pI830->xf86_crtc[p]->randr_crtc, pScreen)) return FALSE; for (o = 0; o < pI830->num_outputs; o++) - if (!RROutputAttachScreen (pI830->output[o].randr_output, pScreen)) + if (!RROutputAttachScreen (pI830->xf86_output[o]->randr_output, pScreen)) return FALSE; /* @@ -870,13 +829,14 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) width = 0; height = 0; for (p = 0; p < pI830->num_pipes; p++) { - I830PipePtr pipe = &pI830->pipes[p]; - int pipe_width = pipe->x + pipe->curMode.HDisplay; - int pipe_height = pipe->y + pipe->curMode.VDisplay; - if (pipe->enabled && pipe_width > width) - width = pipe_width; - if (pipe->enabled && pipe_height > height) - height = pipe_height; + I830_xf86CrtcPtr crtc = pI830->xf86_crtc[p]; + 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; + if (crtc->enabled && crtc_height > height) + height = crtc_height; } if (width && height) @@ -900,7 +860,7 @@ I830RandRCreateScreenResources12 (ScreenPtr pScreen) } for (p = 0; p < pI830->num_pipes; p++) - I830RandRCrtcNotify (pI830->pipes[p].randr_crtc); + I830RandRCrtcNotify (pI830->xf86_crtc[p]->randr_crtc); if (randrp->virtualX == -1 || randrp->virtualY == -1) { @@ -1227,9 +1187,9 @@ I830RandRPreInit (ScrnInfoPtr pScrn) * the initial configuration */ for (o = 0; o < pI830->num_outputs; o++) - outputs[o] = pI830->output[o].randr_output; + outputs[o] = pI830->xf86_output[o]->randr_output; for (c = 0; c < pI830->num_pipes; c++) - crtcs[c] = pI830->pipes[c].randr_crtc; + crtcs[c] = pI830->xf86_crtc[c]->randr_crtc; if (!I830RRInitialConfiguration (outputs, output_crtcs, output_modes, pI830->num_outputs)) @@ -1253,30 +1213,19 @@ I830RandRPreInit (ScrnInfoPtr pScrn) pScrn->display->frameY0 = 0; for (o = 0; o < pI830->num_outputs; o++) { - RRModePtr randr_mode = output_modes[o]; - DisplayModePtr mode; - RRCrtcPtr randr_crtc = output_crtcs[o]; - int pipe; - Bool enabled; + I830_xf86OutputPtr output = pI830->xf86_output[o]; + RRModePtr randr_mode = output_modes[o]; + DisplayModePtr mode; + RRCrtcPtr randr_crtc = output_crtcs[o]; + I830_xf86CrtcPtr crtc = randr_crtc->devPrivate; if (randr_mode) mode = (DisplayModePtr) randr_mode->devPrivate; else mode = NULL; - if (randr_crtc) - { - pipe = (int) randr_crtc->devPrivate; - enabled = TRUE; - } - else - { - pipe = 0; - enabled = FALSE; - } if (mode) - pI830->pipes[pipe].desiredMode = *mode; - pI830->output[o].pipe = pipe; - pI830->output[o].enabled = enabled; + crtc->desiredMode = *mode; + output->crtc = crtc; } #endif i830_set_xf86_modes_from_outputs (pScrn); diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index fedb8a6a..a8eba4c0 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -80,30 +80,32 @@ struct i830_sdvo_priv { }; /** Read a single byte from the given address on the SDVO device. */ -static Bool i830_sdvo_read_byte(I830OutputPtr output, int addr, +static Bool i830_sdvo_read_byte(I830_xf86OutputPtr output, int addr, unsigned char *ch) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; if (!xf86I2CReadByte(&dev_priv->d, addr, ch)) { - xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR, + xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s slave %d.\n", - output->pI2CBus->BusName, dev_priv->d.SlaveAddr); + intel_output->pI2CBus->BusName, dev_priv->d.SlaveAddr); return FALSE; } return TRUE; } /** Write a single byte to the given address on the SDVO device. */ -static Bool i830_sdvo_write_byte(I830OutputPtr output, +static Bool i830_sdvo_write_byte(I830_xf86OutputPtr output, int addr, unsigned char ch) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; if (!xf86I2CWriteByte(&dev_priv->d, addr, ch)) { - xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR, + xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", - output->pI2CBus->BusName, dev_priv->d.SlaveAddr); + intel_output->pI2CBus->BusName, dev_priv->d.SlaveAddr); return FALSE; } return TRUE; @@ -164,16 +166,17 @@ static I2CSlaveAddr slaveAddr; * Writes out the data given in args (up to 8 bytes), followed by the opcode. */ static void -i830_sdvo_write_cmd(I830OutputPtr output, CARD8 cmd, void *args, int args_len) +i830_sdvo_write_cmd(I830_xf86OutputPtr output, CARD8 cmd, void *args, int args_len) { - int i; - struct i830_sdvo_priv *dev_priv = output->dev_priv; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + int i; if (slaveAddr && slaveAddr != dev_priv->d.SlaveAddr) ErrorF ("Mismatch slave addr %x != %x\n", slaveAddr, dev_priv->d.SlaveAddr); /* Write the SDVO command logging */ - xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO, "%s: W: %02X ", SDVO_NAME(dev_priv), cmd); + xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_INFO, "%s: W: %02X ", SDVO_NAME(dev_priv), cmd); for (i = 0; i < args_len; i++) LogWrite(1, "%02X ", ((CARD8 *)args)[i]); for (; i < 8; i++) @@ -210,10 +213,11 @@ static const char *cmd_status_names[] = { * Reads back response_len bytes from the SDVO device, and returns the status. */ static CARD8 -i830_sdvo_read_response(I830OutputPtr output, void *response, int response_len) +i830_sdvo_read_response(I830_xf86OutputPtr output, void *response, int response_len) { - int i; - CARD8 status; + I830OutputPrivatePtr intel_output = output->driver_private; + int i; + CARD8 status; /* Read the command response */ for (i = 0; i < response_len; i++) { @@ -225,8 +229,8 @@ i830_sdvo_read_response(I830OutputPtr output, void *response, int response_len) i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status); /* Write the SDVO command logging */ - xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO, - "%s: R: ", SDVO_NAME(SDVO_PRIV(output))); + xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_INFO, + "%s: R: ", SDVO_NAME(SDVO_PRIV(intel_output))); for (i = 0; i < response_len; i++) LogWrite(1, "%02X ", ((CARD8 *)response)[i]); for (; i < 8; i++) @@ -258,13 +262,13 @@ i830_sdvo_get_pixel_multiplier(DisplayModePtr pMode) * STOP. PROM access is terminated by accessing an internal register. */ static void -i830_sdvo_set_control_bus_switch(I830OutputPtr output, CARD8 target) +i830_sdvo_set_control_bus_switch(I830_xf86OutputPtr output, CARD8 target) { i830_sdvo_write_cmd(output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1); } static Bool -i830_sdvo_set_target_input(I830OutputPtr output, Bool target_0, Bool target_1) +i830_sdvo_set_target_input(I830_xf86OutputPtr output, Bool target_0, Bool target_1) { struct i830_sdvo_set_target_input_args targets = {0}; CARD8 status; @@ -290,7 +294,7 @@ i830_sdvo_set_target_input(I830OutputPtr output, Bool target_0, Bool target_1) * which should be checked against the docs. */ static Bool -i830_sdvo_get_trained_inputs(I830OutputPtr output, Bool *input_1, Bool *input_2) +i830_sdvo_get_trained_inputs(I830_xf86OutputPtr output, Bool *input_1, Bool *input_2) { struct i830_sdvo_get_trained_inputs_response response; CARD8 status; @@ -308,7 +312,7 @@ i830_sdvo_get_trained_inputs(I830OutputPtr output, Bool *input_1, Bool *input_2) } static Bool -i830_sdvo_get_active_outputs(I830OutputPtr output, +i830_sdvo_get_active_outputs(I830_xf86OutputPtr output, CARD16 *outputs) { CARD8 status; @@ -320,7 +324,7 @@ i830_sdvo_get_active_outputs(I830OutputPtr output, } static Bool -i830_sdvo_set_active_outputs(I830OutputPtr output, +i830_sdvo_set_active_outputs(I830_xf86OutputPtr output, CARD16 outputs) { CARD8 status; @@ -336,7 +340,7 @@ i830_sdvo_set_active_outputs(I830OutputPtr output, * Returns the pixel clock range limits of the current target input in kHz. */ static Bool -i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, int *clock_min, +i830_sdvo_get_input_pixel_clock_range(I830_xf86OutputPtr output, int *clock_min, int *clock_max) { struct i830_sdvo_pixel_clock_range clocks; @@ -357,7 +361,7 @@ i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, int *clock_min, } static Bool -i830_sdvo_set_target_output(I830OutputPtr output, CARD16 outputs) +i830_sdvo_set_target_output(I830_xf86OutputPtr output, CARD16 outputs) { CARD8 status; @@ -371,7 +375,7 @@ i830_sdvo_set_target_output(I830OutputPtr output, CARD16 outputs) /** Fetches either input or output timings to *dtd, depending on cmd. */ static Bool -i830_sdvo_get_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd) +i830_sdvo_get_timing(I830_xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd) { CARD8 status; @@ -391,20 +395,20 @@ i830_sdvo_get_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd) } static Bool -i830_sdvo_get_input_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd) +i830_sdvo_get_input_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd) { return i830_sdvo_get_timing(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd); } static Bool -i830_sdvo_get_output_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd) +i830_sdvo_get_output_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd) { return i830_sdvo_get_timing(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1, dtd); } /** Sets either input or output timings from *dtd, depending on cmd. */ static Bool -i830_sdvo_set_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd) +i830_sdvo_set_timing(I830_xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd) { CARD8 status; @@ -422,20 +426,20 @@ i830_sdvo_set_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd) } static Bool -i830_sdvo_set_input_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd) +i830_sdvo_set_input_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd) { return i830_sdvo_set_timing(output, SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd); } static Bool -i830_sdvo_set_output_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd) +i830_sdvo_set_output_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd) { return i830_sdvo_set_timing(output, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd); } #if 0 static Bool -i830_sdvo_create_preferred_input_timing(I830OutputPtr output, CARD16 clock, +i830_sdvo_create_preferred_input_timing(I830_xf86OutputPtr output, CARD16 clock, CARD16 width, CARD16 height) { struct i830_sdvo_priv *dev_priv = output->dev_priv; @@ -479,9 +483,10 @@ i830_sdvo_get_preferred_input_timing(I830OutputPtr output, /** Returns the SDVO_CLOCK_RATE_MULT_* for the current clock multiplier */ static int -i830_sdvo_get_clock_rate_mult(I830OutputPtr output) +i830_sdvo_get_clock_rate_mult(I830_xf86OutputPtr output) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; CARD8 response; CARD8 status; @@ -507,7 +512,7 @@ i830_sdvo_get_clock_rate_mult(I830OutputPtr output) * is actually turned on. */ static Bool -i830_sdvo_set_clock_rate_mult(I830OutputPtr output, CARD8 val) +i830_sdvo_set_clock_rate_mult(I830_xf86OutputPtr output, CARD8 val) { CARD8 status; @@ -520,11 +525,12 @@ i830_sdvo_set_clock_rate_mult(I830OutputPtr output, CARD8 val) } static void -i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr mode) +i830_sdvo_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr mode) { + ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); - struct i830_sdvo_priv *dev_priv = output->dev_priv; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; CARD16 width; CARD16 height; CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; @@ -621,15 +627,18 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, } static void -i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr mode) +i830_sdvo_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr mode) { + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + I830_xf86CrtcPtr crtc = output->crtc; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; I830Ptr pI830 = I830PTR(pScrn); - struct i830_sdvo_priv *dev_priv = output->dev_priv; Bool input1, input2; CARD32 dpll, sdvox; - int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B; - int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; + int dpll_reg = (intel_crtc->pipe == 0) ? DPLL_A : DPLL_B; + int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; int sdvo_pixel_multiply; int i; CARD8 status; @@ -645,7 +654,7 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, break; } sdvox |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE; - if (output->pipe == 1) + if (intel_crtc->pipe == 1) sdvox |= SDVO_PIPE_B_SELECT; dpll = INREG(dpll_reg); @@ -681,10 +690,12 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, } static void -i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +i830_sdvo_dpms(I830_xf86OutputPtr output, int mode) { + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; I830Ptr pI830 = I830PTR(pScrn); - struct i830_sdvo_priv *dev_priv = output->dev_priv; if (mode != DPMSModeOn) { i830_sdvo_set_active_outputs(output, 0); @@ -696,11 +707,13 @@ i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) } static void -i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_sdvo_save(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); - struct i830_sdvo_priv *dev_priv = output->dev_priv; - int o; + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + I830Ptr pI830 = I830PTR(pScrn); + int o; /* XXX: We should save the in/out mapping. */ @@ -731,11 +744,13 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output) } static void -i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_sdvo_restore(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); - struct i830_sdvo_priv *dev_priv = output->dev_priv; - int o; + ScrnInfoPtr pScrn = output->scrn; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + I830Ptr pI830 = I830PTR(pScrn); + int o; if (dev_priv->caps.sdvo_inputs_mask & 0x1) { i830_sdvo_set_target_input(output, TRUE, FALSE); @@ -764,10 +779,10 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output) } static int -i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_sdvo_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; if (pMode->Flags & V_DBLSCAN) return MODE_NO_DBLESCAN; @@ -782,7 +797,7 @@ i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, } static Bool -i830_sdvo_get_capabilities(I830OutputPtr output, struct i830_sdvo_caps *caps) +i830_sdvo_get_capabilities(I830_xf86OutputPtr output, struct i830_sdvo_caps *caps) { CARD8 status; @@ -836,8 +851,9 @@ i830_sdvo_ddc_i2c_put_byte(I2CDevPtr d, I2CByte c) static Bool i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout) { - I830OutputPtr output = b->DriverPrivate.ptr; - I2CBusPtr i2cbus = output->pI2CBus; + I830_xf86OutputPtr output = b->DriverPrivate.ptr; + I830OutputPrivatePtr intel_output = output->driver_private; + I2CBusPtr i2cbus = intel_output->pI2CBus; i830_sdvo_set_control_bus_switch(output, SDVO_CONTROL_BUS_DDC2); return i2cbus->I2CStart(i2cbus, timeout); @@ -847,8 +863,9 @@ i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout) static void i830_sdvo_ddc_i2c_stop(I2CDevPtr d) { - I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr; - I2CBusPtr i2cbus = output->pI2CBus, savebus; + I830_xf86OutputPtr output = d->DriverPrivate.ptr; + I830OutputPrivatePtr intel_output = output->driver_private; + I2CBusPtr i2cbus = intel_output->pI2CBus, savebus; savebus = d->pI2CBus; d->pI2CBus = i2cbus; @@ -883,18 +900,19 @@ i830_sdvo_ddc_i2c_address(I2CDevPtr d, I2CSlaveAddr addr) } static void -i830_sdvo_dump_cmd(I830OutputPtr output, int opcode) +i830_sdvo_dump_cmd(I830_xf86OutputPtr output, int opcode) { - CARD8 response[8]; + CARD8 response[8]; i830_sdvo_write_cmd(output, opcode, NULL, 0); i830_sdvo_read_response(output, response, 8); } static void -i830_sdvo_dump_device(I830OutputPtr output) +i830_sdvo_dump_device(I830_xf86OutputPtr output) { - struct i830_sdvo_priv *dev_priv = output->dev_priv; + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; ErrorF("Dump %s\n", dev_priv->d.DevName); i830_sdvo_dump_cmd(output, SDVO_CMD_GET_DEVICE_CAPS); @@ -926,9 +944,13 @@ i830_sdvo_dump(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); int i; - for (i = 0; i < pI830->num_outputs; i++) { - if (pI830->output[i].type == I830_OUTPUT_SDVO) - i830_sdvo_dump_device(&pI830->output[i]); + for (i = 0; i < pI830->num_outputs; i++) + { + I830_xf86OutputPtr output = pI830->xf86_output[i]; + I830OutputPrivatePtr intel_output = output->driver_private; + + if (intel_output->type == I830_OUTPUT_SDVO) + i830_sdvo_dump_device(output); } } @@ -942,7 +964,7 @@ i830_sdvo_dump(ScrnInfoPtr pScrn) * Takes 14ms on average on my i945G. */ static enum detect_status -i830_sdvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_sdvo_detect(I830_xf86OutputPtr output) { CARD8 response[2]; CARD8 status; @@ -959,25 +981,59 @@ i830_sdvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output) return OUTPUT_STATUS_DISCONNECTED; } +static void +i830_sdvo_destroy (I830_xf86OutputPtr output) +{ + I830OutputPrivatePtr intel_output = output->driver_private; + + if (intel_output) + { + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + + xf86DestroyI2CBusRec (intel_output->pDDCBus, FALSE, FALSE); + xf86DestroyI2CDevRec (&dev_priv->d, FALSE); + xf86DestroyI2CBusRec (dev_priv->d.pI2CBus, TRUE, TRUE); + xfree (intel_output); + } +} + +static const I830_xf86OutputFuncsRec i830_sdvo_output_funcs = { + .dpms = i830_sdvo_dpms, + .save = i830_sdvo_save, + .restore = i830_sdvo_restore, + .mode_valid = i830_sdvo_mode_valid, + .pre_set_mode = i830_sdvo_pre_set_mode, + .post_set_mode = i830_sdvo_post_set_mode, + .detect = i830_sdvo_detect, + .get_modes = i830_ddc_get_modes, + .destroy = i830_sdvo_destroy +}; + void i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) { - I830Ptr pI830 = I830PTR(pScrn); - I830OutputPtr output = &pI830->output[pI830->num_outputs]; - struct i830_sdvo_priv *dev_priv; - int i; - unsigned char ch[0x40]; - I2CBusPtr i2cbus = NULL, ddcbus; - - output->type = I830_OUTPUT_SDVO; - output->dpms = i830_sdvo_dpms; - output->save = i830_sdvo_save; - output->restore = i830_sdvo_restore; - output->mode_valid = i830_sdvo_mode_valid; - output->pre_set_mode = i830_sdvo_pre_set_mode; - output->post_set_mode = i830_sdvo_post_set_mode; - output->detect = i830_sdvo_detect; - output->get_modes = i830_ddc_get_modes; + I830_xf86OutputPtr output; + I830OutputPrivatePtr intel_output; + struct i830_sdvo_priv *dev_priv; + int i; + unsigned char ch[0x40]; + I2CBusPtr i2cbus = NULL, ddcbus; + + output = i830xf86OutputCreate (pScrn, &i830_sdvo_output_funcs, + "ADD2 PCIE card"); + if (!output) + return; + intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) + + sizeof (struct i830_sdvo_priv), 1); + if (!intel_output) + { + i830xf86OutputDestroy (output); + return; + } + output->driver_private = intel_output; + + dev_priv = (struct i830_sdvo_priv *) (intel_output + 1); + intel_output->type = I830_OUTPUT_SDVO; /* While it's the same bus, we just initialize a new copy to avoid trouble * with tracking refcounting ourselves, since the XFree86 DDX bits don't. @@ -988,12 +1044,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOC"); if (i2cbus == NULL) - return; - - /* Allocate the SDVO output private data */ - dev_priv = xcalloc(1, sizeof(struct i830_sdvo_priv)); - if (dev_priv == NULL) { - xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); + { + i830xf86OutputDestroy (output); return; } @@ -1008,12 +1060,12 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) dev_priv->d.DriverPrivate.ptr = output; dev_priv->output_device = output_device; - if (!xf86I2CDevInit(&dev_priv->d)) { + if (!xf86I2CDevInit(&dev_priv->d)) + { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to initialize %s I2C device\n", SDVO_NAME(dev_priv)); - xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); - xfree(dev_priv); + i830xf86OutputDestroy (output); return; } @@ -1023,10 +1075,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) * Start, extra attempts should be harmless. */ ddcbus = xf86CreateI2CBusRec(); - if (ddcbus == NULL) { - xf86DestroyI2CDevRec(&dev_priv->d, FALSE); - xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); - xfree(dev_priv); + if (ddcbus == NULL) + { + i830xf86OutputDestroy (output); return; } if (output_device == SDVOB) @@ -1039,25 +1090,22 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) ddcbus->I2CStart = i830_sdvo_ddc_i2c_start; ddcbus->I2CStop = i830_sdvo_ddc_i2c_stop; ddcbus->I2CAddress = i830_sdvo_ddc_i2c_address; - ddcbus->DriverPrivate.ptr = &pI830->output[pI830->num_outputs]; - if (!xf86I2CBusInit(ddcbus)) { - xf86DestroyI2CDevRec(&dev_priv->d, FALSE); - xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); - xfree(dev_priv); + ddcbus->DriverPrivate.ptr = output; + + if (!xf86I2CBusInit(ddcbus)) + { + i830xf86OutputDestroy (output); return; } - output->pI2CBus = i2cbus; - output->pDDCBus = ddcbus; - output->dev_priv = dev_priv; + intel_output->pI2CBus = i2cbus; + intel_output->pDDCBus = ddcbus; + intel_output->dev_priv = dev_priv; /* Read the regs to test if we can talk to the device */ for (i = 0; i < 0x40; i++) { if (!i830_sdvo_read_byte(output, i, &ch[i])) { - xf86DestroyI2CBusRec(output->pDDCBus, FALSE, FALSE); - xf86DestroyI2CDevRec(&dev_priv->d, FALSE); - xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE); - xfree(dev_priv); + i830xf86OutputDestroy (output); return; } } @@ -1074,7 +1122,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) unsigned char bytes[2]; memcpy (bytes, &dev_priv->caps.output_flags, 2); - xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR, + xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR, "%s: No active TMDS outputs (0x%02x%02x)\n", SDVO_NAME(dev_priv), bytes[0], bytes[1]); @@ -1100,6 +1148,4 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0 ? 'Y' : 'N', dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1 ? 'Y' : 'N'); - - pI830->num_outputs++; } diff --git a/src/i830_tv.c b/src/i830_tv.c index f938d5cc..ec78337a 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -143,11 +143,14 @@ const struct tv_mode { static int -i830_tv_detect_type(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_tv_detect_type(I830_xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830_xf86CrtcPtr crtc = output->crtc; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; CARD32 save_tv_ctl, save_tv_dac; CARD32 tv_ctl, tv_dac; - I830Ptr pI830 = I830PTR(pScrn); save_tv_ctl = INREG(TV_CTL); save_tv_dac = INREG(TV_DAC); @@ -156,7 +159,7 @@ i830_tv_detect_type(ScrnInfoPtr pScrn, I830OutputPtr output) * which is already enabled. */ tv_ctl = INREG(TV_CTL) & ~(TV_ENC_ENABLE | TV_ENC_PIPEB_SELECT); - if (output->pipe == 1) + if (intel_crtc->pipe == 1) tv_ctl |= TV_ENC_PIPEB_SELECT; OUTREG(TV_CTL, tv_ctl); @@ -200,8 +203,9 @@ i830_tv_detect_type(ScrnInfoPtr pScrn, I830OutputPtr output) } static void -i830_tv_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) +i830_tv_dpms(I830_xf86OutputPtr output, int mode) { + ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); switch(mode) { @@ -217,10 +221,12 @@ i830_tv_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode) } static void -i830_tv_save(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_tv_save(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); - struct i830_tv_priv *dev_priv = output->dev_priv; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_tv_priv *dev_priv = intel_output->dev_priv; dev_priv->save_TV_H_CTL_1 = INREG(TV_H_CTL_1); dev_priv->save_TV_H_CTL_2 = INREG(TV_H_CTL_2); @@ -241,10 +247,12 @@ i830_tv_save(ScrnInfoPtr pScrn, I830OutputPtr output) } static void -i830_tv_restore(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_tv_restore(I830_xf86OutputPtr output) { - I830Ptr pI830 = I830PTR(pScrn); - struct i830_tv_priv *dev_priv = output->dev_priv; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_tv_priv *dev_priv = intel_output->dev_priv; OUTREG(TV_H_CTL_1, dev_priv->save_TV_H_CTL_1); OUTREG(TV_H_CTL_2, dev_priv->save_TV_H_CTL_2); @@ -265,16 +273,15 @@ i830_tv_restore(ScrnInfoPtr pScrn, I830OutputPtr output) } static int -i830_tv_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_tv_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode) { return MODE_OK; } static void -i830_tv_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_tv_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode) { + ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); /* Disable the encoder while we set up the pipe. */ @@ -348,10 +355,12 @@ static const CARD32 v_chroma[43] = { }; static void -i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, - DisplayModePtr pMode) +i830_tv_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode) { + ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); + I830_xf86CrtcPtr crtc = output->crtc; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; enum tv_type type; const struct tv_mode *tv_mode; const struct tv_sc_mode *sc_mode; @@ -368,7 +377,7 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, tv_mode = &tv_modes[0]; sc_mode = &tv_sc_modes[TV_SC_NTSC_MJ]; - type = i830_tv_detect_type(pScrn, output); + type = i830_tv_detect_type(output); hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) | (tv_mode->htotal << TV_HTOTAL_SHIFT); @@ -408,7 +417,7 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, (tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT); tv_ctl = TV_ENC_ENABLE; - if (output->pipe == 1) + if (intel_crtc->pipe == 1) tv_ctl |= TV_ENC_PIPEB_SELECT; switch (type) { @@ -501,8 +510,9 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output, * we have a pipe programmed in order to probe the TV. */ static enum detect_status -i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_tv_detect(I830_xf86OutputPtr output) { + /* XXX need to load-detect */ return OUTPUT_STATUS_CONNECTED; } @@ -513,8 +523,9 @@ i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output) * how to probe modes off of TV connections. */ static DisplayModePtr -i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) +i830_tv_get_modes(I830_xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; I830Ptr pI830 = I830PTR(pScrn); DisplayModePtr new; char stmp[32]; @@ -553,36 +564,52 @@ i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output) return new; } +static void +i830_tv_destroy (I830_xf86OutputPtr output) +{ + if (output->driver_private) + xfree (output->driver_private); +} + +static const I830_xf86OutputFuncsRec i830_tv_output_funcs = { + .dpms = i830_tv_dpms, + .save = i830_tv_save, + .restore = i830_tv_restore, + .mode_valid = i830_tv_mode_valid, + .pre_set_mode = i830_tv_pre_set_mode, + .post_set_mode = i830_tv_post_set_mode, + .detect = i830_tv_detect, + .get_modes = i830_tv_get_modes, + .destroy = i830_tv_destroy +}; + void i830_tv_init(ScrnInfoPtr pScrn) { - I830Ptr pI830 = I830PTR(pScrn); - I830OutputPtr output = &pI830->output[pI830->num_outputs]; - struct i830_tv_priv *dev_priv; + I830Ptr pI830 = I830PTR(pScrn); + I830_xf86OutputPtr output; + I830OutputPrivatePtr intel_output; + struct i830_tv_priv *dev_priv; if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) return; - output->type = I830_OUTPUT_TVOUT; - output->pipe = 0; - output->enabled = FALSE; - output->load_detect_temp = FALSE; + output = i830xf86OutputCreate (pScrn, &i830_tv_output_funcs, + "TV"); - output->dpms = i830_tv_dpms; - output->save = i830_tv_save; - output->restore = i830_tv_restore; - output->mode_valid = i830_tv_mode_valid; - output->pre_set_mode = i830_tv_pre_set_mode; - output->post_set_mode = i830_tv_post_set_mode; - output->detect = i830_tv_detect; - output->get_modes = i830_tv_get_modes; - - dev_priv = xnfcalloc(1, sizeof(struct i830_tv_priv)); + if (!output) + return; - if (dev_priv == NULL) + intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) + + sizeof (struct i830_tv_priv), 1); + if (!intel_output) + { + i830xf86OutputDestroy (output); return; - - output->dev_priv = dev_priv; - ErrorF ("TV out is output %d\n", pI830->num_outputs); - pI830->num_outputs++; + } + dev_priv = (struct i830_tv_priv *) (intel_output + 1); + intel_output->type = I830_OUTPUT_SDVO; + intel_output->dev_priv = dev_priv; + + output->driver_private = intel_output; } diff --git a/src/i830_video.c b/src/i830_video.c index d84c1c97..5ce2b5d3 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -3595,7 +3595,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) } /* Check we have an LFP connected */ - if (i830PipeHasType (pScrn, pPriv->pipe, I830_OUTPUT_LVDS)) + if (i830PipeHasType (pI830->xf86_crtc[pPriv->pipe], I830_OUTPUT_LVDS)) { size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC); hsize = (size >> 16) & 0x7FF; diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c new file mode 100644 index 00000000..d0a3119e --- /dev/null +++ b/src/i830_xf86Crtc.c @@ -0,0 +1,126 @@ +/* + * $Id: $ + * + * Copyright © 2006 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stddef.h> +#include <string.h> +#include <stdio.h> + +#include "xf86.h" +#include "i830.h" +#include "i830_xf86Modes.h" +#include "i830_xf86Crtc.h" + +/* + * Crtc functions + */ +I830_xf86CrtcPtr +i830xf86CrtcCreate (ScrnInfoPtr scrn, + I830_xf86CrtcFuncsPtr funcs) +{ + I830_xf86CrtcPtr xf86_crtc; + + xf86_crtc = xcalloc (sizeof (I830_xf86CrtcRec), 1); + if (!xf86_crtc) + return NULL; + xf86_crtc->scrn = scrn; + xf86_crtc->funcs = funcs; +#ifdef RANDR_12_INTERFACE + xf86_crtc->randr_crtc = RRCrtcCreate (xf86_crtc); + if (!xf86_crtc->randr_crtc) + { + xfree (xf86_crtc); + return NULL; + } +#endif + return xf86_crtc; +} + +void +i830xf86CrtcDestroy (I830_xf86CrtcPtr xf86_crtc) +{ +#ifdef RANDR_12_INTERFACE + RRCrtcDestroy (xf86_crtc->randr_crtc); +#endif + xfree (xf86_crtc); +} + +/* + * Output functions + */ +I830_xf86OutputPtr +i830xf86OutputCreate (ScrnInfoPtr scrn, + const I830_xf86OutputFuncsRec *funcs, + const char *name) +{ + I830_xf86OutputPtr output; + I830Ptr pI830 = I830PTR(scrn); + int len = strlen (name); + + output = xcalloc (sizeof (I830_xf86OutputRec) + len + 1, 1); + if (!output) + return NULL; + output->scrn = scrn; + output->funcs = funcs; + output->name = (char *) (output + 1); + strcpy (output->name, name); +#ifdef RANDR_12_INTERFACE + output->randr_output = RROutputCreate (name, strlen (name), output); + if (!output->randr_output) + { + xfree (output); + return NULL; + } +#endif + pI830->xf86_output[pI830->num_outputs++] = output; + return output; +} + +void +i830xf86OutputDestroy (I830_xf86OutputPtr output) +{ + ScrnInfoPtr scrn = output->scrn; + I830Ptr pI830 = I830PTR(scrn); + int o; + + (*output->funcs->destroy) (output); +#ifdef RANDR_12_INTERFACE + RROutputDestroy (output->randr_output); +#endif + while (output->probed_modes) + xf86DeleteMode (&output->probed_modes, output->probed_modes); + for (o = 0; o < pI830->num_outputs; o++) + if (pI830->xf86_output[o] == output) + { + memmove (&pI830->xf86_output[o], + &pI830->xf86_output[o+1], + pI830->num_outputs - (o + 1)); + break; + } + xfree (output); +} + diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h new file mode 100644 index 00000000..6a525179 --- /dev/null +++ b/src/i830_xf86Crtc.h @@ -0,0 +1,296 @@ +/* + * Copyright © 2006 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#ifndef _I830_XF86CRTC_H_ +#define _I830_XF86CRTC_H_ + +#include <edid.h> +#include "i830_xf86Modes.h" + +typedef struct _I830_xf86Crtc I830_xf86CrtcRec, *I830_xf86CrtcPtr; + +typedef struct _I830_xf86CrtcFuncs { + /** + * Turns the crtc on/off, or sets intermediate power levels if available. + * + * Unsupported intermediate modes drop to the lower power setting. If the + * mode is DPMSModeOff, the crtc must be disabled, as the DPLL may be + * disabled afterwards. + */ + void + (*dpms)(I830_xf86CrtcPtr crtc, + int mode); + + /** + * Saves the crtc's state for restoration on VT switch. + */ + void + (*save)(I830_xf86CrtcPtr crtc); + + /** + * Restore's the crtc's state at VT switch. + */ + void + (*restore)(I830_xf86CrtcPtr crtc); + + /** + * Clean up driver-specific bits of the crtc + */ + void + (*destroy) (I830_xf86CrtcPtr crtc); +} I830_xf86CrtcFuncsRec, *I830_xf86CrtcFuncsPtr; + +struct _I830_xf86Crtc { + /** + * Associated ScrnInfo + */ + ScrnInfoPtr scrn; + + /** + * Active state of this CRTC + * + * Set when this CRTC is driving one or more outputs + */ + Bool enabled; + + /** + * Position on screen + * + * Locates this CRTC within the frame buffer + */ + int x, y; + + /** Track whether cursor is within CRTC range */ + Bool cursorInRange; + + /** Track state of cursor associated with this CRTC */ + Bool cursorShown; + + /** + * Active mode + * + * This reflects the mode as set in the CRTC currently + * It will be cleared when the VT is not active or + * during server startup + */ + DisplayModeRec curMode; + + /** + * Desired mode + * + * This is set to the requested mode, independent of + * whether the VT is active. In particular, it receives + * the startup configured mode and saves the active mode + * on VT switch. + */ + DisplayModeRec desiredMode; + + /** crtc-specific functions */ + const I830_xf86CrtcFuncsRec *funcs; + + /** + * Driver private + * + * Holds driver-private information + */ + void *driver_private; + +#ifdef RANDR_12_INTERFACE + /** + * RandR crtc + * + * When RandR 1.2 is available, this + * points at the associated crtc object + */ + RRCrtcPtr randr_crtc; +#else + void *randr_crtc; +#endif +}; + +typedef struct _I830_xf86Output I830_xf86OutputRec, *I830_xf86OutputPtr; + +typedef struct _I830_xf86OutputFuncs { + /** + * Turns the output on/off, or sets intermediate power levels if available. + * + * Unsupported intermediate modes drop to the lower power setting. If the + * mode is DPMSModeOff, the output must be disabled, as the DPLL may be + * disabled afterwards. + */ + void + (*dpms)(I830_xf86OutputPtr output, + int mode); + + /** + * Saves the output's state for restoration on VT switch. + */ + void + (*save)(I830_xf86OutputPtr output); + + /** + * Restore's the output's state at VT switch. + */ + void + (*restore)(I830_xf86OutputPtr output); + + /** + * Callback for testing a video mode for a given output. + * + * This function should only check for cases where a mode can't be supported + * on the pipe specifically, and not represent generic CRTC limitations. + * + * \return MODE_OK if the mode is valid, or another MODE_* otherwise. + */ + int + (*mode_valid)(I830_xf86OutputPtr output, + DisplayModePtr pMode); + + /** + * Callback for setting up a video mode before any crtc/dpll changes. + * + * \param pMode the mode that will be set, or NULL if the mode to be set is + * unknown (such as the restore path of VT switching). + */ + void + (*pre_set_mode)(I830_xf86OutputPtr output, + DisplayModePtr pMode); + + /** + * Callback for setting up a video mode after the DPLL update but before + * the plane is enabled. + */ + void + (*post_set_mode)(I830_xf86OutputPtr output, + DisplayModePtr pMode); + + /** + * Probe for a connected output, and return detect_status. + */ + enum detect_status + (*detect)(I830_xf86OutputPtr output); + + /** + * Query the device for the modes it provides. + * + * This function may also update MonInfo, mm_width, and mm_height. + * + * \return singly-linked list of modes or NULL if no modes found. + */ + DisplayModePtr + (*get_modes)(I830_xf86OutputPtr output); + + /** + * Clean up driver-specific bits of the output + */ + void + (*destroy) (I830_xf86OutputPtr output); +} I830_xf86OutputFuncsRec, *I830_xf86OutputFuncsPtr; + +struct _I830_xf86Output { + /** + * Associated ScrnInfo + */ + ScrnInfoPtr scrn; + /** + * Currently connected crtc (if any) + * + * If this output is not in use, this field will be NULL. + */ + I830_xf86CrtcPtr crtc; + /** + * List of available modes on this output. + * + * This should be the list from get_modes(), plus perhaps additional + * compatible modes added later. + */ + DisplayModePtr probed_modes; + + /** EDID monitor information */ + xf86MonPtr MonInfo; + + /** Physical size of the currently attached output device. */ + int mm_width, mm_height; + + /** Output name */ + char *name; + + /** output-specific functions */ + const I830_xf86OutputFuncsRec *funcs; + + /** driver private information */ + void *driver_private; + +#ifdef RANDR_12_INTERFACE + /** + * RandR 1.2 output structure. + * + * When RandR 1.2 is available, this points at the associated + * RandR output structure and is created when this output is created + */ + RROutputPtr randr_output; +#else + void *randr_output; +#endif +}; + +/* + * Crtc functions + */ +I830_xf86CrtcPtr +i830xf86CrtcCreate (ScrnInfoPtr scrn, + const I830_xf86CrtcFuncsPtr funcs); + +void +i830xf86CrtcDestroy (I830_xf86CrtcPtr xf86_crtc); + + +/** + * Allocate a crtc for the specified output + * + * Find a currently unused CRTC which is suitable for + * the specified output + */ + +I830_xf86CrtcPtr +i830xf86AllocCrtc (I830_xf86OutputPtr output); + +/** + * Free a crtc + * + * Mark the crtc as unused by any outputs + */ + +void +i830xf86FreeCrtc (I830_xf86CrtcPtr crtc); + +/* + * Output functions + */ +I830_xf86OutputPtr +i830xf86OutputCreate (ScrnInfoPtr scrn, + const I830_xf86OutputFuncsRec *funcs, + const char *name); + +void +i830xf86OutputDestroy (I830_xf86OutputPtr xf86_output); + +#endif /* _I830_XF86CRTC_H_ */ diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h index 5a26c0e4..30b926a7 100644 --- a/src/i830_xf86Modes.h +++ b/src/i830_xf86Modes.h @@ -25,6 +25,9 @@ * */ +#ifndef _I830_XF86MODES_H_ +#define _I830_XF86MODES_H_ + double i830xf86ModeHSync(DisplayModePtr mode); @@ -77,3 +80,5 @@ void PrintModeline(int scrnIndex,DisplayModePtr mode); extern DisplayModeRec I830xf86DefaultModes[]; + +#endif /* _I830_XF86MODES_H_ */ |