|
@@ -990,6 +990,22 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
int pipestat_reg = (pipe == 0 ? PIPEASTAT : PIPEBSTAT);
|
|
|
|
|
|
+ /* Clear existing vblank status. Note this will clear any other
|
|
|
+ * sticky status fields as well.
|
|
|
+ *
|
|
|
+ * This races with i915_driver_irq_handler() with the result
|
|
|
+ * that either function could miss a vblank event. Here it is not
|
|
|
+ * fatal, as we will either wait upon the next vblank interrupt or
|
|
|
+ * timeout. Generally speaking intel_wait_for_vblank() is only
|
|
|
+ * called during modeset at which time the GPU should be idle and
|
|
|
+ * should *not* be performing page flips and thus not waiting on
|
|
|
+ * vblanks...
|
|
|
+ * Currently, the result of us stealing a vblank from the irq
|
|
|
+ * handler is that a single frame will be skipped during swapbuffers.
|
|
|
+ */
|
|
|
+ I915_WRITE(pipestat_reg,
|
|
|
+ I915_READ(pipestat_reg) | PIPE_VBLANK_INTERRUPT_STATUS);
|
|
|
+
|
|
|
/* Wait for vblank interrupt bit to set */
|
|
|
if (wait_for((I915_READ(pipestat_reg) &
|
|
|
PIPE_VBLANK_INTERRUPT_STATUS),
|
|
@@ -1486,7 +1502,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|
|
dspcntr &= ~DISPPLANE_TILED;
|
|
|
}
|
|
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
|
/* must disable */
|
|
|
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
|
|
|
|
|
@@ -1495,20 +1511,19 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|
|
Start = obj_priv->gtt_offset;
|
|
|
Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8);
|
|
|
|
|
|
- DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
|
|
|
+ DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
|
|
|
+ Start, Offset, x, y, fb->pitch);
|
|
|
I915_WRITE(dspstride, fb->pitch);
|
|
|
if (IS_I965G(dev)) {
|
|
|
- I915_WRITE(dspbase, Offset);
|
|
|
- I915_READ(dspbase);
|
|
|
I915_WRITE(dspsurf, Start);
|
|
|
- I915_READ(dspsurf);
|
|
|
I915_WRITE(dsptileoff, (y << 16) | x);
|
|
|
+ I915_WRITE(dspbase, Offset);
|
|
|
} else {
|
|
|
I915_WRITE(dspbase, Start + Offset);
|
|
|
- I915_READ(dspbase);
|
|
|
}
|
|
|
+ POSTING_READ(dspbase);
|
|
|
|
|
|
- if ((IS_I965G(dev) || plane == 0))
|
|
|
+ if (IS_I965G(dev) || plane == 0)
|
|
|
intel_update_fbc(crtc, &crtc->mode);
|
|
|
|
|
|
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
|
@@ -1522,7 +1537,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|
|
struct drm_framebuffer *old_fb)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct drm_i915_master_private *master_priv;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
struct intel_framebuffer *intel_fb;
|
|
@@ -1530,13 +1544,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|
|
struct drm_gem_object *obj;
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
int plane = intel_crtc->plane;
|
|
|
- unsigned long Start, Offset;
|
|
|
- int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR);
|
|
|
- int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF);
|
|
|
- int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE;
|
|
|
- int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF);
|
|
|
- int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
|
|
|
- u32 dspcntr;
|
|
|
int ret;
|
|
|
|
|
|
/* no fb bound */
|
|
@@ -1572,71 +1579,18 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- dspcntr = I915_READ(dspcntr_reg);
|
|
|
- /* Mask out pixel format bits in case we change it */
|
|
|
- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
|
|
|
- switch (crtc->fb->bits_per_pixel) {
|
|
|
- case 8:
|
|
|
- dspcntr |= DISPPLANE_8BPP;
|
|
|
- break;
|
|
|
- case 16:
|
|
|
- if (crtc->fb->depth == 15)
|
|
|
- dspcntr |= DISPPLANE_15_16BPP;
|
|
|
- else
|
|
|
- dspcntr |= DISPPLANE_16BPP;
|
|
|
- break;
|
|
|
- case 24:
|
|
|
- case 32:
|
|
|
- if (crtc->fb->depth == 30)
|
|
|
- dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA;
|
|
|
- else
|
|
|
- dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
|
|
|
- break;
|
|
|
- default:
|
|
|
- DRM_ERROR("Unknown color depth\n");
|
|
|
+ ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y);
|
|
|
+ if (ret) {
|
|
|
i915_gem_object_unpin(obj);
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- if (IS_I965G(dev)) {
|
|
|
- if (obj_priv->tiling_mode != I915_TILING_NONE)
|
|
|
- dspcntr |= DISPPLANE_TILED;
|
|
|
- else
|
|
|
- dspcntr &= ~DISPPLANE_TILED;
|
|
|
- }
|
|
|
-
|
|
|
- if (HAS_PCH_SPLIT(dev))
|
|
|
- /* must disable */
|
|
|
- dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
|
|
|
-
|
|
|
- I915_WRITE(dspcntr_reg, dspcntr);
|
|
|
-
|
|
|
- Start = obj_priv->gtt_offset;
|
|
|
- Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
|
|
|
-
|
|
|
- DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
|
|
|
- Start, Offset, x, y, crtc->fb->pitch);
|
|
|
- I915_WRITE(dspstride, crtc->fb->pitch);
|
|
|
- if (IS_I965G(dev)) {
|
|
|
- I915_WRITE(dspsurf, Start);
|
|
|
- I915_WRITE(dsptileoff, (y << 16) | x);
|
|
|
- I915_WRITE(dspbase, Offset);
|
|
|
- } else {
|
|
|
- I915_WRITE(dspbase, Start + Offset);
|
|
|
+ return ret;
|
|
|
}
|
|
|
- POSTING_READ(dspbase);
|
|
|
-
|
|
|
- if ((IS_I965G(dev) || plane == 0))
|
|
|
- intel_update_fbc(crtc, &crtc->mode);
|
|
|
-
|
|
|
- intel_wait_for_vblank(dev, pipe);
|
|
|
|
|
|
if (old_fb) {
|
|
|
intel_fb = to_intel_framebuffer(old_fb);
|
|
|
obj_priv = to_intel_bo(intel_fb->obj);
|
|
|
i915_gem_object_unpin(intel_fb->obj);
|
|
|
}
|
|
|
- intel_increase_pllclock(crtc, true);
|
|
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
@@ -1911,9 +1865,6 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
|
int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
|
|
|
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
|
|
|
int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
|
|
|
- int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
|
|
|
- int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ;
|
|
|
- int pf_win_pos = (pipe == 0) ? PFA_WIN_POS : PFB_WIN_POS;
|
|
|
int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
|
|
|
int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
|
|
|
int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
|
|
@@ -1982,15 +1933,19 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
|
}
|
|
|
|
|
|
/* Enable panel fitting for LVDS */
|
|
|
- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
|
|
|
- || HAS_eDP || intel_pch_has_edp(crtc)) {
|
|
|
- if (dev_priv->pch_pf_size) {
|
|
|
- temp = I915_READ(pf_ctl_reg);
|
|
|
- I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | PF_FILTER_MED_3x3);
|
|
|
- I915_WRITE(pf_win_pos, dev_priv->pch_pf_pos);
|
|
|
- I915_WRITE(pf_win_size, dev_priv->pch_pf_size);
|
|
|
- } else
|
|
|
- I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
|
|
|
+ if (dev_priv->pch_pf_size &&
|
|
|
+ (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
|
|
|
+ || HAS_eDP || intel_pch_has_edp(crtc))) {
|
|
|
+ /* Force use of hard-coded filter coefficients
|
|
|
+ * as some pre-programmed values are broken,
|
|
|
+ * e.g. x201.
|
|
|
+ */
|
|
|
+ I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1,
|
|
|
+ PF_ENABLE | PF_FILTER_MED_3x3);
|
|
|
+ I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS,
|
|
|
+ dev_priv->pch_pf_pos);
|
|
|
+ I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ,
|
|
|
+ dev_priv->pch_pf_size);
|
|
|
}
|
|
|
|
|
|
/* Enable CPU pipe */
|
|
@@ -2115,7 +2070,7 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
|
I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
|
|
|
I915_READ(transconf_reg);
|
|
|
|
|
|
- if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 10, 0))
|
|
|
+ if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 100, 1))
|
|
|
DRM_ERROR("failed to enable transcoder\n");
|
|
|
}
|
|
|
|
|
@@ -2155,14 +2110,8 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
|
udelay(100);
|
|
|
|
|
|
/* Disable PF */
|
|
|
- temp = I915_READ(pf_ctl_reg);
|
|
|
- if ((temp & PF_ENABLE) != 0) {
|
|
|
- I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
|
|
|
- I915_READ(pf_ctl_reg);
|
|
|
- }
|
|
|
- I915_WRITE(pf_win_size, 0);
|
|
|
- POSTING_READ(pf_win_size);
|
|
|
-
|
|
|
+ I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0);
|
|
|
+ I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0);
|
|
|
|
|
|
/* disable CPU FDI tx and PCH FDI rx */
|
|
|
temp = I915_READ(fdi_tx_reg);
|
|
@@ -2421,6 +2370,9 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
|
int pipe = intel_crtc->pipe;
|
|
|
bool enabled;
|
|
|
|
|
|
+ if (intel_crtc->dpms_mode == mode)
|
|
|
+ return;
|
|
|
+
|
|
|
intel_crtc->dpms_mode = mode;
|
|
|
intel_crtc->cursor_on = mode == DRM_MODE_DPMS_ON;
|
|
|
|
|
@@ -3554,10 +3506,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf;
|
|
|
bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
|
|
|
bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
|
|
|
- bool is_edp = false;
|
|
|
+ struct intel_encoder *has_edp_encoder = NULL;
|
|
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
|
|
struct drm_encoder *encoder;
|
|
|
- struct intel_encoder *intel_encoder = NULL;
|
|
|
const intel_limit_t *limit;
|
|
|
int ret;
|
|
|
struct fdi_m_n m_n = {0};
|
|
@@ -3578,12 +3529,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
drm_vblank_pre_modeset(dev, pipe);
|
|
|
|
|
|
list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
|
|
+ struct intel_encoder *intel_encoder;
|
|
|
|
|
|
- if (!encoder || encoder->crtc != crtc)
|
|
|
+ if (encoder->crtc != crtc)
|
|
|
continue;
|
|
|
|
|
|
intel_encoder = enc_to_intel_encoder(encoder);
|
|
|
-
|
|
|
switch (intel_encoder->type) {
|
|
|
case INTEL_OUTPUT_LVDS:
|
|
|
is_lvds = true;
|
|
@@ -3607,7 +3558,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
is_dp = true;
|
|
|
break;
|
|
|
case INTEL_OUTPUT_EDP:
|
|
|
- is_edp = true;
|
|
|
+ has_edp_encoder = intel_encoder;
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -3685,10 +3636,10 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
int lane = 0, link_bw, bpp;
|
|
|
/* eDP doesn't require FDI link, so just set DP M/N
|
|
|
according to current link config */
|
|
|
- if (is_edp) {
|
|
|
+ if (has_edp_encoder) {
|
|
|
target_clock = mode->clock;
|
|
|
- intel_edp_link_config(intel_encoder,
|
|
|
- &lane, &link_bw);
|
|
|
+ intel_edp_link_config(has_edp_encoder,
|
|
|
+ &lane, &link_bw);
|
|
|
} else {
|
|
|
/* DP over FDI requires target mode clock
|
|
|
instead of link clock */
|
|
@@ -3709,7 +3660,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
temp |= PIPE_8BPC;
|
|
|
else
|
|
|
temp |= PIPE_6BPC;
|
|
|
- } else if (is_edp || (is_dp && intel_pch_has_edp(crtc))) {
|
|
|
+ } else if (has_edp_encoder || (is_dp && intel_pch_has_edp(crtc))) {
|
|
|
switch (dev_priv->edp_bpp/3) {
|
|
|
case 8:
|
|
|
temp |= PIPE_8BPC;
|
|
@@ -3782,7 +3733,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
|
|
|
udelay(200);
|
|
|
|
|
|
- if (is_edp) {
|
|
|
+ if (has_edp_encoder) {
|
|
|
if (dev_priv->lvds_use_ssc) {
|
|
|
temp |= DREF_SSC1_ENABLE;
|
|
|
I915_WRITE(PCH_DREF_CONTROL, temp);
|
|
@@ -3931,7 +3882,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
dpll_reg = pch_dpll_reg;
|
|
|
}
|
|
|
|
|
|
- if (!is_edp) {
|
|
|
+ if (!has_edp_encoder) {
|
|
|
I915_WRITE(fp_reg, fp);
|
|
|
I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
|
|
|
I915_READ(dpll_reg);
|
|
@@ -4026,7 +3977,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (!is_edp) {
|
|
|
+ if (!has_edp_encoder) {
|
|
|
I915_WRITE(fp_reg, fp);
|
|
|
I915_WRITE(dpll_reg, dpll);
|
|
|
I915_READ(dpll_reg);
|
|
@@ -4105,7 +4056,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
I915_WRITE(link_m1_reg, m_n.link_m);
|
|
|
I915_WRITE(link_n1_reg, m_n.link_n);
|
|
|
|
|
|
- if (is_edp) {
|
|
|
+ if (has_edp_encoder) {
|
|
|
ironlake_set_pll_edp(crtc, adjusted_mode->clock);
|
|
|
} else {
|
|
|
/* enable FDI RX PLL too */
|
|
@@ -4911,15 +4862,6 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
|
|
|
kfree(intel_crtc);
|
|
|
}
|
|
|
|
|
|
-struct intel_unpin_work {
|
|
|
- struct work_struct work;
|
|
|
- struct drm_device *dev;
|
|
|
- struct drm_gem_object *old_fb_obj;
|
|
|
- struct drm_gem_object *pending_flip_obj;
|
|
|
- struct drm_pending_vblank_event *event;
|
|
|
- int pending;
|
|
|
-};
|
|
|
-
|
|
|
static void intel_unpin_work_fn(struct work_struct *__work)
|
|
|
{
|
|
|
struct intel_unpin_work *work =
|
|
@@ -5007,7 +4949,8 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
|
|
|
|
|
|
spin_lock_irqsave(&dev->event_lock, flags);
|
|
|
if (intel_crtc->unpin_work) {
|
|
|
- intel_crtc->unpin_work->pending = 1;
|
|
|
+ if ((++intel_crtc->unpin_work->pending) > 1)
|
|
|
+ DRM_ERROR("Prepared flip multiple times\n");
|
|
|
} else {
|
|
|
DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n");
|
|
|
}
|
|
@@ -5026,9 +4969,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
struct intel_unpin_work *work;
|
|
|
unsigned long flags, offset;
|
|
|
- int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
|
|
|
- int ret, pipesrc;
|
|
|
- u32 flip_mask;
|
|
|
+ int pipe = intel_crtc->pipe;
|
|
|
+ u32 pf, pipesrc;
|
|
|
+ int ret;
|
|
|
|
|
|
work = kzalloc(sizeof *work, GFP_KERNEL);
|
|
|
if (work == NULL)
|
|
@@ -5077,42 +5020,73 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
|
atomic_inc(&obj_priv->pending_flip);
|
|
|
work->pending_flip_obj = obj;
|
|
|
|
|
|
- if (intel_crtc->plane)
|
|
|
- flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
|
|
|
- else
|
|
|
- flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
|
|
|
-
|
|
|
if (IS_GEN3(dev) || IS_GEN2(dev)) {
|
|
|
+ u32 flip_mask;
|
|
|
+
|
|
|
+ if (intel_crtc->plane)
|
|
|
+ flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
|
|
|
+ else
|
|
|
+ flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
|
|
|
+
|
|
|
BEGIN_LP_RING(2);
|
|
|
OUT_RING(MI_WAIT_FOR_EVENT | flip_mask);
|
|
|
OUT_RING(0);
|
|
|
ADVANCE_LP_RING();
|
|
|
}
|
|
|
|
|
|
+ work->enable_stall_check = true;
|
|
|
+
|
|
|
/* Offset into the new buffer for cases of shared fbs between CRTCs */
|
|
|
- offset = obj_priv->gtt_offset;
|
|
|
- offset += (crtc->y * fb->pitch) + (crtc->x * (fb->bits_per_pixel) / 8);
|
|
|
+ offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8;
|
|
|
|
|
|
BEGIN_LP_RING(4);
|
|
|
- if (IS_I965G(dev)) {
|
|
|
+ switch(INTEL_INFO(dev)->gen) {
|
|
|
+ case 2:
|
|
|
OUT_RING(MI_DISPLAY_FLIP |
|
|
|
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
OUT_RING(fb->pitch);
|
|
|
- OUT_RING(offset | obj_priv->tiling_mode);
|
|
|
- pipesrc = I915_READ(pipesrc_reg);
|
|
|
- OUT_RING(pipesrc & 0x0fff0fff);
|
|
|
- } else if (IS_GEN3(dev)) {
|
|
|
+ OUT_RING(obj_priv->gtt_offset + offset);
|
|
|
+ OUT_RING(MI_NOOP);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 3:
|
|
|
OUT_RING(MI_DISPLAY_FLIP_I915 |
|
|
|
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
OUT_RING(fb->pitch);
|
|
|
- OUT_RING(offset);
|
|
|
+ OUT_RING(obj_priv->gtt_offset + offset);
|
|
|
OUT_RING(MI_NOOP);
|
|
|
- } else {
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 4:
|
|
|
+ case 5:
|
|
|
+ /* i965+ uses the linear or tiled offsets from the
|
|
|
+ * Display Registers (which do not change across a page-flip)
|
|
|
+ * so we need only reprogram the base address.
|
|
|
+ */
|
|
|
OUT_RING(MI_DISPLAY_FLIP |
|
|
|
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
OUT_RING(fb->pitch);
|
|
|
- OUT_RING(offset);
|
|
|
- OUT_RING(MI_NOOP);
|
|
|
+ OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
|
|
|
+
|
|
|
+ /* XXX Enabling the panel-fitter across page-flip is so far
|
|
|
+ * untested on non-native modes, so ignore it for now.
|
|
|
+ * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
|
|
|
+ */
|
|
|
+ pf = 0;
|
|
|
+ pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
|
|
|
+ OUT_RING(pf | pipesrc);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 6:
|
|
|
+ OUT_RING(MI_DISPLAY_FLIP |
|
|
|
+ MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
+ OUT_RING(fb->pitch | obj_priv->tiling_mode);
|
|
|
+ OUT_RING(obj_priv->gtt_offset);
|
|
|
+
|
|
|
+ pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
|
|
|
+ pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
|
|
|
+ OUT_RING(pf | pipesrc);
|
|
|
+ break;
|
|
|
}
|
|
|
ADVANCE_LP_RING();
|
|
|
|
|
@@ -5193,7 +5167,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
|
|
|
dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
|
|
|
|
|
|
intel_crtc->cursor_addr = 0;
|
|
|
- intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF;
|
|
|
+ intel_crtc->dpms_mode = -1;
|
|
|
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
|
|
|
|
|
|
intel_crtc->busy = false;
|