diff options
Diffstat (limited to 'src/i830_display.c')
-rw-r--r-- | src/i830_display.c | 73 |
1 files changed, 65 insertions, 8 deletions
diff --git a/src/i830_display.c b/src/i830_display.c index 56a718de..3967b69b 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -35,6 +35,7 @@ #include <assert.h> #include <stdlib.h> #include <math.h> +#include <sys/ioctl.h> #include "xf86.h" #include "i830.h" @@ -667,7 +668,7 @@ i830_enable_fb_compression(xf86CrtcPtr crtc) ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); - if (IS_IGD_GM(pI830)) + if (IS_GM45(pI830)) return i830_enable_fb_compression2(crtc); i830_enable_fb_compression_8xx(crtc); @@ -679,7 +680,7 @@ i830_disable_fb_compression(xf86CrtcPtr crtc) ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); - if (IS_IGD_GM(pI830)) + if (IS_GM45(pI830)) return i830_disable_fb_compression2(crtc); i830_disable_fb_compression_8xx(crtc); @@ -692,6 +693,7 @@ i830_use_fb_compression(xf86CrtcPtr crtc) xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + unsigned long uncompressed_size; int plane = (intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB); int i, count = 0; @@ -723,6 +725,19 @@ i830_use_fb_compression(xf86CrtcPtr crtc) pScrn->bitsPerPixel == 32)) /* mode_set dtrt if fbc is in use */ return FALSE; + /* Can't cache more lines than we can track */ + if (crtc->mode.VDisplay > FBC_LL_SIZE) + return FALSE; + + /* + * Make sure the compressor doesn't go past the end of our compressed + * buffer if the uncompressed size is large. + */ + uncompressed_size = crtc->mode.HDisplay * crtc->mode.VDisplay * + pI830->cpp; + if (pI830->compressed_front_buffer->size < uncompressed_size) + return FALSE; + /* * No checks for pixel multiply, incl. horizontal, or interlaced modes * since they're currently unused. @@ -730,6 +745,37 @@ i830_use_fb_compression(xf86CrtcPtr crtc) return TRUE; } +#if defined(DRM_IOCTL_MODESET_CTL) && defined(XF86DRI) +static void i830_modeset_ctl(xf86CrtcPtr crtc, int pre) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + struct drm_modeset_ctl modeset; + + modeset.crtc = intel_crtc->plane; + + /* + * DPMS will be called many times (especially off), but we only + * want to catch the transition from on->off and off->on. + */ + if (pre && intel_crtc->dpms_mode != DPMSModeOff) { + /* On -> off is a pre modeset */ + modeset.cmd = _DRM_PRE_MODESET; + ioctl(pI830->drmSubFD, DRM_IOCTL_MODESET_CTL, &modeset); + } else if (!pre && intel_crtc->dpms_mode == DPMSModeOff) { + /* Off -> on means post modeset */ + modeset.cmd = _DRM_POST_MODESET; + ioctl(pI830->drmSubFD, DRM_IOCTL_MODESET_CTL, &modeset); + } +} +#else +static void i830_modeset_ctl(xf86CrtcPtr crtc, int dpms_state) +{ + return; +} +#endif /* DRM_IOCTL_MODESET_CTL && XF86DRI */ + /** * Sets the power management mode of the pipe and plane. * @@ -797,8 +843,10 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Reenable compression if needed */ if (i830_use_fb_compression(crtc)) i830_enable_fb_compression(crtc); + i830_modeset_ctl(crtc, 0); break; case DPMSModeOff: + i830_modeset_ctl(crtc, 1); /* Shut off compression if in use */ if (i830_use_fb_compression(crtc)) i830_disable_fb_compression(crtc); @@ -1080,7 +1128,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS; int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE; int pipestat_reg = (pipe == 0) ? PIPEASTAT : PIPEBSTAT; - int i; + int i, num_outputs = 0; int refclk; intel_clock_t clock; uint32_t dpll = 0, fp = 0, dspcntr, pipeconf, lvds_bits = 0; @@ -1103,6 +1151,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, lvds_bits = intel_output->lvds_bits; break; case I830_OUTPUT_SDVO: + case I830_OUTPUT_HDMI: is_sdvo = TRUE; if (intel_output->needs_tv_clock) is_tv = TRUE; @@ -1119,9 +1168,19 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, is_crt = TRUE; break; } + + num_outputs++; } - if (IS_I9XX(pI830)) { + if (num_outputs > 1) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "clone detected, disabling SSC\n"); + + /* Don't use SSC when cloned */ + if (pI830->lvds_use_ssc && num_outputs < 2) { + refclk = pI830->lvds_ssc_freq * 1000; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "using SSC reference clock of %d MHz\n", refclk / 1000); + } else if (IS_I9XX(pI830)) { refclk = 96000; } else { refclk = 48000; @@ -1174,7 +1233,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; break; } - if (IS_I965G(pI830)) + if (IS_I965G(pI830) && !IS_GM45(pI830)) dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); } else { if (is_lvds) { @@ -1197,10 +1256,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ dpll |= 3; } -#if 0 - else if (is_lvds) + else if (is_lvds && pI830->lvds_use_ssc && num_outputs < 2) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; -#endif else dpll |= PLL_REF_INPUT_DREFCLK; |