Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c4fdcfb authored by Kristian Høgsberg's avatar Kristian Høgsberg Committed by Dave Airlie
Browse files

drm: pin new and unpin old buffer when setting a mode.



This removes the requirement for user space to pin a buffer before
setting a mode that is backed by the pixels from that buffer.

Signed-off-by: default avatarKristian Høgsberg <krh@redhat.com>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent d1e22c6e
Loading
Loading
Loading
Loading
+13 −7
Original line number Original line Diff line number Diff line
@@ -432,7 +432,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
 */
 */
bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
			      struct drm_display_mode *mode,
			      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_device *dev = crtc->dev;
	struct drm_display_mode *adjusted_mode, saved_mode;
	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 (drm_mode_equal(&saved_mode, &crtc->mode)) {
		if (saved_x != crtc->x || saved_y != crtc->y) {
		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;
			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
	/* Set up the DPLL and any encoders state that needs to adjust or depend
	 * on the DPLL.
	 * 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) {
	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_device *dev;
	struct drm_crtc **save_crtcs, *new_crtc;
	struct drm_crtc **save_crtcs, *new_crtc;
	struct drm_encoder **save_encoders, *new_encoder;
	struct drm_encoder **save_encoders, *new_encoder;
	struct drm_framebuffer *old_fb;
	bool save_enabled;
	bool save_enabled;
	bool changed = false;
	bool changed = false;
	bool flip_or_move = false;
	bool flip_or_move = false;
@@ -684,13 +687,15 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
		changed = true;
		changed = true;


	if (changed) {
	if (changed) {
		old_fb = set->crtc->fb;
		set->crtc->fb = set->fb;
		set->crtc->fb = set->fb;
		set->crtc->enabled = (set->mode != NULL);
		set->crtc->enabled = (set->mode != NULL);
		if (set->mode != NULL) {
		if (set->mode != NULL) {
			DRM_DEBUG("attempting to set mode from userspace\n");
			DRM_DEBUG("attempting to set mode from userspace\n");
			drm_mode_debug_printmodeline(set->mode);
			drm_mode_debug_printmodeline(set->mode);
			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
						      set->x, set->y)) {
						      set->x, set->y,
						      old_fb)) {
				ret = -EINVAL;
				ret = -EINVAL;
				goto fail_set_mode;
				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);
		drm_helper_disable_unused_functions(dev);
	} else if (flip_or_move) {
	} else if (flip_or_move) {
		old_fb = set->crtc->fb;
		if (set->crtc->fb != set->fb)
		if (set->crtc->fb != set->fb)
			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);
	kfree(save_encoders);
@@ -809,8 +815,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
		if (!crtc->enabled)
		if (!crtc->enabled)
			continue;
			continue;


		ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
		ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
					       crtc->y);
					       crtc->x, crtc->y, crtc->fb);


		if (ret == false)
		if (ret == false)
			DRM_ERROR("failed to set mode on crtc %p\n", crtc);
			DRM_ERROR("failed to set mode on crtc %p\n", crtc);
+36 −8
Original line number Original line Diff line number Diff line
@@ -344,7 +344,8 @@ intel_wait_for_vblank(struct drm_device *dev)
}
}


static void
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_device *dev = crtc->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	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 dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
	int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
	int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
	u32 dspcntr;
	u32 dspcntr, alignment;


	/* no fb bound */
	/* no fb bound */
	if (!crtc->fb) {
	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);
	intel_fb = to_intel_framebuffer(crtc->fb);

	obj = intel_fb->obj;
	obj = intel_fb->obj;
	obj_priv = obj->driver_private;
	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;
	Start = obj_priv->gtt_offset;
	Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
	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);
		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)
	if (!dev->primary->master)
		return;
		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,
static void intel_crtc_mode_set(struct drm_crtc *crtc,
				struct drm_display_mode *mode,
				struct drm_display_mode *mode,
				struct drm_display_mode *adjusted_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_device *dev = crtc->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	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);
	I915_WRITE(dspcntr_reg, dspcntr);


	/* Flush the plane changes */
	/* Flush the plane changes */
	intel_pipe_set_base(crtc, x, y);
	intel_pipe_set_base(crtc, x, y, old_fb);

	intel_wait_for_vblank(dev);


	drm_vblank_post_modeset(dev, pipe);
	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 (!crtc->enabled) {
		if (!mode)
		if (!mode)
			mode = &load_detect_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 {
	} else {
		if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
		if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
			crtc_funcs = crtc->helper_private;
			crtc_funcs = crtc->helper_private;
+6 −3
Original line number Original line Diff line number Diff line
@@ -55,10 +55,12 @@ struct drm_crtc_helper_funcs {
			   struct drm_display_mode *adjusted_mode);
			   struct drm_display_mode *adjusted_mode);
	/* Actually set the mode */
	/* Actually set the mode */
	void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *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* */
	/* 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 {
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 int drm_crtc_helper_set_config(struct drm_mode_set *set);
extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
				     struct drm_display_mode *mode,
				     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 bool drm_helper_crtc_in_use(struct drm_crtc *crtc);


extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,