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

drm/i915: Plumb 'dsb' all way to the plane hooks



We need to be able to do both MMIO and DSB based pipe/plane
programming. To that end plumb the 'dsb' all way from the top
into the plane commit hooks.

The compiler appears smart enough to combine the branches from
all the back-to-back register writes into a single branch.
So the generated asm ends up looking more or less like this:
plane_hook()
{
	if (dsb) {
		intel_dsb_reg_write();
		intel_dsb_reg_write();
		...
	} else {
		intel_de_write_fw();
		intel_de_write_fw();
		...
	}
}
which seems like a reasonably efficient way to do this.

An alternative I was also considering is some kind of closure
(register write function + display vs. dsb pointer passed to it).
That does result is smaller code as there are no branches anymore,
but having each register access go via function pointer sounds
less efficient.

Not that I actually measured the overhead of either approach yet.
Also the reg_rw tracepoint seems to be making a huge mess of the
generated code for the mmio path. And additionally there's some
kind of IS_GSI_REG() hack in __raw_uncore_read() which ends up
generating a pointless branch for every mmio register access.
So looks like there might be quite a bit of room for improvement
in the mmio path still.

Reviewed-by: default avatarAnimesh Manna <animesh.manna@intel.com>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240930170415.23841-12-ville.syrjala@linux.intel.com
parent dd6ec895
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -416,7 +416,8 @@ static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
	return DIV_ROUND_UP(pixel_rate * num, den);
}

static void i9xx_plane_update_noarm(struct intel_plane *plane,
static void i9xx_plane_update_noarm(struct intel_dsb *dsb,
				    struct intel_plane *plane,
				    const struct intel_crtc_state *crtc_state,
				    const struct intel_plane_state *plane_state)
{
@@ -444,7 +445,8 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane,
	}
}

static void i9xx_plane_update_arm(struct intel_plane *plane,
static void i9xx_plane_update_arm(struct intel_dsb *dsb,
				  struct intel_plane *plane,
				  const struct intel_crtc_state *crtc_state,
				  const struct intel_plane_state *plane_state)
{
@@ -507,7 +509,8 @@ static void i9xx_plane_update_arm(struct intel_plane *plane,
				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
}

static void i830_plane_update_arm(struct intel_plane *plane,
static void i830_plane_update_arm(struct intel_dsb *dsb,
				  struct intel_plane *plane,
				  const struct intel_crtc_state *crtc_state,
				  const struct intel_plane_state *plane_state)
{
@@ -517,11 +520,12 @@ static void i830_plane_update_arm(struct intel_plane *plane,
	 * Additional breakage on i830 causes register reads to return
	 * the last latched value instead of the last written value [ALM026].
	 */
	i9xx_plane_update_noarm(plane, crtc_state, plane_state);
	i9xx_plane_update_arm(plane, crtc_state, plane_state);
	i9xx_plane_update_noarm(dsb, plane, crtc_state, plane_state);
	i9xx_plane_update_arm(dsb, plane, crtc_state, plane_state);
}

static void i9xx_plane_disable_arm(struct intel_plane *plane,
static void i9xx_plane_disable_arm(struct intel_dsb *dsb,
				   struct intel_plane *plane,
				   const struct intel_crtc_state *crtc_state)
{
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
@@ -549,7 +553,8 @@ static void i9xx_plane_disable_arm(struct intel_plane *plane,
}

static void
g4x_primary_async_flip(struct intel_plane *plane,
g4x_primary_async_flip(struct intel_dsb *dsb,
		       struct intel_plane *plane,
		       const struct intel_crtc_state *crtc_state,
		       const struct intel_plane_state *plane_state,
		       bool async_flip)
@@ -569,7 +574,8 @@ g4x_primary_async_flip(struct intel_plane *plane,
}

static void
vlv_primary_async_flip(struct intel_plane *plane,
vlv_primary_async_flip(struct intel_dsb *dsb,
		       struct intel_plane *plane,
		       const struct intel_crtc_state *crtc_state,
		       const struct intel_plane_state *plane_state,
		       bool async_flip)
+29 −20
Original line number Diff line number Diff line
@@ -774,7 +774,8 @@ skl_next_plane_to_commit(struct intel_atomic_state *state,
	return NULL;
}

void intel_plane_update_noarm(struct intel_plane *plane,
void intel_plane_update_noarm(struct intel_dsb *dsb,
			      struct intel_plane *plane,
			      const struct intel_crtc_state *crtc_state,
			      const struct intel_plane_state *plane_state)
{
@@ -783,10 +784,11 @@ void intel_plane_update_noarm(struct intel_plane *plane,
	trace_intel_plane_update_noarm(plane, crtc);

	if (plane->update_noarm)
		plane->update_noarm(plane, crtc_state, plane_state);
		plane->update_noarm(dsb, plane, crtc_state, plane_state);
}

void intel_plane_async_flip(struct intel_plane *plane,
void intel_plane_async_flip(struct intel_dsb *dsb,
			    struct intel_plane *plane,
			    const struct intel_crtc_state *crtc_state,
			    const struct intel_plane_state *plane_state,
			    bool async_flip)
@@ -794,34 +796,37 @@ void intel_plane_async_flip(struct intel_plane *plane,
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);

	trace_intel_plane_async_flip(plane, crtc, async_flip);
	plane->async_flip(plane, crtc_state, plane_state, async_flip);
	plane->async_flip(dsb, plane, crtc_state, plane_state, async_flip);
}

void intel_plane_update_arm(struct intel_plane *plane,
void intel_plane_update_arm(struct intel_dsb *dsb,
			    struct intel_plane *plane,
			    const struct intel_crtc_state *crtc_state,
			    const struct intel_plane_state *plane_state)
{
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);

	if (crtc_state->do_async_flip && plane->async_flip) {
		intel_plane_async_flip(plane, crtc_state, plane_state, true);
		intel_plane_async_flip(dsb, plane, crtc_state, plane_state, true);
		return;
	}

	trace_intel_plane_update_arm(plane, crtc);
	plane->update_arm(plane, crtc_state, plane_state);
	plane->update_arm(dsb, plane, crtc_state, plane_state);
}

void intel_plane_disable_arm(struct intel_plane *plane,
void intel_plane_disable_arm(struct intel_dsb *dsb,
			     struct intel_plane *plane,
			     const struct intel_crtc_state *crtc_state)
{
	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);

	trace_intel_plane_disable_arm(plane, crtc);
	plane->disable_arm(plane, crtc_state);
	plane->disable_arm(dsb, plane, crtc_state);
}

void intel_crtc_planes_update_noarm(struct intel_atomic_state *state,
void intel_crtc_planes_update_noarm(struct intel_dsb *dsb,
				    struct intel_atomic_state *state,
				    struct intel_crtc *crtc)
{
	struct intel_crtc_state *new_crtc_state =
@@ -846,11 +851,13 @@ void intel_crtc_planes_update_noarm(struct intel_atomic_state *state,
		/* TODO: for mailbox updates this should be skipped */
		if (new_plane_state->uapi.visible ||
		    new_plane_state->planar_slave)
			intel_plane_update_noarm(plane, new_crtc_state, new_plane_state);
			intel_plane_update_noarm(dsb, plane,
						 new_crtc_state, new_plane_state);
	}
}

static void skl_crtc_planes_update_arm(struct intel_atomic_state *state,
static void skl_crtc_planes_update_arm(struct intel_dsb *dsb,
				       struct intel_atomic_state *state,
				       struct intel_crtc *crtc)
{
	struct intel_crtc_state *old_crtc_state =
@@ -877,13 +884,14 @@ static void skl_crtc_planes_update_arm(struct intel_atomic_state *state,
		 */
		if (new_plane_state->uapi.visible ||
		    new_plane_state->planar_slave)
			intel_plane_update_arm(plane, new_crtc_state, new_plane_state);
			intel_plane_update_arm(dsb, plane, new_crtc_state, new_plane_state);
		else
			intel_plane_disable_arm(plane, new_crtc_state);
			intel_plane_disable_arm(dsb, plane, new_crtc_state);
	}
}

static void i9xx_crtc_planes_update_arm(struct intel_atomic_state *state,
static void i9xx_crtc_planes_update_arm(struct intel_dsb *dsb,
					struct intel_atomic_state *state,
					struct intel_crtc *crtc)
{
	struct intel_crtc_state *new_crtc_state =
@@ -903,21 +911,22 @@ static void i9xx_crtc_planes_update_arm(struct intel_atomic_state *state,
		 * would have to be called here as well.
		 */
		if (new_plane_state->uapi.visible)
			intel_plane_update_arm(plane, new_crtc_state, new_plane_state);
			intel_plane_update_arm(dsb, plane, new_crtc_state, new_plane_state);
		else
			intel_plane_disable_arm(plane, new_crtc_state);
			intel_plane_disable_arm(dsb, plane, new_crtc_state);
	}
}

void intel_crtc_planes_update_arm(struct intel_atomic_state *state,
void intel_crtc_planes_update_arm(struct intel_dsb *dsb,
				  struct intel_atomic_state *state,
				  struct intel_crtc *crtc)
{
	struct drm_i915_private *i915 = to_i915(state->base.dev);

	if (DISPLAY_VER(i915) >= 9)
		skl_crtc_planes_update_arm(state, crtc);
		skl_crtc_planes_update_arm(dsb, state, crtc);
	else
		i9xx_crtc_planes_update_arm(state, crtc);
		i9xx_crtc_planes_update_arm(dsb, state, crtc);
}

int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
+13 −6
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ struct drm_rect;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_dsb;
struct intel_plane;
struct intel_plane_state;
enum plane_id;
@@ -32,26 +33,32 @@ void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
				       struct intel_crtc *crtc);
void intel_plane_copy_hw_state(struct intel_plane_state *plane_state,
			       const struct intel_plane_state *from_plane_state);
void intel_plane_async_flip(struct intel_plane *plane,
void intel_plane_async_flip(struct intel_dsb *dsb,
			    struct intel_plane *plane,
			    const struct intel_crtc_state *crtc_state,
			    const struct intel_plane_state *plane_state,
			    bool async_flip);
void intel_plane_update_noarm(struct intel_plane *plane,
void intel_plane_update_noarm(struct intel_dsb *dsb,
			      struct intel_plane *plane,
			      const struct intel_crtc_state *crtc_state,
			      const struct intel_plane_state *plane_state);
void intel_plane_update_arm(struct intel_plane *plane,
void intel_plane_update_arm(struct intel_dsb *dsb,
			    struct intel_plane *plane,
			    const struct intel_crtc_state *crtc_state,
			    const struct intel_plane_state *plane_state);
void intel_plane_disable_arm(struct intel_plane *plane,
void intel_plane_disable_arm(struct intel_dsb *dsb,
			     struct intel_plane *plane,
			     const struct intel_crtc_state *crtc_state);
struct intel_plane *intel_plane_alloc(void);
void intel_plane_free(struct intel_plane *plane);
struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane);
void intel_plane_destroy_state(struct drm_plane *plane,
			       struct drm_plane_state *state);
void intel_crtc_planes_update_noarm(struct intel_atomic_state *state,
void intel_crtc_planes_update_noarm(struct intel_dsb *dsb,
				    struct intel_atomic_state *state,
				    struct intel_crtc *crtc);
void intel_crtc_planes_update_arm(struct intel_atomic_state *state,
void intel_crtc_planes_update_arm(struct intel_dsb *dsbx,
				  struct intel_atomic_state *state,
				  struct intel_crtc *crtc);
int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
					struct intel_crtc_state *crtc_state,
+1 −1
Original line number Diff line number Diff line
@@ -1915,7 +1915,7 @@ void intel_color_modeset(const struct intel_crtc_state *crtc_state)
		struct intel_plane *plane = to_intel_plane(crtc->base.primary);

		/* update DSPCNTR to configure gamma/csc for pipe bottom color */
		plane->disable_arm(plane, crtc_state);
		plane->disable_arm(NULL, plane, crtc_state);
	}
}

+54 −47
Original line number Diff line number Diff line
@@ -274,7 +274,8 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state,
}

/* TODO: split into noarm+arm pair */
static void i845_cursor_update_arm(struct intel_plane *plane,
static void i845_cursor_update_arm(struct intel_dsb *dsb,
				   struct intel_plane *plane,
				   const struct intel_crtc_state *crtc_state,
				   const struct intel_plane_state *plane_state)
{
@@ -314,10 +315,11 @@ static void i845_cursor_update_arm(struct intel_plane *plane,
	}
}

static void i845_cursor_disable_arm(struct intel_plane *plane,
static void i845_cursor_disable_arm(struct intel_dsb *dsb,
				    struct intel_plane *plane,
				    const struct intel_crtc_state *crtc_state)
{
	i845_cursor_update_arm(plane, crtc_state, NULL);
	i845_cursor_update_arm(dsb, plane, crtc_state, NULL);
}

static bool i845_cursor_get_hw_state(struct intel_plane *plane,
@@ -526,22 +528,25 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
	return 0;
}

static void i9xx_cursor_disable_sel_fetch_arm(struct intel_plane *plane,
static void i9xx_cursor_disable_sel_fetch_arm(struct intel_dsb *dsb,
					      struct intel_plane *plane,
					      const struct intel_crtc_state *crtc_state)
{
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	struct intel_display *display = to_intel_display(plane->base.dev);
	enum pipe pipe = plane->pipe;

	if (!crtc_state->enable_psr2_sel_fetch)
		return;

	intel_de_write_fw(dev_priv, SEL_FETCH_CUR_CTL(pipe), 0);
	intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), 0);
}

static void wa_16021440873(struct intel_plane *plane,
static void wa_16021440873(struct intel_dsb *dsb,
			   struct intel_plane *plane,
			   const struct intel_crtc_state *crtc_state,
			   const struct intel_plane_state *plane_state)
{
	struct intel_display *display = to_intel_display(plane->base.dev);
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	u32 ctl = plane_state->ctl;
	int et_y_position = drm_rect_height(&crtc_state->pipe_src) + 1;
@@ -550,16 +555,18 @@ static void wa_16021440873(struct intel_plane *plane,
	ctl &= ~MCURSOR_MODE_MASK;
	ctl |= MCURSOR_MODE_64_2B;

	intel_de_write_fw(dev_priv, SEL_FETCH_CUR_CTL(pipe), ctl);
	intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), ctl);

	intel_de_write(dev_priv, CURPOS_ERLY_TPT(dev_priv, pipe),
	intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(dev_priv, pipe),
			   CURSOR_POS_Y(et_y_position));
}

static void i9xx_cursor_update_sel_fetch_arm(struct intel_plane *plane,
static void i9xx_cursor_update_sel_fetch_arm(struct intel_dsb *dsb,
					     struct intel_plane *plane,
					     const struct intel_crtc_state *crtc_state,
					     const struct intel_plane_state *plane_state)
{
	struct intel_display *display = to_intel_display(plane->base.dev);
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;

@@ -570,19 +577,17 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_plane *plane,
		if (crtc_state->enable_psr2_su_region_et) {
			u32 val = intel_cursor_position(crtc_state, plane_state,
				true);
			intel_de_write_fw(dev_priv,
					  CURPOS_ERLY_TPT(dev_priv, pipe),
					  val);

			intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(dev_priv, pipe), val);
		}

		intel_de_write_fw(dev_priv, SEL_FETCH_CUR_CTL(pipe),
				  plane_state->ctl);
		intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), plane_state->ctl);
	} else {
		/* Wa_16021440873 */
		if (crtc_state->enable_psr2_su_region_et)
			wa_16021440873(plane, crtc_state, plane_state);
			wa_16021440873(dsb, plane, crtc_state, plane_state);
		else
			i9xx_cursor_disable_sel_fetch_arm(plane, crtc_state);
			i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state);
	}
}

@@ -609,9 +614,11 @@ static u32 skl_cursor_wm_reg_val(const struct skl_wm_level *level)
	return val;
}

static void skl_write_cursor_wm(struct intel_plane *plane,
static void skl_write_cursor_wm(struct intel_dsb *dsb,
				struct intel_plane *plane,
				const struct intel_crtc_state *crtc_state)
{
	struct intel_display *display = to_intel_display(plane->base.dev);
	struct drm_i915_private *i915 = to_i915(plane->base.dev);
	enum plane_id plane_id = plane->id;
	enum pipe pipe = plane->pipe;
@@ -621,30 +628,32 @@ static void skl_write_cursor_wm(struct intel_plane *plane,
	int level;

	for (level = 0; level < i915->display.wm.num_levels; level++)
		intel_de_write_fw(i915, CUR_WM(pipe, level),
		intel_de_write_dsb(display, dsb, CUR_WM(pipe, level),
				   skl_cursor_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level)));

	intel_de_write_fw(i915, CUR_WM_TRANS(pipe),
	intel_de_write_dsb(display, dsb, CUR_WM_TRANS(pipe),
			   skl_cursor_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id)));

	if (HAS_HW_SAGV_WM(i915)) {
		const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];

		intel_de_write_fw(i915, CUR_WM_SAGV(pipe),
		intel_de_write_dsb(display, dsb, CUR_WM_SAGV(pipe),
				   skl_cursor_wm_reg_val(&wm->sagv.wm0));
		intel_de_write_fw(i915, CUR_WM_SAGV_TRANS(pipe),
		intel_de_write_dsb(display, dsb, CUR_WM_SAGV_TRANS(pipe),
				   skl_cursor_wm_reg_val(&wm->sagv.trans_wm));
	}

	intel_de_write_fw(i915, CUR_BUF_CFG(pipe),
	intel_de_write_dsb(display, dsb, CUR_BUF_CFG(pipe),
			   skl_cursor_ddb_reg_val(ddb));
}

/* TODO: split into noarm+arm pair */
static void i9xx_cursor_update_arm(struct intel_plane *plane,
static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
				   struct intel_plane *plane,
				   const struct intel_crtc_state *crtc_state,
				   const struct intel_plane_state *plane_state)
{
	struct intel_display *display = to_intel_display(plane->base.dev);
	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
	enum pipe pipe = plane->pipe;
	u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
@@ -684,38 +693,36 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane,
	 */

	if (DISPLAY_VER(dev_priv) >= 9)
		skl_write_cursor_wm(plane, crtc_state);
		skl_write_cursor_wm(dsb, plane, crtc_state);

	if (plane_state)
		i9xx_cursor_update_sel_fetch_arm(plane, crtc_state,
						 plane_state);
		i9xx_cursor_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state);
	else
		i9xx_cursor_disable_sel_fetch_arm(plane, crtc_state);
		i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state);

	if (plane->cursor.base != base ||
	    plane->cursor.size != fbc_ctl ||
	    plane->cursor.cntl != cntl) {
		if (HAS_CUR_FBC(dev_priv))
			intel_de_write_fw(dev_priv,
					  CUR_FBC_CTL(dev_priv, pipe),
					  fbc_ctl);
		intel_de_write_fw(dev_priv, CURCNTR(dev_priv, pipe), cntl);
		intel_de_write_fw(dev_priv, CURPOS(dev_priv, pipe), pos);
		intel_de_write_fw(dev_priv, CURBASE(dev_priv, pipe), base);
			intel_de_write_dsb(display, dsb, CUR_FBC_CTL(dev_priv, pipe), fbc_ctl);
		intel_de_write_dsb(display, dsb, CURCNTR(dev_priv, pipe), cntl);
		intel_de_write_dsb(display, dsb, CURPOS(dev_priv, pipe), pos);
		intel_de_write_dsb(display, dsb, CURBASE(dev_priv, pipe), base);

		plane->cursor.base = base;
		plane->cursor.size = fbc_ctl;
		plane->cursor.cntl = cntl;
	} else {
		intel_de_write_fw(dev_priv, CURPOS(dev_priv, pipe), pos);
		intel_de_write_fw(dev_priv, CURBASE(dev_priv, pipe), base);
		intel_de_write_dsb(display, dsb, CURPOS(dev_priv, pipe), pos);
		intel_de_write_dsb(display, dsb, CURBASE(dev_priv, pipe), base);
	}
}

static void i9xx_cursor_disable_arm(struct intel_plane *plane,
static void i9xx_cursor_disable_arm(struct intel_dsb *dsb,
				    struct intel_plane *plane,
				    const struct intel_crtc_state *crtc_state)
{
	i9xx_cursor_update_arm(plane, crtc_state, NULL);
	i9xx_cursor_update_arm(dsb, plane, crtc_state, NULL);
}

static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
@@ -904,10 +911,10 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
	}

	if (new_plane_state->uapi.visible) {
		intel_plane_update_noarm(plane, crtc_state, new_plane_state);
		intel_plane_update_arm(plane, crtc_state, new_plane_state);
		intel_plane_update_noarm(NULL, plane, crtc_state, new_plane_state);
		intel_plane_update_arm(NULL, plane, crtc_state, new_plane_state);
	} else {
		intel_plane_disable_arm(plane, crtc_state);
		intel_plane_disable_arm(NULL, plane, crtc_state);
	}

	local_irq_enable();
Loading