*/
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;
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;
}
}
/* 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) {
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;
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;
}
}
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);
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);
}
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;
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) {
}
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);
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;
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;
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);
}
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;
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 {
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,