[Intel-gfx] [PATCH v2 10/13] drm/i915: Move ddb/wm programming into plane update/disable hooks on skl+

Ville Syrjälä ville.syrjala at linux.intel.com
Wed Nov 21 19:01:18 UTC 2018


On Tue, Nov 20, 2018 at 04:48:39PM -0800, Matt Roper wrote:
> On Wed, Nov 14, 2018 at 11:07:26PM +0200, Ville Syrjala wrote:
> > From: Ville Syrjälä <ville.syrjala at linux.intel.com>
> > 
> > On SKL+ the plane WM/BUF_CFG registers are a proper part of each
> > plane's register set. That means accessing them will cancel any
> > pending plane update, and we would need a PLANE_SURF register write
> > to arm the wm/ddb change as well.
> > 
> > To avoid all the problems with that let's just move the wm/ddb
> > programming into the plane update/disable hooks. Now all plane
> > registers get written in one (hopefully atomic) operation.
> > 
> > To make that feasible we'll move the plane ddb tracking into
> > the crtc state. Watermarks were already tracked there.
> > 
> > v2: Rebase due to input CSC
> > v3: Split out a bunch of junk (Matt)
> > 
> > Cc: Matt Roper <matthew.d.roper at intel.com>
> > Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_debugfs.c  |  21 +-
> >  drivers/gpu/drm/i915/i915_drv.h      |   3 -
> >  drivers/gpu/drm/i915/intel_display.c |  16 +-
> >  drivers/gpu/drm/i915/intel_display.h |  11 +-
> >  drivers/gpu/drm/i915/intel_drv.h     |   9 +
> >  drivers/gpu/drm/i915/intel_pm.c      | 317 ++++++++++++---------------
> >  drivers/gpu/drm/i915/intel_sprite.c  |   4 +
> >  7 files changed, 181 insertions(+), 200 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> > index 670db5073d70..f8b2200947cf 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -3437,31 +3437,32 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
> >  {
> >  	struct drm_i915_private *dev_priv = node_to_i915(m->private);
> >  	struct drm_device *dev = &dev_priv->drm;
> > -	struct skl_ddb_allocation *ddb;
> >  	struct skl_ddb_entry *entry;
> > -	enum pipe pipe;
> > -	int plane;
> > +	struct intel_crtc *crtc;
> >  
> >  	if (INTEL_GEN(dev_priv) < 9)
> >  		return -ENODEV;
> >  
> >  	drm_modeset_lock_all(dev);
> >  
> > -	ddb = &dev_priv->wm.skl_hw.ddb;
> > -
> >  	seq_printf(m, "%-15s%8s%8s%8s\n", "", "Start", "End", "Size");
> >  
> > -	for_each_pipe(dev_priv, pipe) {
> > +	for_each_intel_crtc(&dev_priv->drm, crtc) {
> > +		struct intel_crtc_state *crtc_state =
> > +			to_intel_crtc_state(crtc->base.state);
> > +		enum pipe pipe = crtc->pipe;
> > +		enum plane_id plane_id;
> > +
> >  		seq_printf(m, "Pipe %c\n", pipe_name(pipe));
> >  
> > -		for_each_universal_plane(dev_priv, pipe, plane) {
> > -			entry = &ddb->plane[pipe][plane];
> > -			seq_printf(m, "  Plane%-8d%8u%8u%8u\n", plane + 1,
> > +		for_each_plane_id_on_crtc(crtc, plane_id) {
> > +			entry = &crtc_state->wm.skl.plane_ddb_y[plane_id];
> > +			seq_printf(m, "  Plane%-8d%8u%8u%8u\n", plane_id + 1,
> >  				   entry->start, entry->end,
> >  				   skl_ddb_entry_size(entry));
> >  		}
> >  
> > -		entry = &ddb->plane[pipe][PLANE_CURSOR];
> > +		entry = &crtc_state->wm.skl.plane_ddb_y[PLANE_CURSOR];
> >  		seq_printf(m, "  %-13s%8u%8u%8u\n", "Cursor", entry->start,
> >  			   entry->end, skl_ddb_entry_size(entry));
> >  	}
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 5d686b585a95..89af64fe90a5 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1241,9 +1241,6 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1,
> >  }
> >  
> >  struct skl_ddb_allocation {
> > -	/* packed/y */
> > -	struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES];
> > -	struct skl_ddb_entry uv_plane[I915_MAX_PIPES][I915_MAX_PLANES];
> >  	u8 enabled_slices; /* GEN11 has configurable 2 slices */
> >  };
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 0caba7258fee..2981cea3704a 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -10083,6 +10083,10 @@ static void i9xx_update_cursor(struct intel_plane *plane,
> >  	 * except when the plane is getting enabled at which time
> >  	 * the CURCNTR write arms the update.
> >  	 */
> > +
> > +	if (INTEL_GEN(dev_priv) >= 9)
> > +		skl_write_cursor_wm(plane, crtc_state);
> > +
> >  	if (plane->cursor.base != base ||
> >  	    plane->cursor.size != fbc_ctl ||
> >  	    plane->cursor.cntl != cntl) {
> > @@ -11872,6 +11876,8 @@ static void verify_wm_state(struct drm_crtc *crtc,
> >  	struct skl_pipe_wm hw_wm, *sw_wm;
> >  	struct skl_plane_wm *hw_plane_wm, *sw_plane_wm;
> >  	struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry;
> > +	struct skl_ddb_entry hw_ddb_y[I915_MAX_PLANES];
> > +	struct skl_ddb_entry hw_ddb_uv[I915_MAX_PLANES];
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >  	const enum pipe pipe = intel_crtc->pipe;
> >  	int plane, level, max_level = ilk_wm_max_level(dev_priv);
> > @@ -11882,6 +11888,8 @@ static void verify_wm_state(struct drm_crtc *crtc,
> >  	skl_pipe_wm_get_hw_state(crtc, &hw_wm);
> >  	sw_wm = &to_intel_crtc_state(new_state)->wm.skl.optimal;
> >  
> > +	skl_pipe_ddb_get_hw_state(intel_crtc, hw_ddb_y, hw_ddb_uv);
> > +
> >  	skl_ddb_get_hw_state(dev_priv, &hw_ddb);
> >  	sw_ddb = &dev_priv->wm.skl_hw.ddb;
> >  
> > @@ -11924,8 +11932,8 @@ static void verify_wm_state(struct drm_crtc *crtc,
> >  		}
> >  
> >  		/* DDB */
> > -		hw_ddb_entry = &hw_ddb.plane[pipe][plane];
> > -		sw_ddb_entry = &sw_ddb->plane[pipe][plane];
> > +		hw_ddb_entry = &hw_ddb_y[plane];
> > +		sw_ddb_entry = &to_intel_crtc_state(new_state)->wm.skl.plane_ddb_y[plane];
> >  
> >  		if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
> >  			DRM_ERROR("mismatch in DDB state pipe %c plane %d (expected (%u,%u), found (%u,%u))\n",
> > @@ -11974,8 +11982,8 @@ static void verify_wm_state(struct drm_crtc *crtc,
> >  		}
> >  
> >  		/* DDB */
> > -		hw_ddb_entry = &hw_ddb.plane[pipe][PLANE_CURSOR];
> > -		sw_ddb_entry = &sw_ddb->plane[pipe][PLANE_CURSOR];
> > +		hw_ddb_entry = &hw_ddb_y[PLANE_CURSOR];
> > +		sw_ddb_entry = &to_intel_crtc_state(new_state)->wm.skl.plane_ddb_y[PLANE_CURSOR];
> >  
> >  		if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
> >  			DRM_ERROR("mismatch in DDB state pipe %c cursor (expected (%u,%u), found (%u,%u))\n",
> > diff --git a/drivers/gpu/drm/i915/intel_display.h b/drivers/gpu/drm/i915/intel_display.h
> > index df9e6ebb27de..078406dc65e5 100644
> > --- a/drivers/gpu/drm/i915/intel_display.h
> > +++ b/drivers/gpu/drm/i915/intel_display.h
> > @@ -319,7 +319,7 @@ struct intel_link_m_n {
> >  			    &(dev)->mode_config.plane_list,		\
> >  			    base.head)					\
> >  		for_each_if((plane_mask) &				\
> > -			    drm_plane_mask(&intel_plane->base)))
> > +			    drm_plane_mask(&intel_plane->base))
> >  
> >  #define for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane)	\
> >  	list_for_each_entry(intel_plane,				\
> > @@ -415,6 +415,15 @@ struct intel_link_m_n {
> >  	     (__i)++) \
> >  		for_each_if(plane)
> >  
> > +#define for_each_oldnew_intel_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \
> > +	for ((__i) = 0; \
> > +	     (__i) < (__state)->base.dev->mode_config.num_crtc && \
> > +		     ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
> > +		      (old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), \
> > +		      (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \
> > +	     (__i)++) \
> > +		for_each_if(crtc)
> > +
> >  void intel_link_compute_m_n(int bpp, int nlanes,
> >  			    int pixel_clock, int link_clock,
> >  			    struct intel_link_m_n *m_n,
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 23b33970db17..4a9af09c483a 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -705,6 +705,8 @@ struct intel_crtc_wm_state {
> >  			/* gen9+ only needs 1-step wm programming */
> >  			struct skl_pipe_wm optimal;
> >  			struct skl_ddb_entry ddb;
> > +			struct skl_ddb_entry plane_ddb_y[I915_MAX_PLANES];
> > +			struct skl_ddb_entry plane_ddb_uv[I915_MAX_PLANES];
> 
> I feel like naming these _y and _uv is going to cause confusion.  The Y
> and UV are backwards half the time (based on the swap we have to do
> farther down), and doesn't have meaning at all for RGB.  Maybe name
> these something like "plane_ddb_main" and "plane_ddb_extra" to somewhat
> disassociate it with the actual type of data it's supposed to represent?
> 
> If you want to keep the _y and _uv (which are nice and short), I think
> we at least need some warning comments here explaining the behavior.

Yeah, I was also thinking we might want to just start following the
hardware convention with these and get rid of the swap()s. My initial
idea was just something like ddb[] and ddb_nv12[] to match the
register names.

But let's do that as a followup maybe?

> 
> >  		} skl;
> >  
> >  		struct {
> > @@ -2183,6 +2185,9 @@ void g4x_wm_get_hw_state(struct drm_device *dev);
> >  void vlv_wm_get_hw_state(struct drm_device *dev);
> >  void ilk_wm_get_hw_state(struct drm_device *dev);
> >  void skl_wm_get_hw_state(struct drm_device *dev);
> > +void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
> > +			       struct skl_ddb_entry *ddb_y,
> > +			       struct skl_ddb_entry *ddb_uv);
> >  void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
> >  			  struct skl_ddb_allocation *ddb /* out */);
> >  void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
> > @@ -2197,6 +2202,10 @@ bool skl_wm_level_equals(const struct skl_wm_level *l1,
> >  bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb,
> >  				 const struct skl_ddb_entry entries[],
> >  				 int num_entries, int ignore_idx);
> > +void skl_write_plane_wm(struct intel_plane *plane,
> > +			const struct intel_crtc_state *crtc_state);
> > +void skl_write_cursor_wm(struct intel_plane *plane,
> > +			 const struct intel_crtc_state *crtc_state);
> >  bool ilk_disable_lp_wm(struct drm_device *dev);
> >  int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc,
> >  				  struct intel_crtc_state *cstate);
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index a21654c974ba..1b337004054a 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -3912,68 +3912,70 @@ static void
> >  skl_ddb_get_hw_plane_state(struct drm_i915_private *dev_priv,
> >  			   const enum pipe pipe,
> >  			   const enum plane_id plane_id,
> > -			   struct skl_ddb_allocation *ddb /* out */)
> > +			   struct skl_ddb_entry *ddb_y,
> > +			   struct skl_ddb_entry *ddb_uv)
> >  {
> > -	u32 val, val2 = 0;
> > -	int fourcc, pixel_format;
> > +	u32 val, val2;
> > +	u32 fourcc = 0;
> >  
> >  	/* Cursor doesn't support NV12/planar, so no extra calculation needed */
> >  	if (plane_id == PLANE_CURSOR) {
> >  		val = I915_READ(CUR_BUF_CFG(pipe));
> > -		skl_ddb_entry_init_from_hw(dev_priv,
> > -					   &ddb->plane[pipe][plane_id], val);
> > +		skl_ddb_entry_init_from_hw(dev_priv, ddb_y, val);
> >  		return;
> >  	}
> >  
> >  	val = I915_READ(PLANE_CTL(pipe, plane_id));
> >  
> >  	/* No DDB allocated for disabled planes */
> > -	if (!(val & PLANE_CTL_ENABLE))
> > -		return;
> 
> I think we should mention the readout behavior change in the commit
> message (i.e., we now read out DDB even if we think the plane is
> disabled).  Either that or move the behavior change to a separate patch.
> 
> We should also drop the comment line since I don't think it really makes
> sense anymore.

Sure.

> 
> > +	if (val & PLANE_CTL_ENABLE)
> > +		fourcc = skl_format_to_fourcc(val & PLANE_CTL_FORMAT_MASK,
> > +					      val & PLANE_CTL_ORDER_RGBX,
> > +					      val & PLANE_CTL_ALPHA_MASK);
> >  
> > -	pixel_format = val & PLANE_CTL_FORMAT_MASK;
> > -	fourcc = skl_format_to_fourcc(pixel_format,
> > -				      val & PLANE_CTL_ORDER_RGBX,
> > -				      val & PLANE_CTL_ALPHA_MASK);
> > -
> > -	val = I915_READ(PLANE_BUF_CFG(pipe, plane_id));
> > -	if (fourcc == DRM_FORMAT_NV12 && INTEL_GEN(dev_priv) < 11) {
> > +	if (INTEL_GEN(dev_priv) >= 11) {
> > +		val = I915_READ(PLANE_BUF_CFG(pipe, plane_id));
> > +		skl_ddb_entry_init_from_hw(dev_priv, ddb_y, val);
> > +	} else {
> > +		val = I915_READ(PLANE_BUF_CFG(pipe, plane_id));
> >  		val2 = I915_READ(PLANE_NV12_BUF_CFG(pipe, plane_id));
> >  
> > -		skl_ddb_entry_init_from_hw(dev_priv,
> > -					   &ddb->plane[pipe][plane_id], val2);
> > -		skl_ddb_entry_init_from_hw(dev_priv,
> > -					   &ddb->uv_plane[pipe][plane_id], val);
> > -	} else {
> > -		skl_ddb_entry_init_from_hw(dev_priv,
> > -					   &ddb->plane[pipe][plane_id], val);
> > +		if (fourcc == DRM_FORMAT_NV12)
> > +			swap(val, val2);
> > +
> > +		skl_ddb_entry_init_from_hw(dev_priv, ddb_y, val);
> > +		skl_ddb_entry_init_from_hw(dev_priv, ddb_uv, val2);
> >  	}
> >  }
> >  
> > +void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
> > +			       struct skl_ddb_entry *ddb_y,
> > +			       struct skl_ddb_entry *ddb_uv)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > +	enum intel_display_power_domain power_domain;
> > +	enum pipe pipe = crtc->pipe;
> > +	enum plane_id plane_id;
> > +
> > +	power_domain = POWER_DOMAIN_PIPE(pipe);
> > +	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> > +		return;
> > +
> > +	for_each_plane_id_on_crtc(crtc, plane_id)
> > +		skl_ddb_get_hw_plane_state(dev_priv, pipe,
> > +					   plane_id,
> > +					   &ddb_y[plane_id],
> > +					   &ddb_uv[plane_id]);
> > +
> > +	intel_display_power_put(dev_priv, power_domain);
> > +}
> > +
> >  void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
> >  			  struct skl_ddb_allocation *ddb /* out */)
> >  {
> > -	struct intel_crtc *crtc;
> > -
> >  	memset(ddb, 0, sizeof(*ddb));
> 
> We can drop the memset.  The entire structure is only 1 byte now, and we
> set its only remaining field on the next line.

Ack.

> 
> >  
> >  	ddb->enabled_slices = intel_enabled_dbuf_slices_num(dev_priv);
> > -
> > -	for_each_intel_crtc(&dev_priv->drm, crtc) {
> > -		enum intel_display_power_domain power_domain;
> > -		enum plane_id plane_id;
> > -		enum pipe pipe = crtc->pipe;
> > -
> > -		power_domain = POWER_DOMAIN_PIPE(pipe);
> > -		if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> > -			continue;
> > -
> > -		for_each_plane_id_on_crtc(crtc, plane_id)
> > -			skl_ddb_get_hw_plane_state(dev_priv, pipe,
> > -						   plane_id, ddb);
> > -
> > -		intel_display_power_put(dev_priv, power_domain);
> > -	}
> >  }
> >  
> >  /*
> > @@ -4371,7 +4373,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
> >  	struct drm_crtc *crtc = cstate->base.crtc;
> >  	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > -	enum pipe pipe = intel_crtc->pipe;
> >  	struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb;
> >  	uint16_t alloc_size, start;
> >  	uint16_t minimum[I915_MAX_PLANES] = {};
> > @@ -4384,8 +4385,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
> >  	uint16_t total_min_blocks = 0;
> >  
> >  	/* Clear the partitioning for disabled planes. */
> > -	memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
> > -	memset(ddb->uv_plane[pipe], 0, sizeof(ddb->uv_plane[pipe]));
> > +	memset(cstate->wm.skl.plane_ddb_y, 0, sizeof(cstate->wm.skl.plane_ddb_y));
> > +	memset(cstate->wm.skl.plane_ddb_uv, 0, sizeof(cstate->wm.skl.plane_ddb_uv));
> >  
> >  	if (WARN_ON(!state))
> >  		return 0;
> > @@ -4432,8 +4433,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
> >  	}
> >  
> >  	alloc_size -= total_min_blocks;
> > -	ddb->plane[pipe][PLANE_CURSOR].start = alloc->end - minimum[PLANE_CURSOR];
> > -	ddb->plane[pipe][PLANE_CURSOR].end = alloc->end;
> > +	cstate->wm.skl.plane_ddb_y[PLANE_CURSOR].start = alloc->end - minimum[PLANE_CURSOR];
> > +	cstate->wm.skl.plane_ddb_y[PLANE_CURSOR].end = alloc->end;
> >  
> >  	/*
> >  	 * 2. Distribute the remaining space in proportion to the amount of
> > @@ -4464,8 +4465,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
> >  
> >  		/* Leave disabled planes at (0,0) */
> >  		if (data_rate) {
> > -			ddb->plane[pipe][plane_id].start = start;
> > -			ddb->plane[pipe][plane_id].end = start + plane_blocks;
> > +			cstate->wm.skl.plane_ddb_y[plane_id].start = start;
> > +			cstate->wm.skl.plane_ddb_y[plane_id].end = start + plane_blocks;
> >  		}
> >  
> >  		start += plane_blocks;
> > @@ -4480,8 +4481,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
> >  		WARN_ON(INTEL_GEN(dev_priv) >= 11 && uv_plane_blocks);
> >  
> >  		if (uv_data_rate) {
> > -			ddb->uv_plane[pipe][plane_id].start = start;
> > -			ddb->uv_plane[pipe][plane_id].end =
> > +			cstate->wm.skl.plane_ddb_uv[plane_id].start = start;
> > +			cstate->wm.skl.plane_ddb_uv[plane_id].end =
> >  				start + uv_plane_blocks;
> >  		}
> >  
> > @@ -4939,16 +4940,13 @@ static void skl_compute_transition_wm(const struct intel_crtc_state *cstate,
> >  	}
> >  }
> >  
> > -static int skl_build_plane_wm_single(struct skl_ddb_allocation *ddb,
> > -				     struct intel_crtc_state *crtc_state,
> > +static int skl_build_plane_wm_single(struct intel_crtc_state *crtc_state,
> >  				     const struct intel_plane_state *plane_state,
> >  				     enum plane_id plane_id, int color_plane)
> >  {
> > -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
> >  	struct skl_plane_wm *wm = &crtc_state->wm.skl.optimal.planes[plane_id];
> > +	u16 ddb_blocks = skl_ddb_entry_size(&crtc_state->wm.skl.plane_ddb_y[plane_id]);
> >  	struct skl_wm_params wm_params;
> > -	enum pipe pipe = plane->pipe;
> > -	uint16_t ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][plane_id]);
> >  	int ret;
> >  
> >  	ret = skl_compute_plane_wm_params(crtc_state, plane_state,
> > @@ -4966,16 +4964,13 @@ static int skl_build_plane_wm_single(struct skl_ddb_allocation *ddb,
> >  	return 0;
> >  }
> >  
> > -static int skl_build_plane_wm_uv(struct skl_ddb_allocation *ddb,
> > -				 struct intel_crtc_state *crtc_state,
> > +static int skl_build_plane_wm_uv(struct intel_crtc_state *crtc_state,
> >  				 const struct intel_plane_state *plane_state,
> >  				 enum plane_id plane_id)
> >  {
> > -	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
> >  	struct skl_plane_wm *wm = &crtc_state->wm.skl.optimal.planes[plane_id];
> > +	u16 ddb_blocks = skl_ddb_entry_size(&crtc_state->wm.skl.plane_ddb_uv[plane_id]);
> >  	struct skl_wm_params wm_params;
> > -	enum pipe pipe = plane->pipe;
> > -	uint16_t ddb_blocks = skl_ddb_entry_size(&ddb->uv_plane[pipe][plane_id]);
> >  	int ret;
> >  
> >  	wm->is_planar = true;
> > @@ -4994,8 +4989,7 @@ static int skl_build_plane_wm_uv(struct skl_ddb_allocation *ddb,
> >  	return 0;
> >  }
> >  
> > -static int skl_build_plane_wm(struct skl_ddb_allocation *ddb,
> > -			      struct skl_pipe_wm *pipe_wm,
> > +static int skl_build_plane_wm(struct skl_pipe_wm *pipe_wm,
> >  			      struct intel_crtc_state *crtc_state,
> >  			      const struct intel_plane_state *plane_state)
> >  {
> > @@ -5007,13 +5001,13 @@ static int skl_build_plane_wm(struct skl_ddb_allocation *ddb,
> >  	if (!intel_wm_plane_visible(crtc_state, plane_state))
> >  		return 0;
> >  
> > -	ret = skl_build_plane_wm_single(ddb, crtc_state, plane_state,
> > +	ret = skl_build_plane_wm_single(crtc_state, plane_state,
> >  					plane_id, 0);
> >  	if (ret)
> >  		return ret;
> >  
> >  	if (fb->format->is_yuv && fb->format->num_planes > 1) {
> > -		ret = skl_build_plane_wm_uv(ddb, crtc_state, plane_state,
> > +		ret = skl_build_plane_wm_uv(crtc_state, plane_state,
> >  					    plane_id);
> >  		if (ret)
> >  			return ret;
> > @@ -5022,8 +5016,7 @@ static int skl_build_plane_wm(struct skl_ddb_allocation *ddb,
> >  	return 0;
> >  }
> >  
> > -static int icl_build_plane_wm(struct skl_ddb_allocation *ddb,
> > -			      struct skl_pipe_wm *pipe_wm,
> > +static int icl_build_plane_wm(struct skl_pipe_wm *pipe_wm,
> >  			      struct intel_crtc_state *crtc_state,
> >  			      const struct intel_plane_state *plane_state)
> >  {
> > @@ -5041,17 +5034,17 @@ static int icl_build_plane_wm(struct skl_ddb_allocation *ddb,
> >  		WARN_ON(!fb->format->is_yuv ||
> >  			fb->format->num_planes == 1);
> >  
> > -		ret = skl_build_plane_wm_single(ddb, crtc_state, plane_state,
> > +		ret = skl_build_plane_wm_single(crtc_state, plane_state,
> >  						y_plane_id, 0);
> >  		if (ret)
> >  			return ret;
> >  
> > -		ret = skl_build_plane_wm_single(ddb, crtc_state, plane_state,
> > +		ret = skl_build_plane_wm_single(crtc_state, plane_state,
> >  						plane_id, 1);
> >  		if (ret)
> >  			return ret;
> >  	} else if (intel_wm_plane_visible(crtc_state, plane_state)) {
> > -		ret = skl_build_plane_wm_single(ddb, crtc_state, plane_state,
> > +		ret = skl_build_plane_wm_single(crtc_state, plane_state,
> >  						plane_id, 0);
> >  		if (ret)
> >  			return ret;
> > @@ -5061,7 +5054,6 @@ static int icl_build_plane_wm(struct skl_ddb_allocation *ddb,
> >  }
> >  
> >  static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
> > -			     struct skl_ddb_allocation *ddb,
> >  			     struct skl_pipe_wm *pipe_wm)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
> > @@ -5081,10 +5073,10 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
> >  						to_intel_plane_state(pstate);
> >  
> >  		if (INTEL_GEN(dev_priv) >= 11)
> > -			ret = icl_build_plane_wm(ddb, pipe_wm,
> > +			ret = icl_build_plane_wm(pipe_wm,
> >  						 cstate, intel_pstate);
> >  		else
> > -			ret = skl_build_plane_wm(ddb, pipe_wm,
> > +			ret = skl_build_plane_wm(pipe_wm,
> >  						 cstate, intel_pstate);
> >  		if (ret)
> >  			return ret;
> > @@ -5100,9 +5092,9 @@ static void skl_ddb_entry_write(struct drm_i915_private *dev_priv,
> >  				const struct skl_ddb_entry *entry)
> >  {
> >  	if (entry->end)
> > -		I915_WRITE(reg, (entry->end - 1) << 16 | entry->start);
> > +		I915_WRITE_FW(reg, (entry->end - 1) << 16 | entry->start);
> >  	else
> > -		I915_WRITE(reg, 0);
> > +		I915_WRITE_FW(reg, 0);
> >  }
> >  
> >  static void skl_write_wm_level(struct drm_i915_private *dev_priv,
> > @@ -5117,19 +5109,22 @@ static void skl_write_wm_level(struct drm_i915_private *dev_priv,
> >  		val |= level->plane_res_l << PLANE_WM_LINES_SHIFT;
> >  	}
> >  
> > -	I915_WRITE(reg, val);
> > +	I915_WRITE_FW(reg, val);
> >  }
> >  
> > -static void skl_write_plane_wm(struct intel_crtc *intel_crtc,
> > -			       const struct skl_plane_wm *wm,
> > -			       const struct skl_ddb_allocation *ddb,
> > -			       enum plane_id plane_id)
> > +void skl_write_plane_wm(struct intel_plane *plane,
> > +			const struct intel_crtc_state *crtc_state)
> >  {
> > -	struct drm_crtc *crtc = &intel_crtc->base;
> > -	struct drm_device *dev = crtc->dev;
> > -	struct drm_i915_private *dev_priv = to_i915(dev);
> > +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >  	int level, max_level = ilk_wm_max_level(dev_priv);
> > -	enum pipe pipe = intel_crtc->pipe;
> > +	enum plane_id plane_id = plane->id;
> > +	enum pipe pipe = plane->pipe;
> > +	const struct skl_plane_wm *wm =
> > +		&crtc_state->wm.skl.optimal.planes[plane_id];
> > +	const struct skl_ddb_entry *ddb_y =
> > +		&crtc_state->wm.skl.plane_ddb_y[plane_id];
> > +	const struct skl_ddb_entry *ddb_uv =
> > +		&crtc_state->wm.skl.plane_ddb_uv[plane_id];
> >  
> >  	for (level = 0; level <= max_level; level++) {
> >  		skl_write_wm_level(dev_priv, PLANE_WM(pipe, plane_id, level),
> > @@ -5138,29 +5133,32 @@ static void skl_write_plane_wm(struct intel_crtc *intel_crtc,
> >  	skl_write_wm_level(dev_priv, PLANE_WM_TRANS(pipe, plane_id),
> >  			   &wm->trans_wm);
> >  
> > -	if (wm->is_planar && INTEL_GEN(dev_priv) < 11) {
> > -		skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id),
> > -				    &ddb->uv_plane[pipe][plane_id]);
> > +	if (INTEL_GEN(dev_priv) >= 11) {
> >  		skl_ddb_entry_write(dev_priv,
> > -				    PLANE_NV12_BUF_CFG(pipe, plane_id),
> > -				    &ddb->plane[pipe][plane_id]);
> > -	} else {
> > -		skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id),
> > -				    &ddb->plane[pipe][plane_id]);
> > -		if (INTEL_GEN(dev_priv) < 11)
> > -			I915_WRITE(PLANE_NV12_BUF_CFG(pipe, plane_id), 0x0);
> > +				    PLANE_BUF_CFG(pipe, plane_id), ddb_y);
> > +		return;
> >  	}
> > +
> > +	if (wm->is_planar)
> > +		swap(ddb_y, ddb_uv);
> 
> As noted above, I understand why this is, but it sure looks confusing at
> a casual glance...
> 
> 
> Matt
> 
> > +
> > +	skl_ddb_entry_write(dev_priv,
> > +			    PLANE_BUF_CFG(pipe, plane_id), ddb_y);
> > +	skl_ddb_entry_write(dev_priv,
> > +			    PLANE_NV12_BUF_CFG(pipe, plane_id), ddb_uv);
> >  }
> >  
> > -static void skl_write_cursor_wm(struct intel_crtc *intel_crtc,
> > -				const struct skl_plane_wm *wm,
> > -				const struct skl_ddb_allocation *ddb)
> > +void skl_write_cursor_wm(struct intel_plane *plane,
> > +			 const struct intel_crtc_state *crtc_state)
> >  {
> > -	struct drm_crtc *crtc = &intel_crtc->base;
> > -	struct drm_device *dev = crtc->dev;
> > -	struct drm_i915_private *dev_priv = to_i915(dev);
> > +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> >  	int level, max_level = ilk_wm_max_level(dev_priv);
> > -	enum pipe pipe = intel_crtc->pipe;
> > +	enum plane_id plane_id = plane->id;
> > +	enum pipe pipe = plane->pipe;
> > +	const struct skl_plane_wm *wm =
> > +		&crtc_state->wm.skl.optimal.planes[plane_id];
> > +	const struct skl_ddb_entry *ddb =
> > +		&crtc_state->wm.skl.plane_ddb_y[plane_id];
> >  
> >  	for (level = 0; level <= max_level; level++) {
> >  		skl_write_wm_level(dev_priv, CUR_WM(pipe, level),
> > @@ -5168,8 +5166,7 @@ static void skl_write_cursor_wm(struct intel_crtc *intel_crtc,
> >  	}
> >  	skl_write_wm_level(dev_priv, CUR_WM_TRANS(pipe), &wm->trans_wm);
> >  
> > -	skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe),
> > -			    &ddb->plane[pipe][PLANE_CURSOR]);
> > +	skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe), ddb);
> >  }
> >  
> >  bool skl_wm_level_equals(const struct skl_wm_level *l1,
> > @@ -5210,13 +5207,12 @@ bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb,
> >  static int skl_update_pipe_wm(struct drm_crtc_state *cstate,
> >  			      const struct skl_pipe_wm *old_pipe_wm,
> >  			      struct skl_pipe_wm *pipe_wm, /* out */
> > -			      struct skl_ddb_allocation *ddb, /* out */
> >  			      bool *changed /* out */)
> >  {
> >  	struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate);
> >  	int ret;
> >  
> > -	ret = skl_build_pipe_wm(intel_cstate, ddb, pipe_wm);
> > +	ret = skl_build_pipe_wm(intel_cstate, pipe_wm);
> >  	if (ret)
> >  		return ret;
> >  
> > @@ -5242,42 +5238,29 @@ pipes_modified(struct drm_atomic_state *state)
> >  }
> >  
> >  static int
> > -skl_ddb_add_affected_planes(struct intel_crtc_state *cstate)
> > +skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state,
> > +			    struct intel_crtc_state *new_crtc_state)
> >  {
> > -	struct drm_atomic_state *state = cstate->base.state;
> > -	struct drm_device *dev = state->dev;
> > -	struct drm_crtc *crtc = cstate->base.crtc;
> > -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > -	struct drm_i915_private *dev_priv = to_i915(dev);
> > -	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
> > -	struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb;
> > -	struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb;
> > -	struct drm_plane *plane;
> > -	enum pipe pipe = intel_crtc->pipe;
> > +	struct intel_atomic_state *state = to_intel_atomic_state(new_crtc_state->base.state);
> > +	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
> > +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> > +	struct intel_plane *plane;
> >  
> > -	drm_for_each_plane_mask(plane, dev, cstate->base.plane_mask) {
> > -		struct drm_plane_state *plane_state;
> > -		struct intel_plane *linked;
> > -		enum plane_id plane_id = to_intel_plane(plane)->id;
> > +	for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
> > +		struct intel_plane_state *plane_state;
> > +		enum plane_id plane_id = plane->id;
> >  
> > -		if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][plane_id],
> > -					&new_ddb->plane[pipe][plane_id]) &&
> > -		    skl_ddb_entry_equal(&cur_ddb->uv_plane[pipe][plane_id],
> > -					&new_ddb->uv_plane[pipe][plane_id]))
> > +		if (skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb_y[plane_id],
> > +					&new_crtc_state->wm.skl.plane_ddb_y[plane_id]) &&
> > +		    skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb_uv[plane_id],
> > +					&new_crtc_state->wm.skl.plane_ddb_uv[plane_id]))
> >  			continue;
> >  
> > -		plane_state = drm_atomic_get_plane_state(state, plane);
> > +		plane_state = intel_atomic_get_plane_state(state, plane);
> >  		if (IS_ERR(plane_state))
> >  			return PTR_ERR(plane_state);
> >  
> > -		/* Make sure linked plane is updated too */
> > -		linked = to_intel_plane_state(plane_state)->linked_plane;
> > -		if (!linked)
> > -			continue;
> > -
> > -		plane_state = drm_atomic_get_plane_state(state, &linked->base);
> > -		if (IS_ERR(plane_state))
> > -			return PTR_ERR(plane_state);
> > +		new_crtc_state->update_planes |= BIT(plane_id);
> >  	}
> >  
> >  	return 0;
> > @@ -5289,18 +5272,21 @@ skl_compute_ddb(struct drm_atomic_state *state)
> >  	const struct drm_i915_private *dev_priv = to_i915(state->dev);
> >  	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
> >  	struct skl_ddb_allocation *ddb = &intel_state->wm_results.ddb;
> > +	struct intel_crtc_state *old_crtc_state;
> > +	struct intel_crtc_state *new_crtc_state;
> >  	struct intel_crtc *crtc;
> > -	struct intel_crtc_state *cstate;
> >  	int ret, i;
> >  
> >  	memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb));
> >  
> > -	for_each_new_intel_crtc_in_state(intel_state, crtc, cstate, i) {
> > -		ret = skl_allocate_pipe_ddb(cstate, ddb);
> > +	for_each_oldnew_intel_crtc_in_state(intel_state, crtc, old_crtc_state,
> > +					    new_crtc_state, i) {
> > +		ret = skl_allocate_pipe_ddb(new_crtc_state, ddb);
> >  		if (ret)
> >  			return ret;
> >  
> > -		ret = skl_ddb_add_affected_planes(cstate);
> > +		ret = skl_ddb_add_affected_planes(old_crtc_state,
> > +						  new_crtc_state);
> >  		if (ret)
> >  			return ret;
> >  	}
> > @@ -5309,36 +5295,29 @@ skl_compute_ddb(struct drm_atomic_state *state)
> >  }
> >  
> >  static void
> > -skl_print_wm_changes(const struct drm_atomic_state *state)
> > +skl_print_wm_changes(struct intel_atomic_state *state)
> >  {
> > -	const struct drm_device *dev = state->dev;
> > -	const struct drm_i915_private *dev_priv = to_i915(dev);
> > -	const struct intel_atomic_state *intel_state =
> > -		to_intel_atomic_state(state);
> > -	const struct drm_crtc *crtc;
> > -	const struct drm_crtc_state *cstate;
> > -	const struct intel_plane *intel_plane;
> > -	const struct skl_ddb_allocation *old_ddb = &dev_priv->wm.skl_hw.ddb;
> > -	const struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb;
> > +	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> > +	const struct intel_crtc_state *old_crtc_state;
> > +	const struct intel_crtc_state *new_crtc_state;
> > +	struct intel_plane *plane;
> > +	struct intel_crtc *crtc;
> >  	int i;
> >  
> > -	for_each_new_crtc_in_state(state, crtc, cstate, i) {
> > -		const struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > -		enum pipe pipe = intel_crtc->pipe;
> > -
> > -		for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
> > -			enum plane_id plane_id = intel_plane->id;
> > +	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
> > +					    new_crtc_state, i) {
> > +		for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
> > +			enum plane_id plane_id = plane->id;
> >  			const struct skl_ddb_entry *old, *new;
> >  
> > -			old = &old_ddb->plane[pipe][plane_id];
> > -			new = &new_ddb->plane[pipe][plane_id];
> > +			old = &old_crtc_state->wm.skl.plane_ddb_y[plane_id];
> > +			new = &new_crtc_state->wm.skl.plane_ddb_y[plane_id];
> >  
> >  			if (skl_ddb_entry_equal(old, new))
> >  				continue;
> >  
> >  			DRM_DEBUG_KMS("[PLANE:%d:%s] ddb (%d - %d) -> (%d - %d)\n",
> > -				      intel_plane->base.base.id,
> > -				      intel_plane->base.name,
> > +				      plane->base.base.id, plane->base.name,
> >  				      old->start, old->end,
> >  				      new->start, new->end);
> >  		}
> > @@ -5474,8 +5453,7 @@ skl_compute_wm(struct drm_atomic_state *state)
> >  			&to_intel_crtc_state(crtc->state)->wm.skl.optimal;
> >  
> >  		pipe_wm = &intel_cstate->wm.skl.optimal;
> > -		ret = skl_update_pipe_wm(cstate, old_pipe_wm, pipe_wm,
> > -					 &results->ddb, &changed);
> > +		ret = skl_update_pipe_wm(cstate, old_pipe_wm, pipe_wm, &changed);
> >  		if (ret)
> >  			return ret;
> >  
> > @@ -5489,7 +5467,7 @@ skl_compute_wm(struct drm_atomic_state *state)
> >  		intel_cstate->update_wm_pre = true;
> >  	}
> >  
> > -	skl_print_wm_changes(state);
> > +	skl_print_wm_changes(intel_state);
> >  
> >  	return 0;
> >  }
> > @@ -5500,23 +5478,12 @@ static void skl_atomic_update_crtc_wm(struct intel_atomic_state *state,
> >  	struct intel_crtc *crtc = to_intel_crtc(cstate->base.crtc);
> >  	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
> >  	struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal;
> > -	const struct skl_ddb_allocation *ddb = &state->wm_results.ddb;
> >  	enum pipe pipe = crtc->pipe;
> > -	enum plane_id plane_id;
> >  
> >  	if (!(state->wm_results.dirty_pipes & drm_crtc_mask(&crtc->base)))
> >  		return;
> >  
> >  	I915_WRITE(PIPE_WM_LINETIME(pipe), pipe_wm->linetime);
> > -
> > -	for_each_plane_id_on_crtc(crtc, plane_id) {
> > -		if (plane_id != PLANE_CURSOR)
> > -			skl_write_plane_wm(crtc, &pipe_wm->planes[plane_id],
> > -					   ddb, plane_id);
> > -		else
> > -			skl_write_cursor_wm(crtc, &pipe_wm->planes[plane_id],
> > -					    ddb);
> > -	}
> >  }
> >  
> >  static void skl_initial_wm(struct intel_atomic_state *state,
> > @@ -5526,8 +5493,6 @@ static void skl_initial_wm(struct intel_atomic_state *state,
> >  	struct drm_device *dev = intel_crtc->base.dev;
> >  	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	struct skl_ddb_values *results = &state->wm_results;
> > -	struct skl_ddb_values *hw_vals = &dev_priv->wm.skl_hw;
> > -	enum pipe pipe = intel_crtc->pipe;
> >  
> >  	if ((results->dirty_pipes & drm_crtc_mask(&intel_crtc->base)) == 0)
> >  		return;
> > @@ -5537,11 +5502,6 @@ static void skl_initial_wm(struct intel_atomic_state *state,
> >  	if (cstate->base.active_changed)
> >  		skl_atomic_update_crtc_wm(state, cstate);
> >  
> > -	memcpy(hw_vals->ddb.uv_plane[pipe], results->ddb.uv_plane[pipe],
> > -	       sizeof(hw_vals->ddb.uv_plane[pipe]));
> > -	memcpy(hw_vals->ddb.plane[pipe], results->ddb.plane[pipe],
> > -	       sizeof(hw_vals->ddb.plane[pipe]));
> > -
> >  	mutex_unlock(&dev_priv->wm.wm_mutex);
> >  }
> >  
> > @@ -5692,13 +5652,6 @@ void skl_wm_get_hw_state(struct drm_device *dev)
> >  	if (dev_priv->active_crtcs) {
> >  		/* Fully recompute DDB on first atomic commit */
> >  		dev_priv->wm.distrust_bios_wm = true;
> > -	} else {
> > -		/*
> > -		 * Easy/common case; just sanitize DDB now if everything off
> > -		 * Keep dbuf slice info intact
> > -		 */
> > -		memset(ddb->plane, 0, sizeof(ddb->plane));
> > -		memset(ddb->uv_plane, 0, sizeof(ddb->uv_plane));
> >  	}
> >  }
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> > index 74d904a49bf9..0262159e7084 100644
> > --- a/drivers/gpu/drm/i915/intel_sprite.c
> > +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > @@ -542,6 +542,8 @@ skl_program_plane(struct intel_plane *plane,
> >  	if (fb->format->is_yuv && icl_is_hdr_plane(plane))
> >  		icl_program_input_csc_coeff(crtc_state, plane_state);
> >  
> > +	skl_write_plane_wm(plane, crtc_state);
> > +
> >  	I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
> >  	I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk);
> >  	I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax);
> > @@ -604,6 +606,8 @@ skl_disable_plane(struct intel_plane *plane,
> >  
> >  	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> >  
> > +	skl_write_plane_wm(plane, crtc_state);
> > +
> >  	I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
> >  	I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
> >  
> > -- 
> > 2.18.1
> > 
> 
> -- 
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795

-- 
Ville Syrjälä
Intel


More information about the Intel-gfx mailing list