diff options
-rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 44 | ||||
-rw-r--r-- | include/drm/drm_crtc_helper.h | 9 |
3 files changed, 55 insertions, 18 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 58e3359..d8a982b 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -432,7 +432,8 @@ static void drm_setup_crtcs(struct drm_device *dev) */ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, - int x, int y) + int x, int y, + struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; struct drm_display_mode *adjusted_mode, saved_mode; @@ -462,7 +463,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (drm_mode_equal(&saved_mode, &crtc->mode)) { if (saved_x != crtc->x || saved_y != crtc->y) { - crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y); + crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, + old_fb); goto done; } } @@ -501,7 +503,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, /* Set up the DPLL and any encoders state that needs to adjust or depend * on the DPLL. */ - crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y); + crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { @@ -564,6 +566,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) struct drm_device *dev; struct drm_crtc **save_crtcs, *new_crtc; struct drm_encoder **save_encoders, *new_encoder; + struct drm_framebuffer *old_fb; bool save_enabled; bool changed = false; bool flip_or_move = false; @@ -684,13 +687,15 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) changed = true; if (changed) { + old_fb = set->crtc->fb; set->crtc->fb = set->fb; set->crtc->enabled = (set->mode != NULL); if (set->mode != NULL) { DRM_DEBUG("attempting to set mode from userspace\n"); drm_mode_debug_printmodeline(set->mode); if (!drm_crtc_helper_set_mode(set->crtc, set->mode, - set->x, set->y)) { + set->x, set->y, + old_fb)) { ret = -EINVAL; goto fail_set_mode; } @@ -701,9 +706,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) } drm_helper_disable_unused_functions(dev); } else if (flip_or_move) { + old_fb = set->crtc->fb; if (set->crtc->fb != set->fb) set->crtc->fb = set->fb; - crtc_funcs->mode_set_base(set->crtc, set->x, set->y); + crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb); } kfree(save_encoders); @@ -809,8 +815,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev) if (!crtc->enabled) continue; - ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x, - crtc->y); + ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, + crtc->x, crtc->y, crtc->fb); if (ret == false) DRM_ERROR("failed to set mode on crtc %p\n", crtc); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6e8b9ab..e5c1c80 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -344,7 +344,8 @@ intel_wait_for_vblank(struct drm_device *dev) } static void -intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) +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; @@ -359,7 +360,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; - u32 dspcntr; + u32 dspcntr, alignment; /* no fb bound */ if (!crtc->fb) { @@ -368,10 +369,32 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) } intel_fb = to_intel_framebuffer(crtc->fb); - obj = intel_fb->obj; obj_priv = obj->driver_private; + switch (obj_priv->tiling_mode) { + case I915_TILING_NONE: + alignment = 64 * 1024; + break; + case I915_TILING_X: + if (IS_I9XX(dev)) + alignment = 1024 * 1024; + else + alignment = 512 * 1024; + break; + case I915_TILING_Y: + /* FIXME: Is this true? */ + DRM_ERROR("Y tiled not allowed for scan out buffers\n"); + return; + default: + BUG(); + } + + if (i915_gem_object_pin(intel_fb->obj, alignment)) + return; + + i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1); + Start = obj_priv->gtt_offset; Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); @@ -409,6 +432,12 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y) I915_READ(dspbase); } + intel_wait_for_vblank(dev); + + if (old_fb) { + intel_fb = to_intel_framebuffer(old_fb); + i915_gem_object_unpin(intel_fb->obj); + } if (!dev->primary->master) return; @@ -680,7 +709,8 @@ static int intel_panel_fitter_pipe (struct drm_device *dev) static void intel_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, - int x, int y) + int x, int y, + struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -915,9 +945,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(dspcntr_reg, dspcntr); /* Flush the plane changes */ - intel_pipe_set_base(crtc, x, y); - - intel_wait_for_vblank(dev); + intel_pipe_set_base(crtc, x, y, old_fb); drm_vblank_post_modeset(dev, pipe); } @@ -1153,7 +1181,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output, if (!crtc->enabled) { if (!mode) mode = &load_detect_mode; - drm_crtc_helper_set_mode(crtc, mode, 0, 0); + drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb); } else { if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) { crtc_funcs = crtc->helper_private; diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index a341828..4bc04cf 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -55,10 +55,12 @@ struct drm_crtc_helper_funcs { struct drm_display_mode *adjusted_mode); /* Actually set the mode */ void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y); + struct drm_display_mode *adjusted_mode, int x, int y, + struct drm_framebuffer *old_fb); /* Move the crtc on the current fb to the given position *optional* */ - void (*mode_set_base)(struct drm_crtc *crtc, int x, int y); + void (*mode_set_base)(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb); }; struct drm_encoder_helper_funcs { @@ -93,7 +95,8 @@ extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow); extern int drm_crtc_helper_set_config(struct drm_mode_set *set); extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, - int x, int y); + int x, int y, + struct drm_framebuffer *old_fb); extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, |