diff --git a/src/common.h b/src/common.h index 47d564d0..d061a7f2 100644 --- a/src/common.h +++ b/src/common.h @@ -96,7 +96,7 @@ extern void I830DPRINTF_stub(const char *filename, int line, const char *function, const char *fmt, ...); #ifdef _I830_H_ -#define PrintErrorState I830PrintErrorState +#define PrintErrorState i830_dump_error_state #define WaitRingFunc I830WaitLpRing #define RecPtr pI830 #else diff --git a/src/i810_reg.h b/src/i810_reg.h index d5250245..7c85cffd 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -398,8 +398,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define EIR 0x20B0 #define EMR 0x20B4 #define ESR 0x20B8 -#define IP_ERR 0x0001 -#define ERROR_RESERVED 0xffc6 +# define ERR_VERTEX_MAX (1 << 5) /* lpt/cst */ +# define ERR_PGTBL_ERROR (1 << 4) +# define ERR_DISPLAY_OVERLAY_UNDERRUN (1 << 3) +# define ERR_MAIN_MEMORY_REFRESH (1 << 2) +# define ERR_INSTRUCTION_ERROR (1 << 0) /* Interrupt Control Registers @@ -507,8 +510,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PGETBL_SIZE_256KB (1 << 1) #define PGETBL_SIZE_128KB (2 << 1) -/* Register containing pge table error results, p276 +/** @defgroup PGE_ERR + * @{ */ +/** Page table debug register for i845 */ #define PGE_ERR 0x2024 #define PGE_ERR_ADDR_MASK 0xFFFFF000 #define PGE_ERR_ID_MASK 0x00000038 @@ -528,8 +533,33 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PGE_ERR_ILLEGAL_TRX 0x00000004 #define PGE_ERR_LOCAL_MEM 0x00000005 #define PGE_ERR_TILED 0x00000006 +/** @} */ - +/** @defgroup PGTBL_ER + * @{ + */ +/** Page table debug register for i945 */ +# define PGTBL_ER 0x2024 +# define PGTBL_ERR_MT_TILING (1 << 27) +# define PGTBL_ERR_MT_GTT_PTE (1 << 26) +# define PGTBL_ERR_LC_TILING (1 << 25) +# define PGTBL_ERR_LC_GTT_PTE (1 << 24) +# define PGTBL_ERR_BIN_VERTEXDATA_GTT_PTE (1 << 23) +# define PGTBL_ERR_BIN_INSTRUCTION_GTT_PTE (1 << 22) +# define PGTBL_ERR_CS_VERTEXDATA_GTT_PTE (1 << 21) +# define PGTBL_ERR_CS_INSTRUCTION_GTT_PTE (1 << 20) +# define PGTBL_ERR_CS_GTT (1 << 19) +# define PGTBL_ERR_OVERLAY_TILING (1 << 18) +# define PGTBL_ERR_OVERLAY_GTT_PTE (1 << 16) +# define PGTBL_ERR_DISPC_TILING (1 << 14) +# define PGTBL_ERR_DISPC_GTT_PTE (1 << 12) +# define PGTBL_ERR_DISPB_TILING (1 << 10) +# define PGTBL_ERR_DISPB_GTT_PTE (1 << 8) +# define PGTBL_ERR_DISPA_TILING (1 << 6) +# define PGTBL_ERR_DISPA_GTT_PTE (1 << 4) +# define PGTBL_ERR_HOST_PTE_DATA (1 << 1) +# define PGTBL_ERR_HOST_GTT_PTE (1 << 0) +/** @} */ /* Page table entries loaded via mmio region, p323 */ @@ -888,6 +918,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /** @} */ #define DPLL_TEST 0x606c +# define DPLLB_TEST_SDVO_DIV_1 (0 << 22) +# define DPLLB_TEST_SDVO_DIV_2 (1 << 22) +# define DPLLB_TEST_SDVO_DIV_4 (2 << 22) +# define DPLLB_TEST_SDVO_DIV_MASK (3 << 22) +# define DPLLB_TEST_N_BYPASS (1 << 19) +# define DPLLB_TEST_M_BYPASS (1 << 18) +# define DPLLB_INPUT_BUFFER_ENABLE (1 << 16) +# define DPLLA_TEST_N_BYPASS (1 << 3) +# define DPLLA_TEST_M_BYPASS (1 << 2) +# define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) #define D_STATE 0x6104 #define DSPCLK_GATE_D 0x6200 diff --git a/src/i830.h b/src/i830.h index 56a57d6b..e484fce1 100644 --- a/src/i830.h +++ b/src/i830.h @@ -235,23 +235,11 @@ typedef struct _I830PipeRec { } I830PipeRec, *I830PipePtr; typedef struct _I830Rec { - /* Must be first */ - xf86CrtcConfigRec xf86_config; - unsigned char *MMIOBase; unsigned char *FbBase; int cpp; DisplayModePtr currentMode; - /* Mode saved during randr reprobe, which will need to be freed at the point - * of the next SwitchMode, when we lose this last reference to it. - */ - DisplayModePtr savedCurrentMode; - - Bool Clone; - int CloneRefresh; - int CloneHDisplay; - int CloneVDisplay; I830EntPtr entityPrivate; int init; @@ -511,8 +499,6 @@ typedef struct _I830Rec { extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis); extern void I830SetPIOAccess(I830Ptr pI830); extern void I830SetMMIOAccess(I830Ptr pI830); -extern void I830PrintErrorState(ScrnInfoPtr pScrn); -extern void I965PrintErrorState(ScrnInfoPtr pScrn); extern void I830Sync(ScrnInfoPtr pScrn); extern void I830InitHWCursor(ScrnInfoPtr pScrn); extern void I830SetPipeCursor (xf86CrtcPtr crtc, Bool force); @@ -529,8 +515,7 @@ extern Bool I830DGAInit(ScreenPtr pScreen); #ifdef I830_XV extern void I830InitVideo(ScreenPtr pScreen); -extern void I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode); -extern void I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode); +extern void i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on); #endif extern Bool I830AllocateRotatedBuffer(ScrnInfoPtr pScrn, const int flags); diff --git a/src/i830_accel.c b/src/i830_accel.c index 6ad62d1f..2260b71b 100644 --- a/src/i830_accel.c +++ b/src/i830_accel.c @@ -58,6 +58,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xaarop.h" #include "i830.h" #include "i810_reg.h" +#include "i830_debug.h" int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) @@ -99,7 +100,7 @@ I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) } else if (now - start > timeout_millis) { ErrorF("Error in I830WaitLpRing(), now is %d, start is %d\n", now, start); - I830PrintErrorState(pScrn); + i830_dump_error_state(pScrn); ErrorF("space: %d wanted %d\n", ring->space, n); #ifdef XF86DRI if (pI830->directRenderingEnabled) { diff --git a/src/i830_cursor.c b/src/i830_cursor.c index e9ca8f15..cb1585fb 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -86,10 +86,11 @@ I830SetPipeCursorBase (xf86CrtcPtr crtc) I830CrtcPrivatePtr intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE); I830MemRange *cursor_mem; - if (pipe >= pI830->xf86_config.num_crtc) + if (pipe >= xf86_config->num_crtc) FatalError("Bad pipe number for cursor base setting\n"); if (pI830->CursorIsARGB) @@ -180,17 +181,18 @@ I830SetPipeCursor (xf86CrtcPtr crtc, Bool force) void I830InitHWCursor(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); CARD32 temp; int i; DPRINTF(PFX, "I830InitHWCursor\n"); - for (i = 0; i < pI830->xf86_config.num_crtc; i++) - pI830->xf86_config.crtc[i]->cursorShown = FALSE; + for (i = 0; i < xf86_config->num_crtc; i++) + xf86_config->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->xf86_config.num_crtc; i++) + for (i = 0; i < xf86_config->num_crtc; i++) { int cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL; temp = INREG(cursor_control); @@ -204,7 +206,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn) temp |= CURSOR_MODE_64_4C_AX; /* Need to set control, then address. */ OUTREG(cursor_control, temp); - I830SetPipeCursorBase(pI830->xf86_config.crtc[i]); + I830SetPipeCursorBase(xf86_config->crtc[i]); } } else { temp = INREG(CURSOR_CONTROL); @@ -217,7 +219,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(pI830->xf86_config.crtc[0]); + I830SetPipeCursorBase(xf86_config->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); @@ -454,6 +456,7 @@ static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) static void I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); CARD32 temp; Bool inrange; @@ -490,9 +493,9 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) x -= hotspotx; y -= hotspoty; - for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++) + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[pipe]; + xf86CrtcPtr crtc = xf86_config->crtc[pipe]; DisplayModePtr mode = &crtc->curMode; int thisx = x - crtc->x; int thisy = y - crtc->y; @@ -542,6 +545,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) static void I830ShowCursor(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int pipe; @@ -556,26 +560,28 @@ I830ShowCursor(ScrnInfoPtr pScrn) pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start); pI830->cursorOn = TRUE; - for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++) - I830SetPipeCursor (pI830->xf86_config.crtc[pipe], TRUE); + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) + I830SetPipeCursor (xf86_config->crtc[pipe], TRUE); } static void I830HideCursor(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int pipe; DPRINTF(PFX, "I830HideCursor\n"); pI830->cursorOn = FALSE; - for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++) - I830SetPipeCursor (pI830->xf86_config.crtc[pipe], TRUE); + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) + I830SetPipeCursor (xf86_config->crtc[pipe], TRUE); } static void I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int pipe; @@ -587,9 +593,9 @@ I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) DPRINTF(PFX, "I830SetCursorColors\n"); - for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++) + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[pipe]; + xf86CrtcPtr crtc = xf86_config->crtc[pipe]; int pal0 = pipe == 0 ? CURSOR_A_PALETTE0 : CURSOR_B_PALETTE0; if (crtc->enabled) diff --git a/src/i830_debug.c b/src/i830_debug.c index 8c8b95ee..25245fb2 100644 --- a/src/i830_debug.c +++ b/src/i830_debug.c @@ -160,8 +160,8 @@ DEBUGSTRING(i830_debug_dpll) } if (IS_I945G(pI830) || IS_I945GM(pI830)) { sprintf(sdvoextra, ", SDVO mult %d", - (int)(val & SDVO_MULTIPLIER_MASK) >> - SDVO_MULTIPLIER_SHIFT_HIRES); + (int)((val & SDVO_MULTIPLIER_MASK) >> + SDVO_MULTIPLIER_SHIFT_HIRES) + 1); } else { sdvoextra[0] = '\0'; } @@ -172,6 +172,22 @@ DEBUGSTRING(i830_debug_dpll) fpextra, sdvoextra); } +DEBUGSTRING(i830_debug_dpll_test) +{ + char *dpllandiv = val & DPLLA_TEST_N_BYPASS ? ", DPLLA N bypassed" : ""; + char *dpllamdiv = val & DPLLA_TEST_M_BYPASS ? ", DPLLA M bypassed" : ""; + char *dpllainput = val & DPLLA_INPUT_BUFFER_ENABLE ? + "" : ", DPLLA input buffer disabled"; + char *dpllbndiv = val & DPLLB_TEST_N_BYPASS ? ", DPLLB N bypassed" : ""; + char *dpllbmdiv = val & DPLLB_TEST_M_BYPASS ? ", DPLLB M bypassed" : ""; + char *dpllbinput = val & DPLLB_INPUT_BUFFER_ENABLE ? + "" : ", DPLLB input buffer disabled"; + + return XNFprintf("%s%s%s%s%s%s", + dpllandiv, dpllamdiv, dpllainput, + dpllbndiv, dpllbmdiv, dpllbinput); +} + DEBUGSTRING(i830_debug_lvds) { char pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A'; @@ -180,6 +196,27 @@ DEBUGSTRING(i830_debug_lvds) return XNFprintf("%s, pipe %c", enable, pipe); } +DEBUGSTRING(i830_debug_sdvo) +{ + char *enable = val & SDVO_ENABLE ? "enabled" : "disabled"; + char pipe = val & SDVO_PIPE_B_SELECT ? 'B' : 'A'; + char *stall = val & SDVO_STALL_SELECT ? "enabled" : "disabled"; + char *detected = val & SDVO_DETECTED ? "" : "not "; + char *gang = val & SDVOC_GANG_MODE ? ", gang mode" : ""; + char sdvoextra[20]; + + if (IS_I915G(pI830) || IS_I915GM(pI830)) { + sprintf(sdvoextra, ", SDVO mult %d", + (int)((val & SDVO_PORT_MULTIPLY_MASK) >> + SDVO_PORT_MULTIPLY_SHIFT) + 1); + } else { + sdvoextra[0] = '\0'; + } + + return XNFprintf("%s, pipe %c, stall %s, %sdetected%s%s", + enable, pipe, stall, detected, sdvoextra, gang); +} + #define DEFINEREG(reg) \ { reg, #reg, NULL, 0 } #define DEFINEREG2(reg, func) \ @@ -194,14 +231,14 @@ static struct i830SnapshotRec { DEFINEREG(VCLK_DIVISOR_VGA0), DEFINEREG(VCLK_DIVISOR_VGA1), DEFINEREG(VCLK_POST_DIV), - DEFINEREG(DPLL_TEST), + DEFINEREG2(DPLL_TEST, i830_debug_dpll_test), DEFINEREG(D_STATE), DEFINEREG(DSPCLK_GATE_D), DEFINEREG(RENCLK_GATE_D1), DEFINEREG(RENCLK_GATE_D2), /* DEFINEREG(RAMCLK_GATE_D), CRL only */ - DEFINEREG(SDVOB), - DEFINEREG(SDVOC), + DEFINEREG2(SDVOB, i830_debug_sdvo), + DEFINEREG2(SDVOC, i830_debug_sdvo), /* DEFINEREG(UDIB_SVB_SHB_CODES), CRL only */ /* DEFINEREG(UDIB_SHA_BLANK_CODES), CRL only */ DEFINEREG(SDVOUDI), @@ -485,3 +522,211 @@ void i830DumpRegs (ScrnInfoPtr pScrn) } xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsEnd\n"); } + +/* Famous last words + */ +void +i830_dump_error_state(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", + (unsigned long)INREG(PGETBL_CTL), (unsigned long)INREG(PGE_ERR)); + + ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long)INREG(IPEIR), + (unsigned long)INREG(IPEHR)); + + ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", + (unsigned long)INREG(LP_RING + RING_TAIL), + (unsigned long)INREG(LP_RING + RING_HEAD) & HEAD_ADDR, + (unsigned long)INREG(LP_RING + RING_LEN), + (unsigned long)INREG(LP_RING + RING_START)); + + ErrorF("eir: %x esr: %x emr: %x\n", + INREG16(EIR), INREG16(ESR), INREG16(EMR)); + + ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM)); + + ErrorF("memmode: %lx instps: %lx\n", (unsigned long)INREG(MEMMODE), + (unsigned long)INREG(INST_PS)); + + ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n", + INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR)); +} + +void +i965_dump_error_state(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", + INREG(PGETBL_CTL), INREG(PGE_ERR)); + + ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR_I965), INREG(IPEHR_I965)); + + ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", + INREG(LP_RING + RING_TAIL), + INREG(LP_RING + RING_HEAD) & HEAD_ADDR, + INREG(LP_RING + RING_LEN), INREG(LP_RING + RING_START)); + + ErrorF("Err ID (eir): %x Err Status (esr): %x Err Mask (emr): %x\n", + (int)INREG(EIR), (int)INREG(ESR), (int)INREG(EMR)); + + ErrorF("instdone: %x instdone_1: %x\n", (int)INREG(INST_DONE_I965), + (int)INREG(INST_DONE_1)); + ErrorF("instpm: %x\n", (int)INREG(INST_PM)); + + ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS_I965)); + + ErrorF("HW Status mask (hwstam): %x\nIRQ enable (ier): %x " + "imr: %x iir: %x\n", + (int)INREG(HWSTAM), (int)INREG(IER), (int)INREG(IMR), + (int)INREG(IIR)); + + ErrorF("acthd: %lx dma_fadd_p: %lx\n", INREG(ACTHD), INREG(DMA_FADD_P)); + ErrorF("ecoskpd: %lx excc: %lx\n", INREG(ECOSKPD), INREG(EXCC)); + + ErrorF("cache_mode: %x/%x\n", (int)INREG(CACHE_MODE_0), + (int)INREG(CACHE_MODE_1)); + ErrorF("mi_arb_state: %x\n", (int)INREG(MI_ARB_STATE)); + + ErrorF("IA_VERTICES_COUNT_QW %x/%x\n", + (int)INREG(IA_VERTICES_COUNT_QW), + (int)INREG(IA_VERTICES_COUNT_QW+4)); + ErrorF("IA_PRIMITIVES_COUNT_QW %x/%x\n", + (int)INREG(IA_PRIMITIVES_COUNT_QW), + (int)INREG(IA_PRIMITIVES_COUNT_QW+4)); + + ErrorF("VS_INVOCATION_COUNT_QW %x/%x\n", + (int)INREG(VS_INVOCATION_COUNT_QW), + (int)INREG(VS_INVOCATION_COUNT_QW+4)); + + ErrorF("GS_INVOCATION_COUNT_QW %x/%x\n", + (int)INREG(GS_INVOCATION_COUNT_QW), + (int)INREG(GS_INVOCATION_COUNT_QW+4)); + ErrorF("GS_PRIMITIVES_COUNT_QW %x/%x\n", + (int)INREG(GS_PRIMITIVES_COUNT_QW), + (int)INREG(GS_PRIMITIVES_COUNT_QW+4)); + + ErrorF("CL_INVOCATION_COUNT_QW %x/%x\n", + (int)INREG(CL_INVOCATION_COUNT_QW), + (int)INREG(CL_INVOCATION_COUNT_QW+4)); + ErrorF("CL_PRIMITIVES_COUNT_QW %x/%x\n", + (int)INREG(CL_PRIMITIVES_COUNT_QW), + (int)INREG(CL_PRIMITIVES_COUNT_QW+4)); + + ErrorF("PS_INVOCATION_COUNT_QW %x/%x\n", + (int)INREG(PS_INVOCATION_COUNT_QW), + (int)INREG(PS_INVOCATION_COUNT_QW+4)); + ErrorF("PS_DEPTH_COUNT_QW %x/%x\n", + (int)INREG(PS_DEPTH_COUNT_QW), + (int)INREG(PS_DEPTH_COUNT_QW+4)); + + ErrorF("WIZ_CTL %x\n", (int)INREG(WIZ_CTL)); + ErrorF("TS_CTL %x TS_DEBUG_DATA %x\n", (int)INREG(TS_CTL), + (int)INREG(TS_DEBUG_DATA)); + ErrorF("TD_CTL %x / %x\n", (int)INREG(TD_CTL), (int)INREG(TD_CTL2)); +} + +/** + * Checks the hardware error state bits. + * + * \return TRUE if any errors were found. + */ +Bool +i830_check_error_state(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + int errors = 0; + unsigned long temp, head, tail; + + if (!I830IsPrimary(pScrn)) return TRUE; + + temp = INREG16(ESR); + if (temp != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "ESR is 0x%08lx%s%s%s%s\n", temp, + temp & ERR_VERTEX_MAX ? ", max vertices exceeded" : "", + temp & ERR_PGTBL_ERROR ? ", page table error" : "", + temp & ERR_DISPLAY_OVERLAY_UNDERRUN ? + ", display/overlay underrun" : "", + temp & ERR_INSTRUCTION_ERROR ? ", instruction error" : ""); + errors++; + } + /* Check first for page table errors */ + if (!IS_I9XX(pI830)) { + temp = INREG(PGE_ERR); + if (temp != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "PGTBL_ER is 0x%08lx\n", temp); + errors++; + } + } else { + temp = INREG(PGTBL_ER); + if (temp != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "PGTBL_ER is 0x%08lx" + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", temp, + temp & PGTBL_ERR_HOST_GTT_PTE ? ", host gtt pte" : "", + temp & PGTBL_ERR_HOST_PTE_DATA ? ", host pte data" : "", + temp & PGTBL_ERR_DISPA_GTT_PTE ? ", display A pte" : "", + temp & PGTBL_ERR_DISPA_TILING ? + ", display A tiling" : "", + temp & PGTBL_ERR_DISPB_GTT_PTE ? ", display B pte" : "", + temp & PGTBL_ERR_DISPB_TILING ? + ", display B tiling" : "", + temp & PGTBL_ERR_DISPC_GTT_PTE ? ", display C pte" : "", + temp & PGTBL_ERR_DISPC_TILING ? + ", display C tiling" : "", + temp & PGTBL_ERR_OVERLAY_GTT_PTE ? + ", overlay GTT PTE" : "", + temp & PGTBL_ERR_OVERLAY_TILING ? + ", overlay tiling" : "", + temp & PGTBL_ERR_CS_GTT ? ", CS GTT" : "", + temp & PGTBL_ERR_CS_INSTRUCTION_GTT_PTE ? + ", CS instruction GTT PTE" : "", + temp & PGTBL_ERR_CS_VERTEXDATA_GTT_PTE ? + ", CS vertex data GTT PTE" : "", + temp & PGTBL_ERR_BIN_INSTRUCTION_GTT_PTE ? + ", BIN instruction GTT PTE" : "", + temp & PGTBL_ERR_BIN_VERTEXDATA_GTT_PTE ? + ", BIN vertex data GTT PTE" : "", + temp & PGTBL_ERR_LC_GTT_PTE ? ", LC pte" : "", + temp & PGTBL_ERR_LC_TILING ? ", LC tiling" : "", + temp & PGTBL_ERR_MT_GTT_PTE ? ", MT pte" : "", + temp & PGTBL_ERR_MT_TILING ? ", MT tiling" : ""); + errors++; + } + } + temp = INREG(PGETBL_CTL); + if (!(temp & 1)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "PGTBL_CTL (0x%08lx) indicates GTT is disabled\n", temp); + errors++; + } + temp = INREG(LP_RING + RING_LEN); + if (temp & 1) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "PRB0_CTL (0x%08lx) indicates ring buffer enabled\n", temp); + errors++; + } + head = INREG(LP_RING + RING_HEAD); + tail = INREG(LP_RING + RING_TAIL); + if ((tail & I830_TAIL_MASK) != (head & I830_HEAD_MASK)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "PRB0_HEAD (0x%08lx) and PRB0_TAIL (0x%08lx) indicate " + "ring buffer not flushed\n", head, tail); + errors++; + } + +#if 0 + if (errors) { + if (IS_I965G(pI830)) + i965_dump_error_state(pScrn); + else + i830_dump_error_state(pScrn); + } +#endif + + return (errors != 0); +} diff --git a/src/i830_debug.h b/src/i830_debug.h index a365085c..2d2e72bf 100644 --- a/src/i830_debug.h +++ b/src/i830_debug.h @@ -28,3 +28,7 @@ void i830TakeRegSnapshot(ScrnInfoPtr pScrn); void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where); void i830DumpRegs (ScrnInfoPtr pScrn); +void i830_dump_error_state(ScrnInfoPtr pScrn); +void i965_dump_error_state(ScrnInfoPtr pScrn); +Bool i830_check_error_state(ScrnInfoPtr pScrn); + diff --git a/src/i830_display.c b/src/i830_display.c index 439c2986..f87aadca 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -225,12 +225,12 @@ Bool i830PipeHasType (xf86CrtcPtr crtc, int type) { ScrnInfoPtr pScrn = crtc->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; - for (i = 0; i < pI830->xf86_config.num_output; i++) + for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc) { I830OutputPrivatePtr intel_output = output->driver_private; @@ -373,14 +373,14 @@ DisplayModePtr i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode) { ScrnInfoPtr pScrn = crtc->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); DisplayModePtr pBest = NULL, pScan = NULL; int i; /* Assume that there's only one output connected to the given CRTC. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) + for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc && output->probed_modes != NULL) { pScan = output->probed_modes; @@ -469,15 +469,21 @@ Bool i830PipeInUse (xf86CrtcPtr crtc) { ScrnInfoPtr pScrn = crtc->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; - for (i = 0; i < pI830->xf86_config.num_output; i++) - if (pI830->xf86_config.output[i]->crtc == crtc) + for (i = 0; i < xf86_config->num_output; i++) + if (xf86_config->output[i]->crtc == crtc) return TRUE; return FALSE; } +/** + * Sets the power management mode of the pipe and plane. + * + * This code should probably grow support for turning the cursor off and back + * on appropriately at the same time as we're turning the pipe off/on. + */ static void i830_crtc_dpms(xf86CrtcPtr crtc, int mode) { @@ -487,6 +493,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) int pipe = intel_crtc->pipe; int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; CARD32 temp; @@ -499,27 +506,52 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) case DPMSModeSuspend: /* Enable the DPLL */ temp = INREG(dpll_reg); - OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE); - - /* Wait for the clocks to stabilize. */ - usleep(150); + if ((temp & DPLL_VCO_ENABLE) == 0) + { + OUTREG(dpll_reg, temp); + /* Wait for the clocks to stabilize. */ + usleep(150); + OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE); + /* Wait for the clocks to stabilize. */ + usleep(150); + OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE); + /* Wait for the clocks to stabilize. */ + usleep(150); + } /* Enable the pipe */ temp = INREG(pipeconf_reg); - OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE); + if ((temp & PIPEACONF_ENABLE) == 0) + OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE); /* Enable the plane */ temp = INREG(dspcntr_reg); - OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); + if ((temp & DISPLAY_PLANE_ENABLE) == 0) + { + OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + OUTREG(dspbase_reg, INREG(dspbase_reg)); + } + + /* Give the overlay scaler a chance to enable if it's on this pipe */ + i830_crtc_dpms_video(crtc, TRUE); break; case DPMSModeOff: - /* Disable display plane */ - temp = INREG(dspcntr_reg); - OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); + /* Give the overlay scaler a chance to disable if it's on this pipe */ + i830_crtc_dpms_video(crtc, FALSE); /* Disable the VGA plane that we never use */ OUTREG(VGACNTRL, VGA_DISP_DISABLE); + /* Disable display plane */ + temp = INREG(dspcntr_reg); + if ((temp & DISPLAY_PLANE_ENABLE) != 0) + { + OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); + /* Flush the plane changes */ + OUTREG(dspbase_reg, INREG(dspbase_reg)); + } + if (!IS_I9XX(pI830)) { /* Wait for vblank for the disable to take effect */ i830WaitForVblank(pScrn); @@ -527,13 +559,18 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Next, disable display pipes */ temp = INREG(pipeconf_reg); - OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE); + if ((temp & PIPEACONF_ENABLE) != 0) + OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE); /* Wait for vblank for the disable to take effect. */ i830WaitForVblank(pScrn); temp = INREG(dpll_reg); - OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE); + if ((temp & DPLL_VCO_ENABLE) != 0) + OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE); + + /* Wait for the clocks to turn off. */ + usleep(150); break; } } @@ -558,6 +595,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) { ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); I830CrtcPrivatePtr intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; @@ -565,6 +603,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; + int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; @@ -586,8 +625,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, /* Set up some convenient bools for what outputs are connected to * our pipe, used in DPLL setup. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; I830OutputPrivatePtr intel_output = output->driver_private; if (output->crtc != crtc) @@ -726,19 +765,49 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, else pipeconf &= ~PIPEACONF_DOUBLE_WIDE; } +#if 1 + dspcntr |= DISPLAY_PLANE_ENABLE; + pipeconf |= PIPEACONF_ENABLE; + dpll |= DPLL_VCO_ENABLE; +#endif + + if (is_lvds) + { + /* The LVDS pin pair needs to be on before the DPLLs are enabled. + * This is an exception to the general rule that mode_set doesn't turn + * things on. + */ + OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT); + } + + /* Disable the panel fitter if it was on our pipe */ + if (!IS_I830(pI830) && ((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe) + OUTREG(PFIT_CONTROL, 0); i830PrintPll("chosen", &clock); ErrorF("clock regs: 0x%08x, 0x%08x\n", (int)dpll, (int)fp); + if (dpll & DPLL_VCO_ENABLE) + { + OUTREG(fp_reg, fp); + OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE); + usleep(150); + } OUTREG(fp_reg, fp); OUTREG(dpll_reg, dpll); + /* Wait for the clocks to stabilize. */ + usleep(150); + if (IS_I965G(pI830)) { - /* Set the SDVO multiplier/divider to 1x for the sake of analog output. - * It will be updated by the SDVO code if SDVO had fixed up the clock - * for a higher multiplier. - */ - OUTREG(dpll_md_reg, 0); + int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock; + OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | + ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); + } else { + /* write it again -- the BIOS does, after all */ + OUTREG(dpll_reg, dpll); } + /* Wait for the clocks to stabilize. */ + usleep(150); OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) | ((adjusted_mode->CrtcHTotal - 1) << 16)); @@ -758,14 +827,16 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, */ OUTREG(dspsize_reg, ((mode->VDisplay - 1) << 16) | (mode->HDisplay - 1)); OUTREG(dsppos_reg, 0); - i830PipeSetBase(crtc, crtc->x, crtc->y); OUTREG(pipesrc_reg, ((mode->HDisplay - 1) << 16) | (mode->VDisplay - 1)); + i830PipeSetBase(crtc, crtc->x, crtc->y); OUTREG(pipeconf_reg, pipeconf); + i830WaitForVblank(pScrn); + OUTREG(dspcntr_reg, dspcntr); - - /* Disable the panel fitter if it was on our pipe */ - if (!IS_I830(pI830) && ((INREG(PFIT_CONTROL) >> 29) & 0x3) == pipe) - OUTREG(PFIT_CONTROL, 0); + /* Flush the plane changes */ + OUTREG(dspbase_reg, INREG(dspbase_reg)); + + i830WaitForVblank(pScrn); } /** @@ -781,7 +852,7 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, Bool plane_enable) { ScrnInfoPtr pScrn = crtc->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; Bool ret = FALSE; #ifdef XF86DRI @@ -809,8 +880,8 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, * adjust it according to limitations or output properties, and also * a chance to reject the mode entirely. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc != crtc) continue; @@ -827,8 +898,8 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, } /* Disable the outputs and CRTCs before setting the mode. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc != crtc) continue; @@ -843,16 +914,16 @@ i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, * on the DPLL. */ crtc->funcs->mode_set(crtc, pMode, adjusted_mode); - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc) output->funcs->mode_set(output, pMode, adjusted_mode); } /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ crtc->funcs->dpms(crtc, DPMSModeOn); - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc) output->funcs->dpms(output, DPMSModeOn); } @@ -890,14 +961,15 @@ done: void i830DisableUnusedFunctions(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int o, pipe; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n"); - for (o = 0; o < pI830->xf86_config.num_output; o++) + for (o = 0; o < xf86_config->num_output; o++) { - xf86OutputPtr output = pI830->xf86_config.output[o]; + xf86OutputPtr output = xf86_config->output[o]; if (!output->crtc) (*output->funcs->dpms)(output, DPMSModeOff); } @@ -906,9 +978,9 @@ i830DisableUnusedFunctions(ScrnInfoPtr pScrn) * 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->xf86_config.num_crtc; pipe++) + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[pipe]; + xf86CrtcPtr crtc = xf86_config->crtc[pipe]; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; int pipe = intel_crtc->pipe; int dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR; @@ -957,7 +1029,6 @@ Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - I830Ptr pI830 = I830PTR(pScrn); Bool ok = TRUE; xf86CrtcPtr crtc = config->output[config->compat_output]->crtc; @@ -976,29 +1047,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) (int)(pMode->HDisplay * pMode->VDisplay * pMode->VRefresh / 1000000)); - if (pI830->savedCurrentMode) { - /* We're done with the currentMode that the last randr probe had left - * behind, so free it. - */ - xfree(pI830->savedCurrentMode->name); - xfree(pI830->savedCurrentMode); - pI830->savedCurrentMode = NULL; - - /* If we might have enabled/disabled some pipes, we need to reset - * cloning mode support. - */ - if (pI830->xf86_config.num_crtc >= 2 && - pI830->xf86_config.crtc[0]->enabled && - pI830->xf86_config.crtc[1]->enabled) - pI830->Clone = TRUE; - else - pI830->Clone = FALSE; - - /* If HW cursor currently showing, reset cursor state */ - if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) - pI830->CursorInfoRec->ShowCursor(pScrn); - } - i830DisableUnusedFunctions(pScrn); i830DescribeOutputConfiguration(pScrn); @@ -1015,13 +1063,14 @@ done: void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int i; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n"); - for (i = 0; i < pI830->xf86_config.num_crtc; i++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->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; @@ -1051,8 +1100,8 @@ i830DescribeOutputConfiguration(ScrnInfoPtr pScrn) } } - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; xf86CrtcPtr crtc = output->crtc; I830CrtcPrivatePtr intel_crtc = crtc ? crtc->driver_private : NULL; @@ -1081,7 +1130,7 @@ xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output) { ScrnInfoPtr pScrn = output->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; xf86CrtcPtr crtc; int i; @@ -1089,14 +1138,14 @@ i830GetLoadDetectPipe(xf86OutputPtr output) if (output->crtc) return output->crtc; - for (i = 0; i < pI830->xf86_config.num_crtc; i++) - if (!i830PipeInUse(pI830->xf86_config.crtc[i])) + for (i = 0; i < xf86_config->num_crtc; i++) + if (!i830PipeInUse(xf86_config->crtc[i])) break; - if (i == pI830->xf86_config.num_crtc) + if (i == xf86_config->num_crtc) return NULL; - crtc = pI830->xf86_config.crtc[i]; + crtc = xf86_config->crtc[i]; output->crtc = crtc; intel_output->load_detect_temp = TRUE; diff --git a/src/i830_dri.c b/src/i830_dri.c index b3206336..c5d7a94e 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -426,15 +426,24 @@ I830CheckDRIAvailable(ScrnInfoPtr pScrn) /* Check that the GLX, DRI, and DRM modules have been loaded by testing * for known symbols in each module. */ - if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) + if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] %s failed: glx not loaded\n", __FUNCTION__); return FALSE; - if (!xf86LoaderCheckSymbol("DRIScreenInit")) + } + if (!xf86LoaderCheckSymbol("DRIScreenInit")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] %s failed: dri not loaded\n", __FUNCTION__); return FALSE; - if (!xf86LoaderCheckSymbol("drmAvailable")) + } + if (!xf86LoaderCheckSymbol("drmAvailable")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] %s failed: libdrm not loaded\n", __FUNCTION__); return FALSE; + } if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[dri] %s failed (libdri.a too old)\n", "I830CheckDRIAvailable"); + "[dri] %s failed (libdri.a too old)\n", __FUNCTION__); return FALSE; } @@ -1509,11 +1518,12 @@ Bool I830DRISetVBlankInterrupt (ScrnInfoPtr pScrn, Bool on) { I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); drmI830VBlankPipe pipe; if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) { if (on) { - if (pI830->xf86_config.num_crtc > 1 && pI830->xf86_config.crtc[1]->enabled) + if (xf86_config->num_crtc > 1 && xf86_config->crtc[1]->enabled) pipe.pipe = DRM_I830_VBLANK_PIPE_B; else pipe.pipe = DRM_I830_VBLANK_PIPE_A; diff --git a/src/i830_driver.c b/src/i830_driver.c index 75e5f228..79d4a00e 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -276,8 +276,6 @@ typedef enum { OPTION_DISPLAY_INFO, OPTION_DEVICE_PRESENCE, OPTION_MONITOR_LAYOUT, - OPTION_CLONE, - OPTION_CLONE_REFRESH, OPTION_CHECKDEVICES, OPTION_FIXEDPIPE, OPTION_ROTATE, @@ -299,8 +297,6 @@ static OptionInfoRec I830Options[] = { {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, {OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE}, {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0}, FALSE}, - {OPTION_CLONE, "Clone", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_CLONE_REFRESH,"CloneRefresh",OPTV_INTEGER, {0}, FALSE}, {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN, {0}, FALSE}, {OPTION_FIXEDPIPE, "FixedPipe", OPTV_ANYSTR, {0}, FALSE}, {OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE}, @@ -320,8 +316,6 @@ const char *i830_output_type_names[] = { "TVOUT", }; -static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, - int PowerManagementMode, int flags); static void i830AdjustFrame(int scrnIndex, int x, int y, int flags); static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool I830SaveScreen(ScreenPtr pScreen, int unblack); @@ -586,6 +580,7 @@ static void I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors, VisualPtr pVisual) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830; int i,j, index; unsigned char r, g, b; @@ -597,9 +592,9 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors); pI830 = I830PTR(pScrn); - for(p=0; p < pI830->xf86_config.num_crtc; p++) + for(p=0; p < xf86_config->num_crtc; p++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[p]; + xf86CrtcPtr crtc = xf86_config->crtc[p]; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; if (p == 0) { @@ -904,6 +899,7 @@ I830ReduceMMSize(ScrnInfoPtr pScrn, unsigned long newSize, static Bool I830PreInit(ScrnInfoPtr pScrn, int flags) { + xf86CrtcConfigPtr xf86_config; vgaHWPtr hwp; I830Ptr pI830; MessageType from = X_PROBED; @@ -918,6 +914,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) Bool enable; const char *chipname; int num_pipe; + int max_width; #ifdef XF86DRI unsigned long savedMMSize; #endif @@ -1186,6 +1183,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n", (unsigned long)pI830->MMIOAddr); + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit (pScrn); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + if (IS_I965G(pI830)) + max_width = 16384; + else + max_width = 8192 / pI830->cpp; + xf86CrtcSetSizeRange (pScrn, 320, 200, max_width, 2048); + /* Some of the probing needs MMIO access, so map it here. */ I830MapMMIO(pScrn); @@ -1388,31 +1395,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) i830_crtc_init(pScrn, i); } - if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) { - if (num_pipe == 1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Can't enable Clone Mode because this is a single pipe device\n"); - PreInitCleanup(pScrn); - return FALSE; - } - if (pI830->entityPrivate) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Can't enable Clone Mode because second head is configured\n"); - PreInitCleanup(pScrn); - return FALSE; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Clone Mode\n"); - pI830->Clone = TRUE; - } - SaveHWState(pScrn); /* Do an initial detection of the outputs while none are configured on yet. * This will give us some likely legitimate response for later if both * pipes are already allocated and we're asked to do a detect. */ - for (i = 0; i < pI830->xf86_config.num_output; i++) + for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + xf86OutputPtr output = xf86_config->output[i]; output->status = (*output->funcs->detect) (output); } @@ -1854,6 +1844,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) if (pScrn->displayWidth * pI830->cpp > 8192) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support frame buffer stride > 8K > DRI.\n"); pI830->disableTiling = TRUE; + pI830->directRenderingDisabled = TRUE; } if (pScrn->virtualY > 2048) { @@ -1969,61 +1960,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) return TRUE; } -/* - * As the name says. Check that the initial state is reasonable. - * If any unrecoverable problems are found, bail out here. - */ -static Bool -CheckInheritedState(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - int errors = 0, fatal = 0; - unsigned long temp, head, tail; - - if (!I830IsPrimary(pScrn)) return TRUE; - - /* Check first for page table errors */ - temp = INREG(PGE_ERR); - if (temp != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08lx\n", temp); - errors++; - } - temp = INREG(PGETBL_CTL); - if (!(temp & 1)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "PGTBL_CTL (0x%08lx) indicates GTT is disabled\n", temp); - errors++; - } - temp = INREG(LP_RING + RING_LEN); - if (temp & 1) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "PRB0_CTL (0x%08lx) indicates ring buffer enabled\n", temp); - errors++; - } - head = INREG(LP_RING + RING_HEAD); - tail = INREG(LP_RING + RING_TAIL); - if ((tail & I830_TAIL_MASK) != (head & I830_HEAD_MASK)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "PRB0_HEAD (0x%08lx) and PRB0_TAIL (0x%08lx) indicate " - "ring buffer not flushed\n", head, tail); - errors++; - } - -#if 0 - if (errors) { - if (IS_I965G(pI830)) - I965PrintErrorState(pScrn); - else - I830PrintErrorState(pScrn); - } -#endif - - if (fatal) - FatalError("CheckInheritedState: can't recover from the above\n"); - - return (errors != 0); -} - /* * Reset registers that it doesn't make sense to save/restore to a sane state. * This is basically the ring buffer and fence registers. Restoring these @@ -2175,6 +2111,7 @@ SetHWOperatingState(ScrnInfoPtr pScrn) static Bool SaveHWState(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); vgaRegPtr vgaReg = &hwp->SavedReg; @@ -2204,7 +2141,7 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2)); } - if(pI830->xf86_config.num_crtc == 2) { + if(xf86_config->num_crtc == 2) { pI830->savePIPEBCONF = INREG(PIPEBCONF); pI830->savePIPEBSRC = INREG(PIPEBSRC); pI830->saveDSPBCNTR = INREG(DSPBCNTR); @@ -2248,8 +2185,8 @@ SaveHWState(ScrnInfoPtr pScrn) pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL); - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; if (output->funcs->save) (*output->funcs->save) (output); } @@ -2263,10 +2200,10 @@ SaveHWState(ScrnInfoPtr pScrn) static Bool RestoreHWState(ScrnInfoPtr pScrn) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); vgaRegPtr vgaReg = &hwp->SavedReg; - CARD32 temp; int i; DPRINTF(PFX, "RestoreHWState\n"); @@ -2274,40 +2211,36 @@ RestoreHWState(ScrnInfoPtr pScrn) #ifdef XF86DRI I830DRISetVBlankInterrupt (pScrn, FALSE); #endif - /* Disable outputs */ - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; output->funcs->dpms(output, DPMSModeOff); } - - /* Disable display planes */ - temp = INREG(DSPACNTR); - OUTREG(DSPACNTR, temp & ~DISPLAY_PLANE_ENABLE); - temp = INREG(DSPBCNTR); - OUTREG(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); - - /* Next, disable display pipes */ - temp = INREG(PIPEACONF); - OUTREG(PIPEACONF, temp & ~PIPEACONF_ENABLE); - temp = INREG(PIPEBCONF); - OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE); - + i830WaitForVblank(pScrn); + + /* Disable pipes */ + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + crtc->funcs->dpms(crtc, DPMSModeOff); + } i830WaitForVblank(pScrn); + if (!IS_I830(pI830) && !IS_845G(pI830)) + OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); + + if (pI830->saveDPLL_A & DPLL_VCO_ENABLE) + { + OUTREG(DPLL_A, pI830->saveDPLL_A & ~DPLL_VCO_ENABLE); + usleep(150); + } OUTREG(FPA0, pI830->saveFPA0); OUTREG(FPA1, pI830->saveFPA1); OUTREG(DPLL_A, pI830->saveDPLL_A); + usleep(150); if (IS_I965G(pI830)) OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD); - if(pI830->xf86_config.num_crtc == 2) { - OUTREG(FPB0, pI830->saveFPB0); - OUTREG(FPB1, pI830->saveFPB1); - OUTREG(DPLL_B, pI830->saveDPLL_B); - if (IS_I965G(pI830)) - OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD); - } - /* Wait for clocks to stabilize */ + else + OUTREG(DPLL_A, pI830->saveDPLL_A); usleep(150); OUTREG(HTOTAL_A, pI830->saveHTOTAL_A); @@ -2316,16 +2249,37 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(VTOTAL_A, pI830->saveVTOTAL_A); OUTREG(VBLANK_A, pI830->saveVBLANK_A); OUTREG(VSYNC_A, pI830->saveVSYNC_A); + OUTREG(DSPASTRIDE, pI830->saveDSPASTRIDE); OUTREG(DSPASIZE, pI830->saveDSPASIZE); OUTREG(DSPAPOS, pI830->saveDSPAPOS); - OUTREG(DSPABASE, pI830->saveDSPABASE); OUTREG(PIPEASRC, pI830->savePIPEASRC); - for(i = 0; i < 256; i++) { - OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]); - } - - if(pI830->xf86_config.num_crtc == 2) { + OUTREG(DSPABASE, pI830->saveDSPABASE); + if (IS_I965G(pI830)) + OUTREG(DSPASURF, pI830->saveDSPASURF); + OUTREG(PIPEACONF, pI830->savePIPEACONF); + i830WaitForVblank(pScrn); + OUTREG(DSPACNTR, pI830->saveDSPACNTR); + OUTREG(DSPABASE, INREG(DSPABASE)); + i830WaitForVblank(pScrn); + + if(xf86_config->num_crtc == 2) + { + if (pI830->saveDPLL_B & DPLL_VCO_ENABLE) + { + OUTREG(DPLL_B, pI830->saveDPLL_B & ~DPLL_VCO_ENABLE); + usleep(150); + } + OUTREG(FPB0, pI830->saveFPB0); + OUTREG(FPB1, pI830->saveFPB1); + OUTREG(DPLL_B, pI830->saveDPLL_B); + usleep(150); + if (IS_I965G(pI830)) + OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD); + else + OUTREG(DPLL_B, pI830->saveDPLL_B); + usleep(150); + OUTREG(HTOTAL_B, pI830->saveHTOTAL_B); OUTREG(HBLANK_B, pI830->saveHBLANK_B); OUTREG(HSYNC_B, pI830->saveHSYNC_B); @@ -2335,50 +2289,49 @@ RestoreHWState(ScrnInfoPtr pScrn) OUTREG(DSPBSTRIDE, pI830->saveDSPBSTRIDE); OUTREG(DSPBSIZE, pI830->saveDSPBSIZE); OUTREG(DSPBPOS, pI830->saveDSPBPOS); - OUTREG(DSPBBASE, pI830->saveDSPBBASE); OUTREG(PIPEBSRC, pI830->savePIPEBSRC); - for(i= 0; i < 256; i++) { - OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]); - } + OUTREG(DSPBBASE, pI830->saveDSPBBASE); + if (IS_I965G(pI830)) + OUTREG(DSPBSURF, pI830->saveDSPBSURF); + OUTREG(PIPEBCONF, pI830->savePIPEBCONF); + i830WaitForVblank(pScrn); + OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); + OUTREG(DSPBBASE, INREG(DSPBBASE)); + i830WaitForVblank(pScrn); } - if (!IS_I830(pI830) && !IS_845G(pI830)) - OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL); - - if (IS_I965G(pI830)) { - OUTREG(DSPASURF, pI830->saveDSPASURF); - OUTREG(DSPBSURF, pI830->saveDSPBSURF); + /* Restore outputs */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + if (output->funcs->restore) + output->funcs->restore(output); } + + OUTREG(VGACNTRL, pI830->saveVGACNTRL); OUTREG(VCLK_DIVISOR_VGA0, pI830->saveVCLK_DIVISOR_VGA0); OUTREG(VCLK_DIVISOR_VGA1, pI830->saveVCLK_DIVISOR_VGA1); OUTREG(VCLK_POST_DIV, pI830->saveVCLK_POST_DIV); - OUTREG(PIPEACONF, pI830->savePIPEACONF); - OUTREG(PIPEBCONF, pI830->savePIPEBCONF); - if (IS_I855(pI830)) - usleep(10); - OUTREG(VGACNTRL, pI830->saveVGACNTRL); - OUTREG(DSPACNTR, pI830->saveDSPACNTR); - OUTREG(DSPBCNTR, pI830->saveDSPBCNTR); - - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; - (*output->funcs->restore) (output); + for(i = 0; i < 256; i++) { + OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]); + } + + if(xf86_config->num_crtc == 2) { + for(i= 0; i < 256; i++) { + OUTREG(PALETTE_B + (i << 2), pI830->savePaletteB[i]); + } } for(i = 0; i < 7; i++) { - OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); - OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); + OUTREG(SWF0 + (i << 2), pI830->saveSWF[i]); + OUTREG(SWF00 + (i << 2), pI830->saveSWF[i+7]); } OUTREG(SWF30, pI830->saveSWF[14]); OUTREG(SWF31, pI830->saveSWF[15]); OUTREG(SWF32, pI830->saveSWF[16]); - for (i = 0; i < 2; i++) - i830WaitForVblank(pScrn); - vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); vgaHWLock(hwp); @@ -2398,103 +2351,6 @@ InitRegisterRec(ScrnInfoPtr pScrn) i830Reg->Fence[i] = 0; } -/* Famous last words - */ -void -I830PrintErrorState(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - - ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", - (unsigned long)INREG(PGETBL_CTL), (unsigned long)INREG(PGE_ERR)); - - ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long)INREG(IPEIR), - (unsigned long)INREG(IPEHR)); - - ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", - (unsigned long)INREG(LP_RING + RING_TAIL), - (unsigned long)INREG(LP_RING + RING_HEAD) & HEAD_ADDR, - (unsigned long)INREG(LP_RING + RING_LEN), - (unsigned long)INREG(LP_RING + RING_START)); - - ErrorF("eir: %x esr: %x emr: %x\n", - INREG16(EIR), INREG16(ESR), INREG16(EMR)); - - ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM)); - - ErrorF("memmode: %lx instps: %lx\n", (unsigned long)INREG(MEMMODE), - (unsigned long)INREG(INST_PS)); - - ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n", - INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR)); -} - -void -I965PrintErrorState(ScrnInfoPtr pScrn) -{ - I830Ptr pI830 = I830PTR(pScrn); - - ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", - INREG(PGETBL_CTL), INREG(PGE_ERR)); - - ErrorF("ipeir: %lx iphdr: %lx\n", INREG(IPEIR_I965), INREG(IPEHR_I965)); - - ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", - INREG(LP_RING + RING_TAIL), - INREG(LP_RING + RING_HEAD) & HEAD_ADDR, - INREG(LP_RING + RING_LEN), INREG(LP_RING + RING_START)); - - ErrorF("Err ID (eir): %x Err Status (esr): %x Err Mask (emr): %x\n", - (int)INREG(EIR), (int)INREG(ESR), (int)INREG(EMR)); - - ErrorF("instdone: %x instdone_1: %x\n", (int)INREG(INST_DONE_I965), - (int)INREG(INST_DONE_1)); - ErrorF("instpm: %x\n", (int)INREG(INST_PM)); - - ErrorF("memmode: %lx instps: %lx\n", INREG(MEMMODE), INREG(INST_PS_I965)); - - ErrorF("HW Status mask (hwstam): %x\nIRQ enable (ier): %x imr: %x iir: %x\n", - (int)INREG(HWSTAM), (int)INREG(IER), (int)INREG(IMR), - (int)INREG(IIR)); - - ErrorF("acthd: %lx dma_fadd_p: %lx\n", INREG(ACTHD), INREG(DMA_FADD_P)); - ErrorF("ecoskpd: %lx excc: %lx\n", INREG(ECOSKPD), INREG(EXCC)); - - ErrorF("cache_mode: %x/%x\n", (int)INREG(CACHE_MODE_0), - (int)INREG(CACHE_MODE_1)); - ErrorF("mi_arb_state: %x\n", (int)INREG(MI_ARB_STATE)); - - ErrorF("IA_VERTICES_COUNT_QW %x/%x\n", (int)INREG(IA_VERTICES_COUNT_QW), - (int)INREG(IA_VERTICES_COUNT_QW+4)); - ErrorF("IA_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(IA_PRIMITIVES_COUNT_QW), - (int)INREG(IA_PRIMITIVES_COUNT_QW+4)); - - ErrorF("VS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(VS_INVOCATION_COUNT_QW), - (int)INREG(VS_INVOCATION_COUNT_QW+4)); - - ErrorF("GS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(GS_INVOCATION_COUNT_QW), - (int)INREG(GS_INVOCATION_COUNT_QW+4)); - ErrorF("GS_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(GS_PRIMITIVES_COUNT_QW), - (int)INREG(GS_PRIMITIVES_COUNT_QW+4)); - - ErrorF("CL_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(CL_INVOCATION_COUNT_QW), - (int)INREG(CL_INVOCATION_COUNT_QW+4)); - ErrorF("CL_PRIMITIVES_COUNT_QW %x/%x\n", (int)INREG(CL_PRIMITIVES_COUNT_QW), - (int)INREG(CL_PRIMITIVES_COUNT_QW+4)); - - ErrorF("PS_INVOCATION_COUNT_QW %x/%x\n", (int)INREG(PS_INVOCATION_COUNT_QW), - (int)INREG(PS_INVOCATION_COUNT_QW+4)); - ErrorF("PS_DEPTH_COUNT_QW %x/%x\n", (int)INREG(PS_DEPTH_COUNT_QW), - (int)INREG(PS_DEPTH_COUNT_QW+4)); - - ErrorF("WIZ_CTL %x\n", (int)INREG(WIZ_CTL)); - ErrorF("TS_CTL %x TS_DEBUG_DATA %x\n", (int)INREG(TS_CTL), - (int)INREG(TS_DEBUG_DATA)); - ErrorF("TD_CTL %x / %x\n", (int)INREG(TD_CTL), (int)INREG(TD_CTL2)); - - -} - static void I830PointerMoved(int index, int x, int y) { @@ -3051,7 +2907,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) return FALSE; } - xf86DPMSInit(pScreen, I830DisplayPowerManagementSet, 0); + xf86DPMSInit(pScreen, xf86DPMSSet, 0); #ifdef I830_XV /* Init video */ @@ -3241,17 +3097,6 @@ I830LeaveVT(int scrnIndex, int flags) i830SetHotkeyControl(pScrn, HOTKEY_BIOS_SWITCH); -#ifdef I830_XV - /* Give the video overlay code a chance to shutdown. */ - I830VideoSwitchModeBefore(pScrn, NULL); -#endif - - if (pI830->Clone) { - /* Ensure we don't try and setup modes on a clone head */ - pI830->CloneHDisplay = 0; - pI830->CloneVDisplay = 0; - } - if (!I830IsPrimary(pScrn)) { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); if (!pI8301->GttBound) { @@ -3298,6 +3143,7 @@ static Bool I830EnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); int i; @@ -3324,14 +3170,17 @@ I830EnterVT(int scrnIndex, int flags) if (!I830BindAGPMemory(pScrn)) return FALSE; - CheckInheritedState(pScrn); + if (i830_check_error_state(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Existing errors found in hardware state\n"); + } ResetState(pScrn, FALSE); SetHWOperatingState(pScrn); - for (i = 0; i < pI830->xf86_config.num_crtc; i++) + for (i = 0; i < xf86_config->num_crtc; i++) { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; + xf86CrtcPtr crtc = xf86_config->crtc[i]; /* Mark that we'll need to re-set the mode for sure */ memset(&crtc->curMode, 0, sizeof(crtc->curMode)); @@ -3352,10 +3201,6 @@ I830EnterVT(int scrnIndex, int flags) #ifdef XF86DRI I830DRISetVBlankInterrupt (pScrn, TRUE); #endif - -#ifdef I830_XV - I830VideoSwitchModeAfter(pScrn, pScrn->currentMode); -#endif ResetState(pScrn, TRUE); SetHWOperatingState(pScrn); @@ -3429,11 +3274,6 @@ I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) DPRINTF(PFX, "I830SwitchMode: mode == %p\n", mode); -#ifdef I830_XV - /* Give the video overlay code a chance to see the new mode. */ - I830VideoSwitchModeBefore(pScrn, mode); -#endif - /* Sync the engine before mode switch */ i830WaitSync(pScrn); @@ -3466,18 +3306,8 @@ I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) xf86DrvMsg(scrnIndex, X_INFO, "Failed to restore previous mode (SwitchMode)\n"); } - -#ifdef I830_XV - /* Give the video overlay code a chance to see the new mode. */ - I830VideoSwitchModeAfter(pScrn, pI830->currentMode); -#endif } else { pI830->currentMode = mode; - -#ifdef I830_XV - /* Give the video overlay code a chance to see the new mode. */ - I830VideoSwitchModeAfter(pScrn, mode); -#endif } return ret; @@ -3487,6 +3317,7 @@ static Bool I830SaveScreen(ScreenPtr pScreen, int mode) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); Bool on = xf86IsUnblank(mode); CARD32 temp, ctrl, base, surf; @@ -3495,7 +3326,7 @@ I830SaveScreen(ScreenPtr pScreen, int mode) DPRINTF(PFX, "I830SaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on)); if (pScrn->vtSema) { - for (i = 0; i < pI830->xf86_config.num_crtc; i++) { + for (i = 0; i < xf86_config->num_crtc; i++) { if (i == 0) { ctrl = DSPACNTR; base = DSPABASE; @@ -3505,7 +3336,7 @@ I830SaveScreen(ScreenPtr pScreen, int mode) base = DSPBADDR; surf = DSPBSURF; } - if (pI830->xf86_config.crtc[i]->enabled) { + if (xf86_config->crtc[i]->enabled) { temp = INREG(ctrl); if (on) temp |= DISPLAY_PLANE_ENABLE; @@ -3533,55 +3364,6 @@ I830SaveScreen(ScreenPtr pScreen, int mode) return TRUE; } -/* Use the VBE version when available. */ -static void -I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, - int flags) -{ - I830Ptr pI830 = I830PTR(pScrn); - int i; - CARD32 temp, ctrl, base; - - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; - - (*output->funcs->dpms) (output, PowerManagementMode); - } - - for (i = 0; i < pI830->xf86_config.num_crtc; i++) - { - xf86CrtcPtr crtc = pI830->xf86_config.crtc[i]; - - if (i == 0) { - ctrl = DSPACNTR; - base = DSPABASE; - } else { - ctrl = DSPBCNTR; - base = DSPBADDR; - } - /* XXX pipe disable too? */ - if (crtc->enabled) { - temp = INREG(ctrl); - if (PowerManagementMode == DPMSModeOn) - temp |= DISPLAY_PLANE_ENABLE; - else - temp &= ~DISPLAY_PLANE_ENABLE; - OUTREG(ctrl, temp); - /* Flush changes */ - temp = INREG(base); - OUTREG(base, temp); - } - } - - if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) { - if (PowerManagementMode == DPMSModeOn) - pI830->CursorInfoRec->ShowCursor(pScrn); - else - pI830->CursorInfoRec->HideCursor(pScrn); - pI830->cursorOn = TRUE; - } -} - static Bool I830CloseScreen(int scrnIndex, ScreenPtr pScreen) { @@ -3773,7 +3555,7 @@ i830MonitorDetectDebugger(ScrnInfoPtr pScrn) if (!pScrn->vtSema) return 1000; - for (i = 0; i < pI830->xf86_config.num_output; i++) { + for (i = 0; i < xf86_config->num_output; i++) { enum output_status ret; char *result; diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 25ced639..ed8d1c74 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -246,7 +246,7 @@ i830_dvo_init(ScrnInfoPtr pScrn) int ret; output = xf86OutputCreate (pScrn, &i830_dvo_output_funcs, - "ADD AGP card"); + "TMDS"); if (!output) return; intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1); diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 90f785e9..b682b27f 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -135,12 +135,13 @@ i830_lvds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) { ScrnInfoPtr pScrn = output->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); I830CrtcPrivatePtr intel_crtc = output->crtc->driver_private; int i; - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr other_output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr other_output = xf86_config->output[i]; if (other_output != output && other_output->crtc == output->crtc) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -195,11 +196,13 @@ i830_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode, I830Ptr pI830 = I830PTR(pScrn); CARD32 pfit_control; +#if 0 /* The LVDS pin pair needs to be on before the DPLLs are enabled. * This is an exception to the general rule that mode_set doesn't turn * things on. */ OUTREG(LVDS, INREG(LVDS) | LVDS_PORT_EN | LVDS_PIPEB_SELECT); +#endif /* Enable automatic panel scaling so that non-native modes fill the * screen. Should be enabled before the pipe is enabled, according to @@ -311,7 +314,7 @@ i830_lvds_init(ScrnInfoPtr pScrn) } } - output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "Built-in LCD panel"); + output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "LVDS"); if (!output) return; intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1); diff --git a/src/i830_randr.c b/src/i830_randr.c index 2d986df2..290cb10d 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -495,13 +495,17 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) int y; Rotation rotation; int numOutputs; - RROutputPtr randr_outputs[XF86_MAX_OUTPUT]; + RROutputPtr *randr_outputs; RROutputPtr randr_output; xf86CrtcPtr crtc = randr_crtc->devPrivate; xf86OutputPtr output; int i, j; DisplayModePtr curMode = &crtc->curMode; + Bool ret; + randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr)); + if (!randr_outputs) + return FALSE; x = crtc->x; y = crtc->y; rotation = RR_Rotate_0; @@ -529,8 +533,10 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) } } } - return RRCrtcNotify (randr_crtc, randr_mode, x, y, - rotation, numOutputs, randr_outputs); + ret = RRCrtcNotify (randr_crtc, randr_mode, x, y, + rotation, numOutputs, randr_outputs); + DEALLOCATE_LOCAL(randr_outputs); + return ret; } static Bool @@ -550,9 +556,10 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, Bool changed = FALSE; Bool pos_changed; int o, ro; - xf86CrtcPtr save_crtcs[XF86_MAX_OUTPUT]; + xf86CrtcPtr *save_crtcs; Bool save_enabled = crtc->enabled; + save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr)); if ((mode != NULL) != crtc->enabled) changed = TRUE; else if (mode && !xf86ModesEqual (&crtc->curMode, mode)) @@ -606,6 +613,7 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, xf86OutputPtr output = config->output[o]; output->crtc = save_crtcs[o]; } + DEALLOCATE_LOCAL(save_crtcs); return FALSE; } crtc->desiredMode = *mode; @@ -616,6 +624,7 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, } if (pos_changed && mode) i830PipeSetBase(crtc, x, y); + DEALLOCATE_LOCAL(save_crtcs); return xf86RandR12CrtcNotify (randr_crtc); } @@ -694,13 +703,15 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - RROutputPtr clones[XF86_MAX_OUTPUT]; - RRCrtcPtr crtcs[XF86_MAX_CRTC]; + RROutputPtr *clones; + RRCrtcPtr *crtcs; int ncrtc; int o, c, l; RRCrtcPtr randr_crtc; int nclone; + clones = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr)); + crtcs = ALLOCATE_LOCAL (config->num_crtc * sizeof (RRCrtcPtr)); for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; @@ -716,7 +727,11 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen) randr_crtc = NULL; if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc)) + { + DEALLOCATE_LOCAL (crtcs); + DEALLOCATE_LOCAL (clones); return FALSE; + } RROutputSetCrtc (output->randr_output, randr_crtc); RROutputSetPhysicalSize(output->randr_output, @@ -750,8 +765,14 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen) clones[nclone++] = clone->randr_output; } if (!RROutputSetClones (output->randr_output, clones, nclone)) + { + DEALLOCATE_LOCAL (crtcs); + DEALLOCATE_LOCAL (clones); return FALSE; + } } + DEALLOCATE_LOCAL (crtcs); + DEALLOCATE_LOCAL (clones); return TRUE; } diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 87dc9d9e..cb68802a 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -556,12 +556,8 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; xf86CrtcPtr crtc = output->crtc; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - Bool input1, input2; CARD32 sdvox; - int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; int sdvo_pixel_multiply; - int i; - CARD8 status; CARD16 width, height; CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; CARD16 h_sync_offset, v_sync_offset; @@ -666,8 +662,7 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode); if (IS_I965G(pI830)) { - OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | - ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); + /* done in crtc_mode_set as the dpll_md reg must be written early */ } else if (IS_I945G(pI830) || IS_I945GM(pI830)) { /* done in crtc_mode_set as it lives inside the dpll register */ } else { @@ -675,18 +670,6 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, } OUTREG(dev_priv->output_device, sdvox); - - for (i = 0; i < 2; i++) - i830WaitForVblank(pScrn); - - status = i830_sdvo_get_trained_inputs(output, &input1, &input2); - - /* Warn if the device reported failure to sync. */ - if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "First %s output reported failure to sync\n", - SDVO_NAME(dev_priv)); - } } static void @@ -696,13 +679,43 @@ i830_sdvo_dpms(xf86OutputPtr output, int mode) I830OutputPrivatePtr intel_output = output->driver_private; struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; I830Ptr pI830 = I830PTR(pScrn); + CARD32 temp; if (mode != DPMSModeOn) { i830_sdvo_set_active_outputs(output, 0); - OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE); + temp = INREG(dev_priv->output_device); + if ((temp & SDVO_ENABLE) != 0) + OUTREG(dev_priv->output_device, temp & ~SDVO_ENABLE); } else { + Bool input1, input2; + int i; + CARD8 status; + + temp = INREG(dev_priv->output_device); + if ((temp & SDVO_ENABLE) == 0) + { + OUTREG(dev_priv->output_device, temp | SDVO_ENABLE); +#if 0 + /* Do it again! If we remove this below register write, or the exact + * same one 2 lines up, the mac mini SDVO output doesn't turn on. + */ + OUTREG(dev_priv->output_device, + INREG(dev_priv->output_device) | SDVO_ENABLE); +#endif + } + for (i = 0; i < 2; i++) + i830WaitForVblank(pScrn); + + status = i830_sdvo_get_trained_inputs(output, &input1, &input2); + + /* Warn if the device reported failure to sync. */ + if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "First %s output reported failure to sync\n", + SDVO_NAME(dev_priv)); + } + i830_sdvo_set_active_outputs(output, dev_priv->active_outputs); - OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) | SDVO_ENABLE); } } @@ -751,6 +764,21 @@ i830_sdvo_restore(xf86OutputPtr output) struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; I830Ptr pI830 = I830PTR(pScrn); int o; + int i; + Bool input1, input2; + CARD8 status; + + i830_sdvo_set_active_outputs(output, 0); + + for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++) + { + CARD16 this_output = (1 << o); + if (dev_priv->caps.output_flags & this_output) + { + i830_sdvo_set_target_output(output, this_output); + i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd[o]); + } + } if (dev_priv->caps.sdvo_inputs_mask & 0x1) { i830_sdvo_set_target_input(output, TRUE, FALSE); @@ -762,20 +790,22 @@ i830_sdvo_restore(xf86OutputPtr output) i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2); } - for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++) - { - CARD16 this_output = (1 << o); - if (dev_priv->caps.output_flags & this_output) - { - i830_sdvo_set_target_output(output, this_output); - i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd[o]); - } - } - i830_sdvo_set_target_output(output, dev_priv->save_active_outputs); - i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult); OUTREG(dev_priv->output_device, dev_priv->save_SDVOX); + + if (dev_priv->save_SDVOX & SDVO_ENABLE) + { + for (i = 0; i < 2; i++) + i830WaitForVblank(pScrn); + status = i830_sdvo_get_trained_inputs(output, &input1, &input2); + if (status == SDVO_CMD_STATUS_SUCCESS && !input1) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "First %s output reported failure to sync\n", + SDVO_NAME(dev_priv)); + } + + i830_sdvo_set_active_outputs(output, dev_priv->save_active_outputs); } static int @@ -943,12 +973,12 @@ i830_sdvo_dump_device(xf86OutputPtr output) void i830_sdvo_dump(ScrnInfoPtr pScrn) { - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; - for (i = 0; i < pI830->xf86_config.num_output; i++) + for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = pI830->xf86_config.output[i]; + xf86OutputPtr output = xf86_config->output[i]; I830OutputPrivatePtr intel_output = output->driver_private; if (intel_output->type == I830_OUTPUT_SDVO) @@ -983,6 +1013,31 @@ i830_sdvo_detect(xf86OutputPtr output) return XF86OutputStatusDisconnected; } +static DisplayModePtr +i830_sdvo_get_modes(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + DisplayModePtr modes; + xf86OutputPtr crt; + + modes = i830_ddc_get_modes(output); + if (modes != NULL) + return modes; + + /* Mac mini hack. On this device, I get DDC through the analog, which + * load-detects as disconnected. I fail to DDC through the SDVO DDC, + * but it does load-detect as connected. So, just steal the DDC bits from + * analog when we fail at finding it the right way. + */ + crt = xf86_config->output[0]; + if (crt->funcs->detect(crt) == XF86OutputStatusDisconnected) { + return crt->funcs->get_modes(crt); + } + + return NULL; +} + static void i830_sdvo_destroy (xf86OutputPtr output) { @@ -1007,7 +1062,7 @@ static const xf86OutputFuncsRec i830_sdvo_output_funcs = { .mode_fixup = i830_sdvo_mode_fixup, .mode_set = i830_sdvo_mode_set, .detect = i830_sdvo_detect, - .get_modes = i830_ddc_get_modes, + .get_modes = i830_sdvo_get_modes, .destroy = i830_sdvo_destroy }; @@ -1020,6 +1075,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) int i; unsigned char ch[0x40]; I2CBusPtr i2cbus = NULL, ddcbus; + char name[60]; + char *name_prefix; + char *name_suffix; output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs, "ADD2 PCIE card"); @@ -1054,9 +1112,11 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) if (output_device == SDVOB) { dev_priv->d.DevName = "SDVO Controller B"; dev_priv->d.SlaveAddr = 0x70; + name_suffix="-1"; } else { dev_priv->d.DevName = "SDVO Controller C"; dev_priv->d.SlaveAddr = 0x72; + name_suffix="-2"; } dev_priv->d.pI2CBus = i2cbus; dev_priv->d.DriverPrivate.ptr = output; @@ -1125,11 +1185,13 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) { dev_priv->active_outputs = SDVO_OUTPUT_TMDS0; output->subpixel_order = SubPixelHorizontalRGB; + name_prefix="TMDS"; } else if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) { dev_priv->active_outputs = SDVO_OUTPUT_TMDS1; output->subpixel_order = SubPixelHorizontalRGB; + name_prefix="TMDS"; } else { @@ -1141,6 +1203,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) SDVO_NAME(dev_priv), bytes[0], bytes[1]); } + strcpy (name, name_prefix); + strcat (name, name_suffix); + xf86OutputRename (output, name); /* Set the input timing to the screen. Assume always input 0. */ i830_sdvo_set_target_input(output, TRUE, FALSE); diff --git a/src/i830_tv.c b/src/i830_tv.c index b6cc2c9b..af9826b0 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -356,11 +356,11 @@ i830_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) { ScrnInfoPtr pScrn = output->scrn; - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; - for (i = 0; i < pI830->xf86_config.num_output; i++) { - xf86OutputPtr other_output = pI830->xf86_config.output[i]; + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr other_output = xf86_config->output[i]; if (other_output != output && other_output->crtc == output->crtc) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -583,8 +583,11 @@ i830_tv_detect_type (xf86CrtcPtr crtc, tv_dac |= (TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL | TVDAC_B_SENSE_CTL | - TVDAC_C_SENSE_CTL); - tv_dac = DAC_CTL_OVERRIDE | DAC_A_0_7_V | DAC_B_0_7_V | DAC_C_0_7_V; + TVDAC_C_SENSE_CTL | + DAC_CTL_OVERRIDE | + DAC_A_0_7_V | + DAC_B_0_7_V | + DAC_C_0_7_V); OUTREG(TV_CTL, tv_ctl); OUTREG(TV_DAC, tv_dac); i830WaitForVblank(pScrn); @@ -612,7 +615,7 @@ i830_tv_detect_type (xf86CrtcPtr crtc, type = TV_TYPE_COMPONENT; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Couldn't detect TV connection\n"); + "No TV connection detected\n"); type = TV_TYPE_NONE; } @@ -699,7 +702,7 @@ i830_tv_get_modes(xf86OutputPtr output) new->VSyncEnd = 777; new->VTotal = 806; - new->type = M_T_PREFERRED; + new->type = M_T_DRIVER; return new; } @@ -730,10 +733,34 @@ i830_tv_init(ScrnInfoPtr pScrn) xf86OutputPtr output; I830OutputPrivatePtr intel_output; struct i830_tv_priv *dev_priv; + CARD32 tv_dac_on, tv_dac_off, save_tv_dac; if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) return; + /* + * Sanity check the TV output by checking to see if the + * DAC register holds a value + */ + save_tv_dac = INREG(TV_DAC); + + OUTREG(TV_DAC, save_tv_dac | TVDAC_STATE_CHG_EN); + tv_dac_on = INREG(TV_DAC); + + OUTREG(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN); + tv_dac_off = INREG(TV_DAC); + + OUTREG(TV_DAC, save_tv_dac); + + /* + * If the register does not hold the state change enable + * bit, (either as a 0 or a 1), assume it doesn't really + * exist + */ + if ((tv_dac_on & TVDAC_STATE_CHG_EN) == 0 || + (tv_dac_off & TVDAC_STATE_CHG_EN) != 0) + return; + output = xf86OutputCreate (pScrn, &i830_tv_output_funcs, "TV"); if (!output) diff --git a/src/i830_video.c b/src/i830_video.c index a3bfda8d..d10fd168 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -738,10 +738,10 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) /* * Initialise pPriv->overlayOK. Set it to TRUE here so that a warning will - * be generated if I830VideoSwitchModeAfter() sets it to FALSE. + * be generated if i830_crtc_dpms_video() sets it to FALSE during mode + * setup. */ pPriv->overlayOK = TRUE; - I830VideoSwitchModeAfter(pScrn, pScrn->currentMode); pI830->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = I830BlockHandler; @@ -954,7 +954,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->OCLRC1 = pPriv->saturation; overlay->OCMD &= ~OVERLAY_ENABLE; OVERLAY_UPDATE; - } else if (pI830->Clone && attribute == xvPipe) { + } else if (attribute == xvPipe) { if ((value < 0) || (value > 1)) return BadValue; pPriv->pipe = value; @@ -2794,7 +2794,7 @@ BroadwaterDisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, if (pI830->AccelInfoRec) (*pI830->AccelInfoRec->Sync)(pScrn); #if WATCH_STATS - I830PrintErrorState (pScrn); + i830_dump_error_state (pScrn); #endif } @@ -3511,107 +3511,78 @@ I830InitOffscreenImages(ScreenPtr pScreen) } void -I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode) +i830_crtc_dpms_video(xf86CrtcPtr crtc, Bool on) { + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - if (!pI830->adaptor) { + if (pI830->adaptor == NULL) + return; + + /* No overlay scaler on the 965. */ + if (IS_I965G(pI830)) return; - } pPriv = GET_PORT_PRIVATE(pScrn); - if (!pPriv) { - xf86ErrorF("pPriv isn't set\n"); - return; - } - - /* We stop the video when mode switching, just so we don't lockup - * the engine. The overlayOK will determine whether we can re-enable - * with the current video on completion of the mode switch. - */ - I830StopVideo(pScrn, pPriv, TRUE); - - pPriv->overlayOK = FALSE; - - pPriv->oneLineMode = FALSE; -} - -void -I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) -{ - I830Ptr pI830 = I830PTR(pScrn); - I830PortPrivPtr pPriv; - int size, hsize, vsize, active; - - if (!pI830->adaptor) { - return; - } - pPriv = GET_PORT_PRIVATE(pScrn); - if (!pPriv) + /* Check if it's the pipe the overlay is on */ + if (intel_crtc->pipe != pPriv->pipe) return; - pPriv->overlayOK = TRUE; + if (on) { + int size, hsize, vsize, active; + int pipeconf_reg = pPriv->pipe == 0 ? PIPEACONF : PIPEBCONF; + char pipename = pPriv->pipe == 0 ? 'A' : 'B'; -#if 0 - /* XXX Must choose pipe wisely */ - /* ensure pipe is updated on mode switch */ - if (!pI830->Clone) { - if (pPriv->pipe != pI830->pipe) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Changing XVideo pipe (%d to %d).\n", pPriv->pipe, pI830->pipe); - pPriv->pipe = pI830->pipe; - } - } -#endif + pPriv->overlayOK = TRUE; - if (!IS_I965G(pI830)) { - if (pPriv->pipe == 0) { - if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Disabling XVideo output because Pipe A is in double-wide mode.\n"); - pPriv->overlayOK = FALSE; - } else if (!pPriv->overlayOK) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Re-enabling XVideo output because Pipe A is now in single-wide mode.\n"); - pPriv->overlayOK = TRUE; - } + if (INREG(pipeconf_reg) & PIPEACONF_DOUBLE_WIDE) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling XVideo output because Pipe %c is in " + "double-wide mode.\n", pipename); + pPriv->overlayOK = FALSE; + } else if (!pPriv->overlayOK) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Re-enabling XVideo output because Pipe %c is now in " + "single-wide mode.\n", pipename); + pPriv->overlayOK = TRUE; } - if (pPriv->pipe == 1) { - if (INREG(PIPEBCONF) & PIPEBCONF_DOUBLE_WIDE) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Disabling XVideo output because Pipe B is in double-wide mode.\n"); - pPriv->overlayOK = FALSE; - } else if (!pPriv->overlayOK) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Re-enabling XVideo output because Pipe B is now in single-wide mode.\n"); - pPriv->overlayOK = TRUE; - } - } - } + /* Check we have an LFP connected */ + if (i830PipeHasType(xf86_config->crtc[pPriv->pipe], + I830_OUTPUT_LVDS)) { + size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC); + hsize = (size >> 16) & 0x7FF; + vsize = size & 0x7FF; + int vtotal_reg = pPriv->pipe ? VTOTAL_A : VTOTAL_B; + active = INREG(vtotal_reg) & 0x7FF; - /* Check we have an LFP connected */ - if (i830PipeHasType (pI830->xf86_config.crtc[pPriv->pipe], I830_OUTPUT_LVDS)) - { - size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC); - hsize = (size >> 16) & 0x7FF; - vsize = size & 0x7FF; - active = pPriv->pipe ? (INREG(VTOTAL_B) & 0x7FF) : (INREG(VTOTAL_A) & 0x7FF); + if (vsize < active && hsize > 1024) + I830SetOneLineModeRatio(pScrn); - if (vsize < active && hsize > 1024) - I830SetOneLineModeRatio(pScrn); - - if (pPriv->scaleRatio & 0xFFFE0000) { - /* Possible bogus ratio, using in-accurate fallback */ - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Bogus panel fit register, Xvideo positioning may not be accurate.\n"); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Using fallback ratio - was 0x%x, now 0x%x\n", pPriv->scaleRatio, (int)(((float)active * 65536)/(float)vsize)); - - - pPriv->scaleRatio = (int)(((float)active * 65536) / (float)vsize); + if (pPriv->scaleRatio & 0xFFFE0000) { + /* Possible bogus ratio, using in-accurate fallback */ + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Bogus panel fit register, Xvideo positioning may not " + "be accurate.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Using fallback ratio - was 0x%x, now 0x%x\n", + pPriv->scaleRatio, + (int)(((float)active * 65536)/(float)vsize)); + + pPriv->scaleRatio = (int)(((float)active * 65536) / (float)vsize); + } } + } else { + /* We stop the video when mode switching, so we don't lock up + * the engine. The overlayOK will determine whether we can re-enable + * with the current video on completion of the mode switch. + */ + I830StopVideo(pScrn, pPriv, TRUE); + pPriv->overlayOK = FALSE; + pPriv->oneLineMode = FALSE; } } diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 3a592e50..51e6f1c7 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -32,9 +32,40 @@ #include "xf86.h" #include "xf86DDC.h" +#include "i830.h" #include "i830_xf86Crtc.h" #include "X11/extensions/render.h" +/* + * Initialize xf86CrtcConfig structure + */ + +int xf86CrtcConfigPrivateIndex = -1; + +void +xf86CrtcConfigInit (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config; + + if (xf86CrtcConfigPrivateIndex == -1) + xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + config = xnfcalloc (1, sizeof (xf86CrtcConfigRec)); + scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config; +} + +void +xf86CrtcSetSizeRange (ScrnInfoPtr scrn, + int minWidth, int minHeight, + int maxWidth, int maxHeight) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + config->minWidth = minWidth; + config->minHeight = minHeight; + config->maxWidth = maxWidth; + config->maxHeight = maxHeight; +} + /* * Crtc functions */ @@ -43,7 +74,7 @@ xf86CrtcCreate (ScrnInfoPtr scrn, const xf86CrtcFuncsRec *funcs) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc; + xf86CrtcPtr crtc, *crtcs; crtc = xcalloc (sizeof (xf86CrtcRec), 1); if (!crtc) @@ -53,6 +84,17 @@ xf86CrtcCreate (ScrnInfoPtr scrn, #ifdef RANDR_12_INTERFACE crtc->randr_crtc = NULL; #endif + if (xf86_config->crtc) + crtcs = xrealloc (xf86_config->crtc, + (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); + else + crtcs = xalloc ((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); + if (!crtcs) + { + xfree (crtc); + return NULL; + } + xf86_config->crtc = crtcs; xf86_config->crtc[xf86_config->num_crtc++] = crtc; return crtc; } @@ -84,7 +126,7 @@ xf86OutputCreate (ScrnInfoPtr scrn, const xf86OutputFuncsRec *funcs, const char *name) { - xf86OutputPtr output; + xf86OutputPtr output, *outputs; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); int len = strlen (name); @@ -99,10 +141,36 @@ xf86OutputCreate (ScrnInfoPtr scrn, #ifdef RANDR_12_INTERFACE output->randr_output = NULL; #endif + if (xf86_config->output) + outputs = xrealloc (xf86_config->output, + (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); + else + outputs = xalloc ((xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); + if (!outputs) + { + xfree (output); + return NULL; + } + xf86_config->output = outputs; xf86_config->output[xf86_config->num_output++] = output; return output; } +void +xf86OutputRename (xf86OutputPtr output, const char *name) +{ + int len = strlen(name); + char *newname = xalloc (len + 1); + + if (!newname) + return; /* so sorry... */ + + strcpy (newname, name); + if (output->name != (char *) (output + 1)) + xfree (output->name); + output->name = newname; +} + void xf86OutputDestroy (xf86OutputPtr output) { @@ -122,11 +190,13 @@ xf86OutputDestroy (xf86OutputPtr output) xf86_config->num_output--; break; } + if (output->name != (char *) (output + 1)) + xfree (output->name); xfree (output); } static DisplayModePtr -xf86DefaultMode (xf86OutputPtr output) +xf86DefaultMode (xf86OutputPtr output, int width, int height) { DisplayModePtr target_mode = NULL; DisplayModePtr mode; @@ -146,6 +216,7 @@ xf86DefaultMode (xf86OutputPtr output) int preferred = (mode->type & M_T_PREFERRED) != 0; int diff; + if (mode->HDisplay > width || mode->VDisplay > height) continue; dpi = (mode->HDisplay * 254) / (mm_height * 10); diff = dpi - 96; diff = diff < 0 ? -diff : diff; @@ -161,7 +232,8 @@ xf86DefaultMode (xf86OutputPtr output) } static DisplayModePtr -xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match) +xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match, + int width, int height) { DisplayModePtr target_mode = NULL; DisplayModePtr mode; @@ -175,6 +247,8 @@ xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match) int dx, dy; int diff; + if (mode->HDisplay > width || mode->VDisplay > height) continue; + /* exact matches are preferred */ if (xf86ModesEqual (mode, match)) return mode; @@ -192,13 +266,16 @@ xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match) } static Bool -xf86OutputHasPreferredMode (xf86OutputPtr output) +xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height) { DisplayModePtr mode; for (mode = output->probed_modes; mode; mode = mode->next) + { + if (mode->HDisplay > width || mode->VDisplay > height) continue; if (mode->type & M_T_PREFERRED) return TRUE; + } return FALSE; } @@ -206,7 +283,9 @@ static int xf86PickCrtcs (ScrnInfoPtr pScrn, xf86CrtcPtr *best_crtcs, DisplayModePtr *modes, - int n) + int n, + int width, + int height) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); int c, o, l; @@ -227,7 +306,7 @@ xf86PickCrtcs (ScrnInfoPtr pScrn, */ best_crtcs[n] = NULL; best_crtc = NULL; - best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1); + best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1, width, height); if (modes[n] == NULL) return best_score; @@ -240,7 +319,7 @@ xf86PickCrtcs (ScrnInfoPtr pScrn, if (output->status == XF86OutputStatusConnected) my_score++; /* Score outputs with preferred modes higher */ - if (xf86OutputHasPreferredMode (output)) + if (xf86OutputHasPreferredMode (output, width, height)) my_score++; /* * Select a crtc for this output and @@ -279,8 +358,8 @@ xf86PickCrtcs (ScrnInfoPtr pScrn, } crtcs[n] = crtc; memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); - score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1); - if (score >= best_score) + score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1, width, height); + if (score > best_score) { best_crtc = crtc; best_score = score; @@ -308,7 +387,7 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) for (c = 0; c < config->num_crtc; c++) { - int crtc_width = 1600, crtc_height = 1200; + int crtc_width = 0, crtc_height = 0; for (o = 0; o < config->num_output; o++) { @@ -322,20 +401,47 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) { if (mode->HDisplay > crtc_width) crtc_width = mode->HDisplay; - if (mode->VDisplay > crtc_width) + if (mode->VDisplay > crtc_height) crtc_height = mode->VDisplay; } } } - if (crtc_width > width) - width = crtc_width; + width += crtc_width; if (crtc_height > height) height = crtc_height; } + if (config->maxWidth && width > config->maxWidth) width = config->maxWidth; + if (config->maxHeight && height > config->maxHeight) height = config->maxHeight; + if (config->minWidth && width < config->minWidth) width = config->minWidth; + if (config->minHeight && height < config->minHeight) height = config->minHeight; *widthp = width; *heightp = height; } +/* + * XXX walk the monitor mode list and prune out duplicates that + * are inserted by xf86DDCMonitorSet. In an ideal world, that + * function would do this work by itself. + */ + +static void +xf86PruneDuplicateMonitorModes (MonPtr Monitor) +{ + DisplayModePtr master, clone, next; + + for (master = Monitor->Modes; + master && master != Monitor->Last; + master = master->next) + { + for (clone = master->next; clone && clone != Monitor->Modes; clone = next) + { + next = clone->next; + if (xf86ModesEqual (master, clone)) + xf86DeleteMode (&Monitor->Modes, clone); + } + } +} + void xf86ProbeOutputModes (ScrnInfoPtr pScrn) { @@ -343,6 +449,9 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn) Bool properties_set = FALSE; int o; + /* Elide duplicate modes before defaulting code uses them */ + xf86PruneDuplicateMonitorModes (pScrn->monitor); + /* Probe the list of modes for each output. */ for (o = 0; o < config->num_output; o++) { @@ -478,6 +587,26 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) xf86ProbeOutputModes (pScrn); + if (pScrn->display->virtualX == 0) + { + /* + * Expand virtual size to cover potential mode switches + */ + xf86DefaultScreenLimits (pScrn, &width, &height); + + pScrn->display->virtualX = width; + pScrn->display->virtualY = height; + } + else + { + width = pScrn->display->virtualX; + height = pScrn->display->virtualY; + } + if (width > pScrn->virtualX) + pScrn->virtualX = width; + if (height > pScrn->virtualY) + pScrn->virtualY = height; + crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); @@ -492,9 +621,9 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) xf86OutputPtr output = config->output[o]; if (output->status != XF86OutputStatusDisconnected && - xf86OutputHasPreferredMode (output)) + xf86OutputHasPreferredMode (output, width, height)) { - target_mode = xf86DefaultMode (output); + target_mode = xf86DefaultMode (output, width, height); if (target_mode) { modes[o] = target_mode; @@ -510,7 +639,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) xf86OutputPtr output = config->output[o]; if (output->status != XF86OutputStatusDisconnected) { - target_mode = xf86DefaultMode (output); + target_mode = xf86DefaultMode (output, width, height); if (target_mode) { modes[o] = target_mode; @@ -525,30 +654,16 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) xf86OutputPtr output = config->output[o]; if (output->status != XF86OutputStatusDisconnected && !modes[o]) - modes[o] = xf86ClosestMode (output, target_mode); + modes[o] = xf86ClosestMode (output, target_mode, width, height); } - if (!xf86PickCrtcs (pScrn, crtcs, modes, 0)) + if (!xf86PickCrtcs (pScrn, crtcs, modes, 0, width, height)) { xfree (crtcs); xfree (modes); return FALSE; } - xf86DefaultScreenLimits (pScrn, &width, &height); - - /* - * Expand virtual size to cover potential mode switches - */ - if (width > pScrn->virtualX) - pScrn->virtualX = width; - if (width > pScrn->display->virtualX) - pScrn->display->virtualX = width; - if (height > pScrn->virtualY) - pScrn->virtualY = height; - if (height > pScrn->display->virtualY) - pScrn->display->virtualY = height; - /* XXX override xf86 common frame computation code */ pScrn->display->frameX0 = 0; @@ -589,3 +704,38 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) xfree (modes); return TRUE; } + +/** + * Set the DPMS power mode of all outputs and CRTCs. + * + * If the new mode is off, it will turn off outputs and then CRTCs. + * Otherwise, it will affect CRTCs before outputs. + */ +void +xf86DPMSSet(ScrnInfoPtr pScrn, int mode, int flags) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + if (mode == DPMSModeOff) { + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + if (output->crtc != NULL) + (*output->funcs->dpms) (output, mode); + } + } + + for (i = 0; i < config->num_crtc; i++) { + xf86CrtcPtr crtc = config->crtc[i]; + if (crtc->enabled) + (*crtc->funcs->dpms) (crtc, mode); + } + + if (mode != DPMSModeOff) { + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + if (output->crtc != NULL) + (*output->funcs->dpms) (output, mode); + } + } +} diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index 21fc244e..9294ccc2 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -307,26 +307,39 @@ struct _xf86Output { #endif }; -/* XXX yes, static allocation is a kludge */ -#define XF86_MAX_CRTC 4 -#define XF86_MAX_OUTPUT 16 - typedef struct _xf86CrtcConfig { - int num_output; - xf86OutputPtr output[XF86_MAX_OUTPUT]; - /** - * compat_output is used whenever we deal - * with legacy code that only understands a single - * output. pScrn->modes will be loaded from this output, - * adjust frame will whack this output, etc. - */ - int compat_output; - - int num_crtc; - xf86CrtcPtr crtc[XF86_MAX_CRTC]; + int num_output; + xf86OutputPtr *output; + /** + * compat_output is used whenever we deal + * with legacy code that only understands a single + * output. pScrn->modes will be loaded from this output, + * adjust frame will whack this output, etc. + */ + int compat_output; + + int num_crtc; + xf86CrtcPtr *crtc; + + int minWidth, minHeight; + int maxWidth, maxHeight; } xf86CrtcConfigRec, *xf86CrtcConfigPtr; -#define XF86_CRTC_CONFIG_PTR(p) ((xf86CrtcConfigPtr) ((p)->driverPrivate)) +extern int xf86CrtcConfigPrivateIndex; + +#define XF86_CRTC_CONFIG_PTR(p) ((xf86CrtcConfigPtr) ((p)->privates[xf86CrtcConfigPrivateIndex].ptr)) + +/* + * Initialize xf86CrtcConfig structure + */ + +void +xf86CrtcConfigInit (ScrnInfoPtr scrn); + +void +xf86CrtcSetSizeRange (ScrnInfoPtr scrn, + int minWidth, int minHeight, + int maxWidth, int maxHeight); /* * Crtc functions @@ -366,6 +379,9 @@ xf86OutputCreate (ScrnInfoPtr scrn, const xf86OutputFuncsRec *funcs, const char *name); +void +xf86OutputRename (xf86OutputPtr output, const char *name); + void xf86OutputDestroy (xf86OutputPtr output); @@ -378,4 +394,7 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn); Bool xf86InitialConfiguration (ScrnInfoPtr pScrn); +void +xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); + #endif /* _XF86CRTC_H_ */