diff options
author | Keith Packard <keithp@neko.keithp.com> | 2006-11-26 16:44:17 -0800 |
---|---|---|
committer | Keith Packard <keithp@neko.keithp.com> | 2006-11-26 16:44:17 -0800 |
commit | 2529863a1ade782819d76be2d0dc16e89028c1e3 (patch) | |
tree | be9973bb1f83a633c998f137caa132b5f1a84bb8 | |
parent | 9aca4e207440119f4280b78199a221f85d50c511 (diff) |
Start output/crtc restructuring work. It compiles.
Outputs and Crtcs are now split between 'generic'
and 'driver specific' pieces in the hope that more code
will be able to migrate to the xf86-generic layer.
Right now, the code remains tangled together, significant
work remains to tease the pieces apart. First the code
needs to be made to actually work as-is though.
-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_ */ |