All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Vetter <daniel@ffwll.ch>
To: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: Re: [PATCH 3/4] drm/fb-helper: Set up gamma_lut during restore_fbdev_mode_atomic()
Date: Fri, 7 Jun 2019 20:40:15 +0200	[thread overview]
Message-ID: <20190607184015.GN21222@phenom.ffwll.local> (raw)
In-Reply-To: <20190607162611.23514-3-ville.syrjala@linux.intel.com>

On Fri, Jun 07, 2019 at 07:26:10PM +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> i915 will now refuse to enable a C8 plane unless the gamma_lut
> is already enabled (to avoid scanning out whatever garbage got
> left in the hw LUT previously). So in order to make the fbdev
> code work with C8 we need to program the gamma_lut already
> during restore_fbdev_mode_atomic().
> 
> To avoid having to update the hw LUT every time
> restore_fbdev_mode_atomic() is called we hang on to the
> current gamma_lut blob. Note that the first crtc to get
> enabled will dictate the size of the gamma_lut, so this
> approach isn't 100% great for hardware with non-uniform
> crtcs. But that problem already exists in setcmap_atomic()
> so we'll just keep ignoring it.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_fb_helper.c | 165 ++++++++++++++++++++------------
>  include/drm/drm_fb_helper.h     |   7 ++
>  2 files changed, 113 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index bdfa14cd7f6d..0ecec763789f 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -436,10 +436,76 @@ static bool drm_fb_helper_panel_rotation(struct drm_mode_set *modeset,
>  	return true;
>  }
>  
> +static int setcmap_crtc_atomic(struct drm_atomic_state *state,
> +			       struct drm_crtc *crtc,
> +			       struct drm_property_blob *gamma_lut)
> +{
> +	struct drm_crtc_state *crtc_state;
> +	bool replaced;
> +
> +	crtc_state = drm_atomic_get_crtc_state(state, crtc);
> +	if (IS_ERR(crtc_state))
> +		return PTR_ERR(crtc_state);
> +
> +	replaced  = drm_property_replace_blob(&crtc_state->degamma_lut,
> +					      NULL);
> +	replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
> +	replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
> +					      gamma_lut);
> +	crtc_state->color_mgmt_changed |= replaced;
> +
> +	return 0;
> +}
> +
> +static struct drm_property_blob *setcmap_new_gamma_lut(struct drm_crtc *crtc,
> +						       struct fb_cmap *cmap)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_property_blob *gamma_lut;
> +	struct drm_color_lut *lut;
> +	int size = crtc->gamma_size;
> +	int i;
> +
> +	if (!size || cmap->start + cmap->len > size)
> +		return ERR_PTR(-EINVAL);
> +
> +	gamma_lut = drm_property_create_blob(dev, sizeof(*lut) * size, NULL);
> +	if (IS_ERR(gamma_lut))
> +		return gamma_lut;
> +
> +	lut = gamma_lut->data;
> +	if (cmap->start || cmap->len != size) {
> +		u16 *r = crtc->gamma_store;
> +		u16 *g = r + crtc->gamma_size;
> +		u16 *b = g + crtc->gamma_size;
> +
> +		for (i = 0; i < cmap->start; i++) {
> +			lut[i].red = r[i];
> +			lut[i].green = g[i];
> +			lut[i].blue = b[i];
> +		}
> +		for (i = cmap->start + cmap->len; i < size; i++) {
> +			lut[i].red = r[i];
> +			lut[i].green = g[i];
> +			lut[i].blue = b[i];
> +		}
> +	}
> +
> +	for (i = 0; i < cmap->len; i++) {
> +		lut[cmap->start + i].red = cmap->red[i];
> +		lut[cmap->start + i].green = cmap->green[i];
> +		lut[cmap->start + i].blue = cmap->blue[i];
> +	}
> +
> +	return gamma_lut;
> +}
> +
>  static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active)
>  {
> +	struct fb_info *info = fb_helper->fbdev;
>  	struct drm_client_dev *client = &fb_helper->client;
>  	struct drm_device *dev = fb_helper->dev;
> +	struct drm_property_blob *gamma_lut;
>  	struct drm_plane_state *plane_state;
>  	struct drm_plane *plane;
>  	struct drm_atomic_state *state;
> @@ -455,6 +521,10 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
>  		goto out_ctx;
>  	}
>  
> +	gamma_lut = fb_helper->gamma_lut;
> +	if (gamma_lut)
> +		drm_property_blob_get(gamma_lut);

Why the get/put stuff here?

> +
>  	state->acquire_ctx = &ctx;
>  retry:
>  	drm_for_each_plane(plane, dev) {
> @@ -476,7 +546,8 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
>  	}
>  
>  	drm_client_for_each_modeset(mode_set, client) {
> -		struct drm_plane *primary = mode_set->crtc->primary;
> +		struct drm_crtc *crtc = mode_set->crtc;
> +		struct drm_plane *primary = crtc->primary;
>  		unsigned int rotation;
>  
>  		if (drm_fb_helper_panel_rotation(mode_set, &rotation)) {
> @@ -489,24 +560,46 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
>  		if (ret != 0)
>  			goto out_state;
>  
> +		if (info->fix.visual != FB_VISUAL_TRUECOLOR) {
> +			if (!gamma_lut)
> +				gamma_lut = setcmap_new_gamma_lut(crtc, &info->cmap);
> +			if (IS_ERR(gamma_lut)) {
> +				ret = PTR_ERR(gamma_lut);
> +				gamma_lut = NULL;
> +				goto out_state;
> +			}
> +
> +			ret = setcmap_crtc_atomic(state, crtc, gamma_lut);
> +			if (ret)
> +				goto out_state;
> +		}
> +
>  		/*
>  		 * __drm_atomic_helper_set_config() sets active when a
>  		 * mode is set, unconditionally clear it if we force DPMS off
>  		 */
>  		if (!active) {
> -			struct drm_crtc *crtc = mode_set->crtc;
> -			struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
> +			struct drm_crtc_state *crtc_state =
> +				drm_atomic_get_new_crtc_state(state, crtc);
>  
>  			crtc_state->active = false;
>  		}
>  	}
>  
>  	ret = drm_atomic_commit(state);
> +	if (ret)
> +		goto out_state;
> +
> +	if (gamma_lut)
> +		drm_property_blob_get(gamma_lut);
> +	drm_property_blob_put(fb_helper->gamma_lut);
> +	fb_helper->gamma_lut = gamma_lut;

Can't we simplify using drm_property_replace_blob here and below?

>  
>  out_state:
>  	if (ret == -EDEADLK)
>  		goto backoff;
>  
> +	drm_property_blob_put(gamma_lut);
>  	drm_atomic_state_put(state);
>  out_ctx:
>  	drm_modeset_drop_locks(&ctx);
> @@ -996,6 +1089,9 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
>  	}
>  	fb_helper->fbdev = NULL;
>  
> +	drm_property_blob_put(fb_helper->gamma_lut);
> +	fb_helper->gamma_lut = NULL;
> +
>  	mutex_lock(&kernel_fb_helper_lock);
>  	if (!list_empty(&fb_helper->kernel_fb_list)) {
>  		list_del(&fb_helper->kernel_fb_list);
> @@ -1390,61 +1486,16 @@ static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info)
>  	return ret;
>  }
>  
> -static struct drm_property_blob *setcmap_new_gamma_lut(struct drm_crtc *crtc,
> -						       struct fb_cmap *cmap)
> -{
> -	struct drm_device *dev = crtc->dev;
> -	struct drm_property_blob *gamma_lut;
> -	struct drm_color_lut *lut;
> -	int size = crtc->gamma_size;
> -	int i;
> -
> -	if (!size || cmap->start + cmap->len > size)
> -		return ERR_PTR(-EINVAL);
> -
> -	gamma_lut = drm_property_create_blob(dev, sizeof(*lut) * size, NULL);
> -	if (IS_ERR(gamma_lut))
> -		return gamma_lut;
> -
> -	lut = gamma_lut->data;
> -	if (cmap->start || cmap->len != size) {
> -		u16 *r = crtc->gamma_store;
> -		u16 *g = r + crtc->gamma_size;
> -		u16 *b = g + crtc->gamma_size;
> -
> -		for (i = 0; i < cmap->start; i++) {
> -			lut[i].red = r[i];
> -			lut[i].green = g[i];
> -			lut[i].blue = b[i];
> -		}
> -		for (i = cmap->start + cmap->len; i < size; i++) {
> -			lut[i].red = r[i];
> -			lut[i].green = g[i];
> -			lut[i].blue = b[i];
> -		}
> -	}
> -
> -	for (i = 0; i < cmap->len; i++) {
> -		lut[cmap->start + i].red = cmap->red[i];
> -		lut[cmap->start + i].green = cmap->green[i];
> -		lut[cmap->start + i].blue = cmap->blue[i];
> -	}
> -
> -	return gamma_lut;
> -}
> -
>  static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
>  {
>  	struct drm_fb_helper *fb_helper = info->par;
>  	struct drm_device *dev = fb_helper->dev;
>  	struct drm_property_blob *gamma_lut = NULL;
>  	struct drm_modeset_acquire_ctx ctx;
> -	struct drm_crtc_state *crtc_state;
>  	struct drm_atomic_state *state;
>  	struct drm_mode_set *modeset;
>  	struct drm_crtc *crtc;
>  	u16 *r, *g, *b;
> -	bool replaced;
>  	int ret = 0;
>  
>  	drm_modeset_acquire_init(&ctx, 0);
> @@ -1468,18 +1519,9 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
>  			goto out_state;
>  		}
>  
> -		crtc_state = drm_atomic_get_crtc_state(state, crtc);
> -		if (IS_ERR(crtc_state)) {
> -			ret = PTR_ERR(crtc_state);
> +		ret = setcmap_crtc_atomic(state, crtc, gamma_lut);
> +		if (ret)
>  			goto out_state;
> -		}
> -
> -		replaced  = drm_property_replace_blob(&crtc_state->degamma_lut,
> -						      NULL);
> -		replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
> -		replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
> -						      gamma_lut);
> -		crtc_state->color_mgmt_changed |= replaced;
>  	}
>  
>  	ret = drm_atomic_commit(state);
> @@ -1498,6 +1540,11 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
>  		memcpy(b + cmap->start, cmap->blue, cmap->len * sizeof(*b));
>  	}

The above "update legacy color table" stuff is missing from the
restore_fbdev_mode_atomic version. Unify more, i.e. maybe convert
setcmap_atomic to just update the property in fb_helper->gamma_lut, and
then call into restore_fbdev_mode_atomic to do all of the heavy lifting?

Or maybe we should push this into
drm_atomic_helper_update_legacy_modeset_state(), but that doesn't quite
work because locking rules are silly :-/ Or teach the gamma_get ioctl to
look at atomic and ditch this, dunno.
-Daniel

>  
> +	if (gamma_lut)
> +		drm_property_blob_get(gamma_lut);
> +	drm_property_blob_put(fb_helper->gamma_lut);
> +	fb_helper->gamma_lut = gamma_lut;
> +
>  out_state:
>  	if (ret == -EDEADLK)
>  		goto backoff;
> diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
> index 6b334f4d8a22..9c797346ede4 100644
> --- a/include/drm/drm_fb_helper.h
> +++ b/include/drm/drm_fb_helper.h
> @@ -155,6 +155,13 @@ struct drm_fb_helper {
>  	struct work_struct dirty_work;
>  	struct work_struct resume_work;
>  
> +	/**
> +	 * @gamma_lut:
> +	 *
> +	 * Current gamma_lut.
> +	 */
> +	struct drm_property_blob *gamma_lut;
> +
>  	/**
>  	 * @lock:
>  	 *
> -- 
> 2.21.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2019-06-07 18:40 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-07 16:26 [PATCH 1/4] drm/fb-helper: Do not assume drm_mode_create_from_cmdline_mode() can't fail Ville Syrjala
2019-06-07 16:26 ` [PATCH 2/4] drm: Refuse to create zero width/height cmdline modes Ville Syrjala
2019-06-07 18:27   ` Daniel Vetter
2019-06-07 16:26 ` [PATCH 3/4] drm/fb-helper: Set up gamma_lut during restore_fbdev_mode_atomic() Ville Syrjala
2019-06-07 18:40   ` Daniel Vetter [this message]
2019-06-11 17:50     ` [Intel-gfx] " Ville Syrjälä
2019-06-11 17:55       ` Daniel Vetter
2019-06-11 18:08         ` Ville Syrjälä
2019-06-07 16:26 ` [PATCH 4/4] drm/i915: Throw away the BIOS fb if has the wrong depth/bpp Ville Syrjala
2019-06-07 18:43   ` Daniel Vetter
2019-06-11 17:51     ` Ville Syrjälä
2019-06-07 16:49 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [1/4] drm/fb-helper: Do not assume drm_mode_create_from_cmdline_mode() can't fail Patchwork
2019-06-07 17:53 ` ✗ Fi.CI.BAT: failure " Patchwork
2019-06-07 18:21 ` [PATCH 1/4] " Daniel Vetter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190607184015.GN21222@phenom.ffwll.local \
    --to=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=ville.syrjala@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.