All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ville Syrjala <ville.syrjala@linux.intel.com>
To: dri-devel@lists.freedesktop.org
Cc: intel-gfx@lists.freedesktop.org
Subject: [PATCH 3/4] drm/fb-helper: Set up gamma_lut during restore_fbdev_mode_atomic()
Date: Fri,  7 Jun 2019 19:26:10 +0300	[thread overview]
Message-ID: <20190607162611.23514-3-ville.syrjala@linux.intel.com> (raw)
In-Reply-To: <20190607162611.23514-1-ville.syrjala@linux.intel.com>

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);
+
 	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;
 
 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));
 	}
 
+	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

  parent reply	other threads:[~2019-06-07 16:26 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 ` Ville Syrjala [this message]
2019-06-07 18:40   ` [PATCH 3/4] drm/fb-helper: Set up gamma_lut during restore_fbdev_mode_atomic() Daniel Vetter
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=20190607162611.23514-3-ville.syrjala@linux.intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /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.