Commit 971eb92b authored by Ville Syrjälä's avatar Ville Syrjälä
Browse files

drm/i915: Precompute plane SURF address



Currently we pre-compute the plane surface/base address
partially (only for cursor_needs_physical cases) in
intel_plane_pin_fb() and finish the calculation in the
plane->update_arm(). Let's just precompute the whole thing
instead.

One benefit is that we get rid of all the vma offset stuff
from the low level plane code. Another use I have in mind
is including the surface address in the plane tracepoints,
which should make it easier to analyze display faults.

v2: Deal with xe reuse_vma() hacks
v3: use intel_plane_ggtt_offset() still in reuse_vma()

Reviewed-by: default avatarJani Nikula <jani.nikula@intel.com>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250717203216.31258-1-ville.syrjala@linux.intel.com
parent 615c8ec4
Loading
Loading
Loading
Loading
+27 −26
Original line number Diff line number Diff line
@@ -360,6 +360,19 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state,
	return 0;
}

static u32 i8xx_plane_surf_offset(const struct intel_plane_state *plane_state)
{
	int x = plane_state->view.color_plane[0].x;
	int y = plane_state->view.color_plane[0].y;

	return intel_fb_xy_to_linear(x, y, plane_state, 0);
}

u32 i965_plane_surf_offset(const struct intel_plane_state *plane_state)
{
	return plane_state->view.color_plane[0].offset;
}

static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
{
	struct intel_display *display = to_intel_display(crtc_state);
@@ -463,7 +476,7 @@ static void i9xx_plane_update_arm(struct intel_dsb *dsb,
	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
	int x = plane_state->view.color_plane[0].x;
	int y = plane_state->view.color_plane[0].y;
	u32 dspcntr, dspaddr_offset, linear_offset;
	u32 dspcntr;

	dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);

@@ -472,13 +485,6 @@ static void i9xx_plane_update_arm(struct intel_dsb *dsb,
	    crtc_state->async_flip_planes & BIT(plane->id))
		dspcntr |= DISP_ASYNC_FLIP;

	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);

	if (DISPLAY_VER(display) >= 4)
		dspaddr_offset = plane_state->view.color_plane[0].offset;
	else
		dspaddr_offset = linear_offset;

	if (display->platform.cherryview && i9xx_plane == PLANE_B) {
		int crtc_x = plane_state->uapi.dst.x1;
		int crtc_y = plane_state->uapi.dst.y1;
@@ -498,7 +504,7 @@ static void i9xx_plane_update_arm(struct intel_dsb *dsb,
				  DISP_OFFSET_Y(y) | DISP_OFFSET_X(x));
	} else if (DISPLAY_VER(display) >= 4) {
		intel_de_write_fw(display, DSPLINOFF(display, i9xx_plane),
				  linear_offset);
				  intel_fb_xy_to_linear(x, y, plane_state, 0));
		intel_de_write_fw(display, DSPTILEOFF(display, i9xx_plane),
				  DISP_OFFSET_Y(y) | DISP_OFFSET_X(x));
	}
@@ -511,11 +517,9 @@ static void i9xx_plane_update_arm(struct intel_dsb *dsb,
	intel_de_write_fw(display, DSPCNTR(display, i9xx_plane), dspcntr);

	if (DISPLAY_VER(display) >= 4)
		intel_de_write_fw(display, DSPSURF(display, i9xx_plane),
				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
		intel_de_write_fw(display, DSPSURF(display, i9xx_plane), plane_state->surf);
	else
		intel_de_write_fw(display, DSPADDR(display, i9xx_plane),
				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
		intel_de_write_fw(display, DSPADDR(display, i9xx_plane), plane_state->surf);
}

static void i830_plane_update_arm(struct intel_dsb *dsb,
@@ -604,16 +608,13 @@ g4x_primary_async_flip(struct intel_dsb *dsb,
{
	struct intel_display *display = to_intel_display(plane);
	u32 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
	u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;

	if (async_flip)
		dspcntr |= DISP_ASYNC_FLIP;

	intel_de_write_fw(display, DSPCNTR(display, i9xx_plane), dspcntr);

	intel_de_write_fw(display, DSPSURF(display, i9xx_plane),
			  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
	intel_de_write_fw(display, DSPSURF(display, i9xx_plane), plane_state->surf);
}

static void
@@ -624,11 +625,9 @@ vlv_primary_async_flip(struct intel_dsb *dsb,
		       bool async_flip)
{
	struct intel_display *display = to_intel_display(plane);
	u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;

	intel_de_write_fw(display, DSPADDR_VLV(display, i9xx_plane),
			  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
	intel_de_write_fw(display, DSPADDR_VLV(display, i9xx_plane), plane_state->surf);
}

static void
@@ -1037,6 +1036,11 @@ intel_primary_plane_create(struct intel_display *display, enum pipe pipe)
	plane->get_hw_state = i9xx_plane_get_hw_state;
	plane->check_plane = i9xx_plane_check;

	if (DISPLAY_VER(display) >= 4)
		plane->surf_offset = i965_plane_surf_offset;
	else
		plane->surf_offset = i8xx_plane_surf_offset;

	if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
		plane->capture_error = g4x_primary_capture_error;
	else if (DISPLAY_VER(display) >= 4)
@@ -1254,24 +1258,21 @@ bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc,
	const struct intel_plane_state *plane_state =
		to_intel_plane_state(plane->base.state);
	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
	u32 base;

	if (!plane_state->uapi.visible)
		return false;

	base = intel_plane_ggtt_offset(plane_state);

	/*
	 * We may have moved the surface to a different
	 * part of ggtt, make the plane aware of that.
	 */
	if (plane_config->base == base)
	if (plane_config->base == plane_state->surf)
		return false;

	if (DISPLAY_VER(display) >= 4)
		intel_de_write(display, DSPSURF(display, i9xx_plane), base);
		intel_de_write(display, DSPSURF(display, i9xx_plane), plane_state->surf);
	else
		intel_de_write(display, DSPADDR(display, i9xx_plane), base);
		intel_de_write(display, DSPADDR(display, i9xx_plane), plane_state->surf);

	return true;
}
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ unsigned int vlv_plane_min_alignment(struct intel_plane *plane,
				     const struct drm_framebuffer *fb,
				     int colot_plane);
int i9xx_check_plane_surface(struct intel_plane_state *plane_state);
u32 i965_plane_surf_offset(const struct intel_plane_state *plane_state);

struct intel_plane *
intel_primary_plane_create(struct intel_display *display, enum pipe pipe);
+6 −12
Original line number Diff line number Diff line
@@ -33,17 +33,9 @@ static const u32 intel_cursor_formats[] = {
	DRM_FORMAT_ARGB8888,
};

static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
static u32 intel_cursor_surf_offset(const struct intel_plane_state *plane_state)
{
	struct intel_display *display = to_intel_display(plane_state);
	u32 base;

	if (DISPLAY_INFO(display)->cursor_needs_physical)
		base = plane_state->phys_dma_addr;
	else
		base = intel_plane_ggtt_offset(plane_state);

	return base + plane_state->view.color_plane[0].offset;
	return plane_state->view.color_plane[0].offset;
}

static u32 intel_cursor_position(const struct intel_crtc_state *crtc_state,
@@ -297,7 +289,7 @@ static void i845_cursor_update_arm(struct intel_dsb *dsb,

		size = CURSOR_HEIGHT(height) | CURSOR_WIDTH(width);

		base = intel_cursor_base(plane_state);
		base = plane_state->surf;
		pos = intel_cursor_position(crtc_state, plane_state, false);
	}

@@ -675,7 +667,7 @@ static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
		if (width != height)
			fbc_ctl = CUR_FBC_EN | CUR_FBC_HEIGHT(height - 1);

		base = intel_cursor_base(plane_state);
		base = plane_state->surf;
		pos = intel_cursor_position(crtc_state, plane_state, false);
	}

@@ -1051,6 +1043,8 @@ intel_cursor_plane_create(struct intel_display *display,
		cursor->check_plane = i9xx_check_cursor;
	}

	cursor->surf_offset = intel_cursor_surf_offset;

	if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
		cursor->capture_error = g4x_cursor_capture_error;
	else
+4 −1
Original line number Diff line number Diff line
@@ -642,7 +642,6 @@ struct intel_plane_state {
#define PLANE_HAS_FENCE BIT(0)

	struct intel_fb_view view;
	u32 phys_dma_addr; /* for cursor_needs_physical */

	/* for legacy cursor fb unpin */
	struct drm_vblank_work unpin_work;
@@ -665,6 +664,9 @@ struct intel_plane_state {
	/* chroma upsampler control register */
	u32 cus_ctl;

	/* surface address register */
	u32 surf;

	/*
	 * scaler_id
	 *    = -1 : not using a scaler
@@ -1534,6 +1536,7 @@ struct intel_plane {
	bool (*get_hw_state)(struct intel_plane *plane, enum pipe *pipe);
	int (*check_plane)(struct intel_crtc_state *crtc_state,
			   struct intel_plane_state *plane_state);
	u32 (*surf_offset)(const struct intel_plane_state *plane_state);
	int (*min_cdclk)(const struct intel_crtc_state *crtc_state,
			 const struct intel_plane_state *plane_state);
	void (*async_flip)(struct intel_dsb *dsb,
+16 −11
Original line number Diff line number Diff line
@@ -277,17 +277,6 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state,

		plane_state->ggtt_vma = vma;

		/*
		 * Pre-populate the dma address before we enter the vblank
		 * evade critical section as i915_gem_object_get_dma_address()
		 * will trigger might_sleep() even if it won't actually sleep,
		 * which is the case when the fb has already been pinned.
		 */
		if (intel_plane_needs_physical(plane)) {
			struct drm_i915_gem_object *obj = to_intel_bo(intel_fb_bo(&fb->base));

			plane_state->phys_dma_addr = i915_gem_object_get_dma_address(obj, 0);
		}
	} else {
		unsigned int alignment = intel_plane_fb_min_alignment(plane_state);

@@ -311,6 +300,22 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state,
		WARN_ON(plane_state->ggtt_vma == plane_state->dpt_vma);
	}

	/*
	 * Pre-populate the dma address before we enter the vblank
	 * evade critical section as i915_gem_object_get_dma_address()
	 * will trigger might_sleep() even if it won't actually sleep,
	 * which is the case when the fb has already been pinned.
	 */
	if (intel_plane_needs_physical(plane)) {
		struct drm_i915_gem_object *obj = to_intel_bo(intel_fb_bo(&fb->base));

		plane_state->surf = i915_gem_object_get_dma_address(obj, 0) +
			plane->surf_offset(plane_state);
	} else {
		plane_state->surf = intel_plane_ggtt_offset(plane_state) +
			plane->surf_offset(plane_state);
	}

	return 0;
}

Loading