From 327097930d655de5964fcb843b2b412ab68a9bac Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 29 Feb 2016 11:21:10 +0800 Subject: [PATCH 01/27] drm/crtc: Use drm_mode_object_put() in __drm_framebuffer_unregister() The function __drm_framebuffer_unregister() has boilerplate code to drop idr reference. Let's replace it with drm_mode_object_put() to simplify the code. Signed-off-by: Liu Ying Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1456716070-2602-1-git-send-email-gnuiyl@gmail.com --- drivers/gpu/drm/drm_crtc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 65258acddb90..579505c0a498 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -430,9 +430,7 @@ EXPORT_SYMBOL(drm_framebuffer_init); static void __drm_framebuffer_unregister(struct drm_device *dev, struct drm_framebuffer *fb) { - mutex_lock(&dev->mode_config.idr_mutex); - idr_remove(&dev->mode_config.crtc_idr, fb->base.id); - mutex_unlock(&dev->mode_config.idr_mutex); + drm_mode_object_put(dev, &fb->base); fb->base.id = 0; } From 6ab520a2a105abbd275c4814ac0d61d36b1db4fe Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 24 Feb 2016 09:37:28 +0100 Subject: [PATCH 02/27] drm/atomic: Clean up update_output_state. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the addition of crtc_state->connector_mask other connectors from different crtc's aren't needed any more to determine if a crtc has connectors, so only call add_affected_connectors on the target crtc. This allows a cleanup to first remove all current connectors, then add all set->connectors to the target crtc. Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1456303053-28806-2-git-send-email-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/drm_atomic_helper.c | 41 ++++++++++++----------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2b430b05f35d..ddcfc8efe59e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1761,28 +1761,18 @@ static int update_output_state(struct drm_atomic_state *state, struct drm_crtc_state *crtc_state; struct drm_connector *connector; struct drm_connector_state *conn_state; - int ret, i, j; + int ret, i; ret = drm_modeset_lock(&dev->mode_config.connection_mutex, state->acquire_ctx); if (ret) return ret; - /* First grab all affected connector/crtc states. */ - for (i = 0; i < set->num_connectors; i++) { - conn_state = drm_atomic_get_connector_state(state, - set->connectors[i]); - if (IS_ERR(conn_state)) - return PTR_ERR(conn_state); - } + /* First disable all connectors on the target crtc. */ + ret = drm_atomic_add_affected_connectors(state, set->crtc); + if (ret) + return ret; - for_each_crtc_in_state(state, crtc, crtc_state, i) { - ret = drm_atomic_add_affected_connectors(state, crtc); - if (ret) - return ret; - } - - /* Then recompute connector->crtc links and crtc enabling state. */ for_each_connector_in_state(state, connector, conn_state, i) { if (conn_state->crtc == set->crtc) { ret = drm_atomic_set_crtc_for_connector(conn_state, @@ -1790,16 +1780,19 @@ static int update_output_state(struct drm_atomic_state *state, if (ret) return ret; } + } - for (j = 0; j < set->num_connectors; j++) { - if (set->connectors[j] == connector) { - ret = drm_atomic_set_crtc_for_connector(conn_state, - set->crtc); - if (ret) - return ret; - break; - } - } + /* Then set all connectors from set->connectors on the target crtc */ + for (i = 0; i < set->num_connectors; i++) { + conn_state = drm_atomic_get_connector_state(state, + set->connectors[i]); + if (IS_ERR(conn_state)) + return PTR_ERR(conn_state); + + ret = drm_atomic_set_crtc_for_connector(conn_state, + set->crtc); + if (ret) + return ret; } for_each_crtc_in_state(state, crtc, crtc_state, i) { From 9459545b9c966bd221e6e3129b635a4b0a9cf6c2 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 24 Feb 2016 09:37:29 +0100 Subject: [PATCH 03/27] drm/atomic: Pass connector and state to update_connector_routing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Minor cleanup, connector and connector_state are always non-NULL here. Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1456303053-28806-3-git-send-email-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/drm_atomic_helper.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ddcfc8efe59e..ed28ca1fc494 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -215,22 +215,16 @@ steal_encoder(struct drm_atomic_state *state, } static int -update_connector_routing(struct drm_atomic_state *state, int conn_idx) +update_connector_routing(struct drm_atomic_state *state, + struct drm_connector *connector, + struct drm_connector_state *connector_state) { const struct drm_connector_helper_funcs *funcs; struct drm_encoder *new_encoder; struct drm_crtc *encoder_crtc; - struct drm_connector *connector; - struct drm_connector_state *connector_state; struct drm_crtc_state *crtc_state; int idx, ret; - connector = state->connectors[conn_idx]; - connector_state = state->connector_states[conn_idx]; - - if (!connector) - return 0; - DRM_DEBUG_ATOMIC("Updating routing for [CONNECTOR:%d:%s]\n", connector->base.id, connector->name); @@ -494,7 +488,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, * drivers must set crtc->mode_changed themselves when connector * properties need to be updated. */ - ret = update_connector_routing(state, i); + ret = update_connector_routing(state, connector, + connector_state); if (ret) return ret; } From 3382553d504c322d10b791d6a964413b215cccfc Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:16:51 +0000 Subject: [PATCH 04/27] drm/cirrus: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/5a3c41fed15847549f9bdeae89b72705b4756cc4.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/cirrus/cirrus_mode.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 432ce9440e09..d3d8d7bfcc57 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -91,18 +91,6 @@ static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode) WREG_GFX(0xe, gr0e); } -/* - * The core passes the desired mode to the CRTC code to see whether any - * CRTC-specific modifications need to be made to it. We're in a position - * to just pass that straight through, so this does nothing - */ -static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset) { struct cirrus_device *cdev = crtc->dev->dev_private; @@ -372,7 +360,6 @@ static const struct drm_crtc_funcs cirrus_crtc_funcs = { static const struct drm_crtc_helper_funcs cirrus_helper_funcs = { .dpms = cirrus_crtc_dpms, - .mode_fixup = cirrus_crtc_mode_fixup, .mode_set = cirrus_crtc_mode_set, .mode_set_base = cirrus_crtc_mode_set_base, .prepare = cirrus_crtc_prepare, From 2a1dc26bdb68b0694409fbf375612a43dd255074 Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:17:20 +0000 Subject: [PATCH 05/27] drm/mgag200: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/3d089c84bcb1aafd485d4944ad472f9843c38eaf.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/mgag200/mgag200_mode.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index af8b4c19cf15..14e64e08909e 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -92,18 +92,6 @@ static inline void mga_wait_busy(struct mga_device *mdev) } while ((status & 0x01) && time_before(jiffies, timeout)); } -/* - * The core passes the desired mode to the CRTC code to see whether any - * CRTC-specific modifications need to be made to it. We're in a position - * to just pass that straight through, so this does nothing - */ -static bool mga_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - #define P_ARRAY_SIZE 9 static int mga_g200se_set_plls(struct mga_device *mdev, long clock) @@ -1410,7 +1398,6 @@ static const struct drm_crtc_funcs mga_crtc_funcs = { static const struct drm_crtc_helper_funcs mga_helper_funcs = { .disable = mga_crtc_disable, .dpms = mga_crtc_dpms, - .mode_fixup = mga_crtc_mode_fixup, .mode_set = mga_crtc_mode_set, .mode_set_base = mga_crtc_mode_set_base, .prepare = mga_crtc_prepare, From 1323963f96d30e15fa6972511048fe90bc15c958 Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:17:33 +0000 Subject: [PATCH 06/27] drm/udl: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/11327d1a3c3b6623064f6d82efa96e7993f77f38.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/udl/udl_modeset.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 160ef2a08b89..b87afee44995 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -279,14 +279,6 @@ static void udl_crtc_dpms(struct drm_crtc *crtc, int mode) } -static bool udl_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) - -{ - return true; -} - #if 0 static int udl_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, @@ -402,7 +394,6 @@ static void udl_crtc_commit(struct drm_crtc *crtc) static const struct drm_crtc_helper_funcs udl_helper_funcs = { .dpms = udl_crtc_dpms, - .mode_fixup = udl_crtc_mode_fixup, .mode_set = udl_crtc_mode_set, .prepare = udl_crtc_prepare, .commit = udl_crtc_commit, From afe7ef916652ec34fb35a038f6faeafef98c988a Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:17:45 +0000 Subject: [PATCH 07/27] drm/gma: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Signed-off-by: Daniel Vetter --- drivers/gpu/drm/gma500/cdv_intel_display.c | 13 ++++++------- drivers/gpu/drm/gma500/gma_display.c | 7 ------- drivers/gpu/drm/gma500/gma_display.h | 3 --- drivers/gpu/drm/gma500/mdfld_intel_display.c | 2 -- drivers/gpu/drm/gma500/oaktrail_crtc.c | 1 - drivers/gpu/drm/gma500/psb_intel_display.c | 1 - 6 files changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index 6126546295e9..17db4b4749d5 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -116,7 +116,7 @@ static const struct gma_limit_t cdv_intel_limits[] = { .p1 = {.min = 1, .max = 10}, .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10}, .find_pll = cdv_intel_find_dp_pll, - } + } }; #define _wait_for(COND, MS, W) ({ \ @@ -245,7 +245,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, /* We don't know what the other fields of these regs are, so * leave them in place. */ - /* + /* * The BIT 14:13 of 0x8010/0x8030 is used to select the ref clk * for the pipe A/B. Display spec 1.06 has wrong definition. * Correct definition is like below: @@ -256,7 +256,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, * * if DPLLA sets 01 and DPLLB sets 02, both use clk from DPLLA * - */ + */ ret = cdv_sb_read(dev, ref_sfr, &ref_value); if (ret) return ret; @@ -646,7 +646,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, * for DP/eDP. When using SSC clock, the ref clk is 100MHz.Otherwise * it will be 27MHz. From the VBIOS code it seems that the pipe A choose * 27MHz for DP/eDP while the Pipe B chooses the 100MHz. - */ + */ if (pipe == 0) refclk = 27000; else @@ -659,7 +659,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, } drm_mode_debug_printmodeline(adjusted_mode); - + limit = gma_crtc->clock_funcs->limit(crtc, refclk); ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, @@ -721,7 +721,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, pipeconf |= PIPE_6BPC; } else pipeconf |= PIPE_8BPC; - + /* Set up the display plane register */ dspcntr = DISPPLANE_GAMMA_ENABLE; @@ -974,7 +974,6 @@ struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev, const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = { .dpms = gma_crtc_dpms, - .mode_fixup = gma_crtc_mode_fixup, .mode_set = cdv_intel_crtc_mode_set, .mode_set_base = gma_pipe_set_base, .prepare = gma_crtc_prepare, diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index 927082148d4d..5bf765de2517 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -478,13 +478,6 @@ int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) return 0; } -bool gma_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - void gma_crtc_prepare(struct drm_crtc *crtc) { const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; diff --git a/drivers/gpu/drm/gma500/gma_display.h b/drivers/gpu/drm/gma500/gma_display.h index 78b9f986a6e5..b2491c65f053 100644 --- a/drivers/gpu/drm/gma500/gma_display.h +++ b/drivers/gpu/drm/gma500/gma_display.h @@ -75,9 +75,6 @@ extern void gma_crtc_load_lut(struct drm_crtc *crtc); extern void gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, u32 start, u32 size); extern void gma_crtc_dpms(struct drm_crtc *crtc, int mode); -extern bool gma_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode); extern void gma_crtc_prepare(struct drm_crtc *crtc); extern void gma_crtc_commit(struct drm_crtc *crtc); extern void gma_crtc_disable(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c index acd38344b302..92e3f93ee682 100644 --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c @@ -1026,10 +1026,8 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc, const struct drm_crtc_helper_funcs mdfld_helper_funcs = { .dpms = mdfld_crtc_dpms, - .mode_fixup = gma_crtc_mode_fixup, .mode_set = mdfld_crtc_mode_set, .mode_set_base = mdfld__intel_pipe_set_base, .prepare = gma_crtc_prepare, .commit = gma_crtc_commit, }; - diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index 1048f0c7c6ce..da9fd34b9550 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -657,7 +657,6 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc, const struct drm_crtc_helper_funcs oaktrail_helper_funcs = { .dpms = oaktrail_crtc_dpms, - .mode_fixup = gma_crtc_mode_fixup, .mode_set = oaktrail_crtc_mode_set, .mode_set_base = oaktrail_pipe_set_base, .prepare = gma_crtc_prepare, diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index dcdbc37e55e1..398015be87e4 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -430,7 +430,6 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { .dpms = gma_crtc_dpms, - .mode_fixup = gma_crtc_mode_fixup, .mode_set = psb_intel_crtc_mode_set, .mode_set_base = gma_pipe_set_base, .prepare = gma_crtc_prepare, From 1ed3b5730afc7d59bb7594a8e218af4534419939 Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:18:00 +0000 Subject: [PATCH 08/27] drm/rcar-du: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/becab4ff666eca77162e5cd978087f2d3fb3e308.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 51e9e8ce551a..d9f06cc361fa 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -491,14 +491,6 @@ static void rcar_du_crtc_disable(struct drm_crtc *crtc) rcrtc->outputs = 0; } -static bool rcar_du_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - /* TODO Fixup modes */ - return true; -} - static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { @@ -531,7 +523,6 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs crtc_helper_funcs = { - .mode_fixup = rcar_du_crtc_mode_fixup, .disable = rcar_du_crtc_disable, .enable = rcar_du_crtc_enable, .atomic_begin = rcar_du_crtc_atomic_begin, From 4091e54e846c4813ef93f2471a0f358d07ca9510 Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:18:12 +0000 Subject: [PATCH 09/27] drm/omapdrm: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/101f043d5fa747291c09ae765bac4d55c6e39988.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/omapdrm/omap_crtc.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index d38fcbcc43a8..483acdbd664b 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -330,13 +330,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc) kfree(omap_crtc); } -static bool omap_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static void omap_crtc_enable(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); @@ -451,7 +444,6 @@ static const struct drm_crtc_funcs omap_crtc_funcs = { }; static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { - .mode_fixup = omap_crtc_mode_fixup, .mode_set_nofb = omap_crtc_mode_set_nofb, .disable = omap_crtc_disable, .enable = omap_crtc_enable, From b205b8ebc56cdee75239399cd4dd880d6919c35b Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:18:26 +0000 Subject: [PATCH 10/27] drm/msm/mdp: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Signed-off-by: Daniel Vetter --- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 8 -------- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 8 -------- 2 files changed, 16 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 909d74250de7..38329a617da0 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -147,13 +147,6 @@ static void mdp4_crtc_destroy(struct drm_crtc *crtc) kfree(mdp4_crtc); } -static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - /* statically (for now) map planes to mixer stage (z-order): */ static const int idxs[] = { [VG1] = 1, @@ -508,7 +501,6 @@ static const struct drm_crtc_funcs mdp4_crtc_funcs = { }; static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = { - .mode_fixup = mdp4_crtc_mode_fixup, .mode_set_nofb = mdp4_crtc_mode_set_nofb, .disable = mdp4_crtc_disable, .enable = mdp4_crtc_enable, diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 46682aa8870c..d6b45eb57d4f 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -185,13 +185,6 @@ static void mdp5_crtc_destroy(struct drm_crtc *crtc) kfree(mdp5_crtc); } -static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - /* * blend_setup() - blend all the planes of a CRTC * @@ -634,7 +627,6 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = { }; static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { - .mode_fixup = mdp5_crtc_mode_fixup, .mode_set_nofb = mdp5_crtc_mode_set_nofb, .disable = mdp5_crtc_disable, .enable = mdp5_crtc_enable, From 4676be11e0b83376f2e3f4799479176a876c569e Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:18:40 +0000 Subject: [PATCH 11/27] drm/shmobile: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter --- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index 27342fd76e90..88643ab160bf 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -359,13 +359,6 @@ static void shmob_drm_crtc_dpms(struct drm_crtc *crtc, int mode) scrtc->dpms = mode; } -static bool shmob_drm_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static void shmob_drm_crtc_mode_prepare(struct drm_crtc *crtc) { shmob_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); @@ -431,7 +424,6 @@ static int shmob_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, static const struct drm_crtc_helper_funcs crtc_helper_funcs = { .dpms = shmob_drm_crtc_dpms, - .mode_fixup = shmob_drm_crtc_mode_fixup, .prepare = shmob_drm_crtc_mode_prepare, .commit = shmob_drm_crtc_mode_commit, .mode_set = shmob_drm_crtc_mode_set, From 8a2fa38fddd33a5a22a430545720f7f81d88e8db Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:18:53 +0000 Subject: [PATCH 12/27] drm/sti: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/08d27e27582fb2daa48555ab542245c6cf0a2268.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/sti/sti_crtc.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c index de11c7cfb02f..e04deedabd4a 100644 --- a/drivers/gpu/drm/sti/sti_crtc.c +++ b/drivers/gpu/drm/sti/sti_crtc.c @@ -51,14 +51,6 @@ static void sti_crtc_disabling(struct drm_crtc *crtc) mixer->status = STI_MIXER_DISABLING; } -static bool sti_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - /* accept the provided drm_display_mode, do not fix it up */ - return true; -} - static int sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode) { @@ -229,7 +221,6 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { .enable = sti_crtc_enable, .disable = sti_crtc_disabling, - .mode_fixup = sti_crtc_mode_fixup, .mode_set = drm_helper_crtc_mode_set, .mode_set_nofb = sti_crtc_mode_set_nofb, .mode_set_base = drm_helper_crtc_mode_set_base, From 074b962428d4280176dfd7c3a957b94a08b092af Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:19:06 +0000 Subject: [PATCH 13/27] drm/atmel-hlcdc: remove optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Acked-by: Boris Brezillon Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/e4bdb8552c245f8b73084b93da60460a00f7798c.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 9863291a9a54..58c4f785cf84 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -121,13 +121,6 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c) cfg); } -static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static void atmel_hlcdc_crtc_disable(struct drm_crtc *c) { struct drm_device *dev = c->dev; @@ -261,7 +254,6 @@ static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc, } static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = { - .mode_fixup = atmel_hlcdc_crtc_mode_fixup, .mode_set = drm_helper_crtc_mode_set, .mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb, .mode_set_base = drm_helper_crtc_mode_set_base, @@ -349,4 +341,3 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev) atmel_hlcdc_crtc_destroy(&crtc->base); return ret; } - From c57d860f4c863cc7b3e62e21adf17f2c7055a767 Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:19:19 +0000 Subject: [PATCH 14/27] drm/nouveau/dispnv04: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/897eae438eec566078b1872d7654c4863e4e4e57.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 6f04397d43a7..55ccbf006b5e 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -227,13 +227,6 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); } -static bool -nv_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static void nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) { @@ -1093,7 +1086,6 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { .dpms = nv_crtc_dpms, .prepare = nv_crtc_prepare, .commit = nv_crtc_commit, - .mode_fixup = nv_crtc_mode_fixup, .mode_set = nv_crtc_mode_set, .mode_set_base = nv04_crtc_mode_set_base, .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, From f40f917a87daf13c7b494910c0af4c686b0a65eb Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:19:32 +0000 Subject: [PATCH 15/27] drm/virtio: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/ae865f0deca4e64a0f47f2d2d14b54ff00c0672e.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/virtio/virtgpu_display.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 429aa311685a..4854dac87e24 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -237,13 +237,6 @@ virtio_gpu_framebuffer_init(struct drm_device *dev, return 0; } -static bool virtio_gpu_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -277,7 +270,6 @@ static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { .enable = virtio_gpu_crtc_enable, .disable = virtio_gpu_crtc_disable, - .mode_fixup = virtio_gpu_crtc_mode_fixup, .mode_set_nofb = virtio_gpu_crtc_mode_set_nofb, .atomic_check = virtio_gpu_crtc_atomic_check, }; From de3aa0aae639560dfe394aecdcb1f10c79c96b7a Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:19:46 +0000 Subject: [PATCH 16/27] drm/fsl-dcu: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/a9827a57b25509dae29c0e8d09a9063a11970647.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c index 7574db2da413..4ed7798533f9 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c @@ -62,13 +62,6 @@ static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc) DCU_UPDATE_MODE_READREG); } -static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -127,7 +120,6 @@ static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = { .atomic_flush = fsl_dcu_drm_crtc_atomic_flush, .disable = fsl_dcu_drm_disable_crtc, .enable = fsl_dcu_drm_crtc_enable, - .mode_fixup = fsl_dcu_drm_crtc_mode_fixup, .mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb, }; From 7e1f9e890317ed91c860889d7a3668ba5ef37e64 Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:20:02 +0000 Subject: [PATCH 17/27] drm/bochs: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/40a78cafba2cd5b391d244e806613192b3a31413.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/bochs/bochs_kms.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 317c27f2a50b..96926f09e0c9 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -30,13 +30,6 @@ static void bochs_crtc_dpms(struct drm_crtc *crtc, int mode) } } -static bool bochs_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { @@ -135,7 +128,6 @@ static const struct drm_crtc_funcs bochs_crtc_funcs = { static const struct drm_crtc_helper_funcs bochs_helper_funcs = { .dpms = bochs_crtc_dpms, - .mode_fixup = bochs_crtc_mode_fixup, .mode_set = bochs_crtc_mode_set, .mode_set_base = bochs_crtc_mode_set_base, .prepare = bochs_crtc_prepare, From b282e969b19997c8ff03f8ef9a6e765e7199093a Mon Sep 17 00:00:00 2001 From: Carlos Palminha Date: Tue, 16 Feb 2016 14:20:14 +0000 Subject: [PATCH 18/27] drm/ast: removed optional dummy crtc mode_fixup function. This patch set nukes all the dummy crtc mode_fixup implementations. (made on top of Daniel topic/drm-misc branch) Signed-off-by: Carlos Palminha Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/0f8f948babd93fce8523253b0f525446e2f565db.1455630967.git.palminha@synopsys.com --- drivers/gpu/drm/ast/ast_mode.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index f221e2dc1b0d..a965e7e8ad6e 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -497,13 +497,6 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) } } -static bool ast_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - /* ast is different - we will force move buffers out of VRAM */ static int ast_crtc_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *fb, @@ -617,7 +610,6 @@ static void ast_crtc_commit(struct drm_crtc *crtc) static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { .dpms = ast_crtc_dpms, - .mode_fixup = ast_crtc_mode_fixup, .mode_set = ast_crtc_mode_set, .mode_set_base = ast_crtc_mode_set_base, .disable = ast_crtc_disable, From ff19b7867fcaa00638018e116c63aba75c4b07ba Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 3 Mar 2016 10:17:38 +0100 Subject: [PATCH 19/27] drm/atomic: Always call steal_encoder, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no need to have a separate function to get the crtc which is stolen, this can already be found when actually stealing the encoder. drm_for_each_connector already checks for connection_mutex, so use that macro now. Changes since v1: - Do not check for NULL crtc in connector_state, this may happen when a crtc is disabled and its encoder stolen. - Because of this, use connector->state->crtc instead of conn_state->crtc. Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1456996662-8704-4-git-send-email-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/drm_atomic_helper.c | 74 ++++++++--------------------- 1 file changed, 20 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ed28ca1fc494..32f6f57fc66e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -106,25 +106,6 @@ check_pending_encoder_assignment(struct drm_atomic_state *state, return true; } -static struct drm_crtc * -get_current_crtc_for_encoder(struct drm_device *dev, - struct drm_encoder *encoder) -{ - struct drm_mode_config *config = &dev->mode_config; - struct drm_connector *connector; - - WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); - - drm_for_each_connector(connector, dev) { - if (connector->state->best_encoder != encoder) - continue; - - return connector->state->crtc; - } - - return NULL; -} - static void set_best_encoder(struct drm_atomic_state *state, struct drm_connector_state *conn_state, @@ -168,38 +149,18 @@ set_best_encoder(struct drm_atomic_state *state, static int steal_encoder(struct drm_atomic_state *state, - struct drm_encoder *encoder, - struct drm_crtc *encoder_crtc) + struct drm_encoder *encoder) { - struct drm_mode_config *config = &state->dev->mode_config; struct drm_crtc_state *crtc_state; struct drm_connector *connector; struct drm_connector_state *connector_state; - /* - * We can only steal an encoder coming from a connector, which means we - * must already hold the connection_mutex. - */ - WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); + drm_for_each_connector(connector, state->dev) { + struct drm_crtc *encoder_crtc; - DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n", - encoder->base.id, encoder->name, - encoder_crtc->base.id, encoder_crtc->name); - - crtc_state = drm_atomic_get_crtc_state(state, encoder_crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); - - crtc_state->connectors_changed = true; - - list_for_each_entry(connector, &config->connector_list, head) { if (connector->state->best_encoder != encoder) continue; - DRM_DEBUG_ATOMIC("Stealing encoder from [CONNECTOR:%d:%s]\n", - connector->base.id, - connector->name); - connector_state = drm_atomic_get_connector_state(state, connector); if (IS_ERR(connector_state)) @@ -208,7 +169,18 @@ steal_encoder(struct drm_atomic_state *state, if (connector_state->best_encoder != encoder) continue; + encoder_crtc = connector->state->crtc; + + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n", + encoder->base.id, encoder->name, + encoder_crtc->base.id, encoder_crtc->name); + set_best_encoder(state, connector_state, NULL); + + crtc_state = drm_atomic_get_existing_crtc_state(state, encoder_crtc); + crtc_state->connectors_changed = true; + + return 0; } return 0; @@ -221,7 +193,6 @@ update_connector_routing(struct drm_atomic_state *state, { const struct drm_connector_helper_funcs *funcs; struct drm_encoder *new_encoder; - struct drm_crtc *encoder_crtc; struct drm_crtc_state *crtc_state; int idx, ret; @@ -299,17 +270,12 @@ update_connector_routing(struct drm_atomic_state *state, return -EINVAL; } - encoder_crtc = get_current_crtc_for_encoder(state->dev, - new_encoder); - - if (encoder_crtc) { - ret = steal_encoder(state, new_encoder, encoder_crtc); - if (ret) { - DRM_DEBUG_ATOMIC("Encoder stealing failed for [CONNECTOR:%d:%s]\n", - connector->base.id, - connector->name); - return ret; - } + ret = steal_encoder(state, new_encoder); + if (ret) { + DRM_DEBUG_ATOMIC("Encoder stealing failed for [CONNECTOR:%d:%s]\n", + connector->base.id, + connector->name); + return ret; } if (WARN_ON(!connector_state->crtc)) From 40616a26d1c68e4c80e2358a02297ba492f4cc17 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 3 Mar 2016 10:17:39 +0100 Subject: [PATCH 20/27] drm/atomic: Handle encoder stealing from set_config better. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of failing with -EINVAL when conflicting encoders are found, the legacy set_config will disable other connectors when encoders conflict. With the previous commit this becomes a lot easier to implement. set_config only adds connectors to the state that are modified, and because of the previous commit that calls add_affected_connectors only on set->crtc it means any connector not part of the modeset can be stolen from. We disable the connector in that case, and possibly the crtc if required. Atomic modeset itself still doesn't allow encoder stealing, the results would be too unpredictable. Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1456996662-8704-5-git-send-email-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/drm_atomic_helper.c | 69 +++++++++++++++++++++++++++++ include/drm/drm_crtc.h | 2 + 2 files changed, 71 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 32f6f57fc66e..9fab9860999b 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -86,6 +86,68 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, } } +static int disable_conflicting_connectors(struct drm_atomic_state *state) +{ + struct drm_connector_state *conn_state; + struct drm_connector *connector; + struct drm_encoder *encoder; + unsigned encoder_mask = 0; + int i, ret; + + for_each_connector_in_state(state, connector, conn_state, i) { + const struct drm_connector_helper_funcs *funcs = connector->helper_private; + struct drm_encoder *new_encoder; + + if (!conn_state->crtc) + continue; + + if (funcs->atomic_best_encoder) + new_encoder = funcs->atomic_best_encoder(connector, conn_state); + else + new_encoder = funcs->best_encoder(connector); + + if (new_encoder) + encoder_mask |= 1 << drm_encoder_index(new_encoder); + } + + drm_for_each_connector(connector, state->dev) { + struct drm_crtc_state *crtc_state; + + if (drm_atomic_get_existing_connector_state(state, connector)) + continue; + + encoder = connector->state->best_encoder; + if (!encoder || !(encoder_mask & (1 << drm_encoder_index(encoder)))) + continue; + + conn_state = drm_atomic_get_connector_state(state, connector); + if (IS_ERR(conn_state)) + return PTR_ERR(conn_state); + + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], disabling [CONNECTOR:%d:%s]\n", + encoder->base.id, encoder->name, + conn_state->crtc->base.id, conn_state->crtc->name, + connector->base.id, connector->name); + + crtc_state = drm_atomic_get_existing_crtc_state(state, conn_state->crtc); + + ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); + if (ret) + return ret; + + if (!crtc_state->connector_mask) { + ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, + NULL); + if (ret < 0) + return ret; + + crtc_state->active = false; + } + } + + return 0; +} + static bool check_pending_encoder_assignment(struct drm_atomic_state *state, struct drm_encoder *new_encoder) @@ -448,6 +510,12 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, } } + if (state->legacy_set_config) { + ret = disable_conflicting_connectors(state); + if (ret) + return ret; + } + for_each_connector_in_state(state, connector, connector_state, i) { /* * This only sets crtc->mode_changed for routing changes, @@ -1796,6 +1864,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set) if (!state) return -ENOMEM; + state->legacy_set_config = true; state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); retry: ret = __drm_atomic_helper_set_config(set, state); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 8c7fb3d0f9d0..75b28deeaf24 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1676,6 +1676,7 @@ struct drm_bridge { * @dev: parent DRM device * @allow_modeset: allow full modeset * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics + * @legacy_set_config: Disable conflicting encoders instead of failing with -EINVAL. * @planes: pointer to array of plane pointers * @plane_states: pointer to array of plane states pointers * @crtcs: pointer to array of CRTC pointers @@ -1689,6 +1690,7 @@ struct drm_atomic_state { struct drm_device *dev; bool allow_modeset : 1; bool legacy_cursor_update : 1; + bool legacy_set_config : 1; struct drm_plane **planes; struct drm_plane_state **plane_states; struct drm_crtc **crtcs; From 8248b65df653c0a536bdd64f8a6c8bb150bfdd60 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 3 Mar 2016 10:17:40 +0100 Subject: [PATCH 21/27] drm/atomic: Handle encoder assignment conflicts in a separate check, v3. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current check doesn't handle the case where we don't steal an encoder, but keep it on the current connector. If we repurpose disable_conflicting_encoders to do the checking, we just have to reject the ones that conflict. Changes since v1: - Return early with empty encoder_mask, drm_for_each_connector requires connection_mutex held. Changes since v2: - Add comments for the loops. Signed-off-by: Maarten Lankhorst Testcase: kms_setmode.invalid-clone-single-crtc-stealing Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1456996662-8704-6-git-send-email-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/drm_atomic_helper.c | 77 ++++++++++++++++------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9fab9860999b..52c03cea6cf9 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -86,7 +86,8 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, } } -static int disable_conflicting_connectors(struct drm_atomic_state *state) +static int handle_conflicting_encoders(struct drm_atomic_state *state, + bool disable_conflicting_encoders) { struct drm_connector_state *conn_state; struct drm_connector *connector; @@ -94,6 +95,11 @@ static int disable_conflicting_connectors(struct drm_atomic_state *state) unsigned encoder_mask = 0; int i, ret; + /* + * First loop, find all newly assigned encoders from the connectors + * part of the state. If the same encoder is assigned to multiple + * connectors bail out. + */ for_each_connector_in_state(state, connector, conn_state, i) { const struct drm_connector_helper_funcs *funcs = connector->helper_private; struct drm_encoder *new_encoder; @@ -106,10 +112,33 @@ static int disable_conflicting_connectors(struct drm_atomic_state *state) else new_encoder = funcs->best_encoder(connector); - if (new_encoder) + if (new_encoder) { + if (encoder_mask & (1 << drm_encoder_index(new_encoder))) { + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] on [CONNECTOR:%d:%s] already assigned\n", + new_encoder->base.id, new_encoder->name, + connector->base.id, connector->name); + + return -EINVAL; + } + encoder_mask |= 1 << drm_encoder_index(new_encoder); + } } + if (!encoder_mask) + return 0; + + /* + * Second loop, iterate over all connectors not part of the state. + * + * If a conflicting encoder is found and disable_conflicting_encoders + * is not set, an error is returned. Userspace can provide a solution + * through the atomic ioctl. + * + * If the flag is set conflicting connectors are removed from the crtc + * and the crtc is disabled if no encoder is left. This preserves + * compatibility with the legacy set_config behavior. + */ drm_for_each_connector(connector, state->dev) { struct drm_crtc_state *crtc_state; @@ -120,6 +149,15 @@ static int disable_conflicting_connectors(struct drm_atomic_state *state) if (!encoder || !(encoder_mask & (1 << drm_encoder_index(encoder)))) continue; + if (!disable_conflicting_encoders) { + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s] by [CONNECTOR:%d:%s]\n", + encoder->base.id, encoder->name, + connector->state->crtc->base.id, + connector->state->crtc->name, + connector->base.id, connector->name); + return -EINVAL; + } + conn_state = drm_atomic_get_connector_state(state, connector); if (IS_ERR(conn_state)) return PTR_ERR(conn_state); @@ -148,26 +186,6 @@ static int disable_conflicting_connectors(struct drm_atomic_state *state) return 0; } -static bool -check_pending_encoder_assignment(struct drm_atomic_state *state, - struct drm_encoder *new_encoder) -{ - struct drm_connector *connector; - struct drm_connector_state *conn_state; - int i; - - for_each_connector_in_state(state, connector, conn_state, i) { - if (conn_state->best_encoder != new_encoder) - continue; - - /* encoder already assigned and we're trying to re-steal it! */ - if (connector->state->best_encoder != conn_state->best_encoder) - return false; - } - - return true; -} - static void set_best_encoder(struct drm_atomic_state *state, struct drm_connector_state *conn_state, @@ -325,13 +343,6 @@ update_connector_routing(struct drm_atomic_state *state, return 0; } - if (!check_pending_encoder_assignment(state, new_encoder)) { - DRM_DEBUG_ATOMIC("Encoder for [CONNECTOR:%d:%s] already assigned\n", - connector->base.id, - connector->name); - return -EINVAL; - } - ret = steal_encoder(state, new_encoder); if (ret) { DRM_DEBUG_ATOMIC("Encoder stealing failed for [CONNECTOR:%d:%s]\n", @@ -510,11 +521,9 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, } } - if (state->legacy_set_config) { - ret = disable_conflicting_connectors(state); - if (ret) - return ret; - } + ret = handle_conflicting_encoders(state, state->legacy_set_config); + if (ret) + return ret; for_each_connector_in_state(state, connector, connector_state, i) { /* From ec5aaa586fe0d826b6e65a60756b9bbf4d93e011 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 3 Mar 2016 10:17:41 +0100 Subject: [PATCH 22/27] drm/atomic: Clean up steal_encoder, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that only encoders can be stolen that are part of the state steal_encoder no longer needs to inspect all connectors, just those that are part of the atomic state. Changes since v1: - Change return value to void, can no longer fail. Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä [danvet: Appease gcc, reported by kbuild.] Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1456996662-8704-7-git-send-email-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/drm_atomic_helper.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 52c03cea6cf9..baa0fc652f43 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -227,25 +227,18 @@ set_best_encoder(struct drm_atomic_state *state, conn_state->best_encoder = encoder; } -static int +static void steal_encoder(struct drm_atomic_state *state, struct drm_encoder *encoder) { struct drm_crtc_state *crtc_state; struct drm_connector *connector; struct drm_connector_state *connector_state; + int i; - drm_for_each_connector(connector, state->dev) { + for_each_connector_in_state(state, connector, connector_state, i) { struct drm_crtc *encoder_crtc; - if (connector->state->best_encoder != encoder) - continue; - - connector_state = drm_atomic_get_connector_state(state, - connector); - if (IS_ERR(connector_state)) - return PTR_ERR(connector_state); - if (connector_state->best_encoder != encoder) continue; @@ -260,10 +253,8 @@ steal_encoder(struct drm_atomic_state *state, crtc_state = drm_atomic_get_existing_crtc_state(state, encoder_crtc); crtc_state->connectors_changed = true; - return 0; + return; } - - return 0; } static int @@ -274,7 +265,7 @@ update_connector_routing(struct drm_atomic_state *state, const struct drm_connector_helper_funcs *funcs; struct drm_encoder *new_encoder; struct drm_crtc_state *crtc_state; - int idx, ret; + int idx; DRM_DEBUG_ATOMIC("Updating routing for [CONNECTOR:%d:%s]\n", connector->base.id, @@ -343,13 +334,7 @@ update_connector_routing(struct drm_atomic_state *state, return 0; } - ret = steal_encoder(state, new_encoder); - if (ret) { - DRM_DEBUG_ATOMIC("Encoder stealing failed for [CONNECTOR:%d:%s]\n", - connector->base.id, - connector->name); - return ret; - } + steal_encoder(state, new_encoder); if (WARN_ON(!connector_state->crtc)) return -EINVAL; From 9b8d1e53f6da63920ba569405b8d57ddbb42a988 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 3 Mar 2016 10:17:42 +0100 Subject: [PATCH 23/27] drm/atomic: Clean up update_connector_routing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit connector_state->crtc can no longer be unset by accident, so that check can be removed. The other code open-codes drm_atomic_get_existing_crtc_state, so use that. Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä [danvet: Resolve tiny conflict due to gcc warning fix on previous patch.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index baa0fc652f43..7a034b231792 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -265,7 +265,6 @@ update_connector_routing(struct drm_atomic_state *state, const struct drm_connector_helper_funcs *funcs; struct drm_encoder *new_encoder; struct drm_crtc_state *crtc_state; - int idx; DRM_DEBUG_ATOMIC("Updating routing for [CONNECTOR:%d:%s]\n", connector->base.id, @@ -273,16 +272,12 @@ update_connector_routing(struct drm_atomic_state *state, if (connector->state->crtc != connector_state->crtc) { if (connector->state->crtc) { - idx = drm_crtc_index(connector->state->crtc); - - crtc_state = state->crtc_states[idx]; + crtc_state = drm_atomic_get_existing_crtc_state(state, connector->state->crtc); crtc_state->connectors_changed = true; } if (connector_state->crtc) { - idx = drm_crtc_index(connector_state->crtc); - - crtc_state = state->crtc_states[idx]; + crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc); crtc_state->connectors_changed = true; } } @@ -336,14 +331,9 @@ update_connector_routing(struct drm_atomic_state *state, steal_encoder(state, new_encoder); - if (WARN_ON(!connector_state->crtc)) - return -EINVAL; - set_best_encoder(state, connector_state, new_encoder); - idx = drm_crtc_index(connector_state->crtc); - - crtc_state = state->crtc_states[idx]; + crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc); crtc_state->connectors_changed = true; DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n", From 5488dc16fde74595a40c5d20ae52d978313f0b4e Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Fri, 26 Feb 2016 17:05:00 +0000 Subject: [PATCH 24/27] drm: introduce pipe color correction properties Patch based on a previous series by Shashank Sharma. This introduces optional properties to enable color correction at the pipe level. It relies on 3 transformations applied to every pixels displayed. First a lookup into a degamma table, then a multiplication of the rgb components by a 3x3 matrix and finally another lookup into a gamma table. The following properties can be added to a pipe : - DEGAMMA_LUT : blob containing degamma LUT - DEGAMMA_LUT_SIZE : number of elements in DEGAMMA_LUT - CTM : transformation matrix applied after the degamma LUT - GAMMA_LUT : blob containing gamma LUT - GAMMA_LUT_SIZE : number of elements in GAMMA_LUT DEGAMMA_LUT_SIZE and GAMMA_LUT_SIZE are read only properties, set by the driver to tell userspace applications what sizes should be the lookup tables in DEGAMMA_LUT and GAMMA_LUT. A helper is also provided so legacy gamma correction is redirected through these new properties. v2: Register LUT size properties as range v3: Fix round in drm_color_lut_get_value() helper More docs on how degamma/gamma properties are used v4: Update contributors v5: Rename CTM_MATRIX property to CTM (Doh!) Add legacy gamma_set atomic helper Describe CTM/LUT acronyms in the kernel doc v6: Fix missing blob unref in drm_atomic_helper_crtc_reset Signed-off-by: Shashank Sharma Signed-off-by: Kumar, Kiran S Signed-off-by: Kausal Malladi Signed-off-by: Lionel Landwerlin Reviewed-by: Matt Roper Acked-by: Rob Bradford [danvet: CrOS maintainers are also happy with the userspacde side: https://codereview.chromium.org/1182063002/ ] Reviewed-by: Daniel Stone Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1456506302-640-4-git-send-email-lionel.g.landwerlin@intel.com --- Documentation/DocBook/gpu.tmpl | 59 ++++++++++++++- drivers/gpu/drm/drm_atomic.c | 88 +++++++++++++++++++++- drivers/gpu/drm/drm_atomic_helper.c | 110 +++++++++++++++++++++++++++- drivers/gpu/drm/drm_crtc.c | 35 +++++++++ drivers/gpu/drm/drm_crtc_helper.c | 33 +++++++++ include/drm/drm_atomic_helper.h | 3 + include/drm/drm_crtc.h | 46 +++++++++++- include/drm/drm_crtc_helper.h | 3 + include/uapi/drm/drm_mode.h | 15 ++++ 9 files changed, 386 insertions(+), 6 deletions(-) diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index fe6b36a2fd98..1692c4dd5487 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl @@ -1816,7 +1816,7 @@ void intel_crt_init(struct drm_device *dev) Description/Restrictions - DRM + DRM Generic “rotation” BITMASK @@ -2068,7 +2068,7 @@ void intel_crt_init(struct drm_device *dev) property to suggest an Y offset for a connector - Optional + Optional “scaling mode” ENUM { "None", "Full", "Center", "Full aspect" } @@ -2092,6 +2092,61 @@ void intel_crt_init(struct drm_device *dev) TBD + “DEGAMMA_LUT” + BLOB + 0 + CRTC + DRM property to set the degamma lookup table + (LUT) mapping pixel data from the framebuffer before it is + given to the transformation matrix. The data is an interpreted + as an array of struct drm_color_lut elements. Hardware might + choose not to use the full precision of the LUT elements nor + use all the elements of the LUT (for example the hardware + might choose to interpolate between LUT[0] and LUT[4]). + + + “DEGAMMA_LUT_SIZE” + RANGE | IMMUTABLE + Min=0, Max=UINT_MAX + CRTC + DRM property to gives the size of the lookup + table to be set on the DEGAMMA_LUT property (the size depends + on the underlying hardware). + + + “CTM” + BLOB + 0 + CRTC + DRM property to set the current + transformation matrix (CTM) apply to pixel data after the + lookup through the degamma LUT and before the lookup through + the gamma LUT. The data is an interpreted as a struct + drm_color_ctm. + + + “GAMMA_LUT” + BLOB + 0 + CRTC + DRM property to set the gamma lookup table + (LUT) mapping pixel data after to the transformation matrix to + data sent to the connector. The data is an interpreted as an + array of struct drm_color_lut elements. Hardware might choose + not to use the full precision of the LUT elements nor use all + the elements of the LUT (for example the hardware might choose + to interpolate between LUT[0] and LUT[4]). + + + “GAMMA_LUT_SIZE” + RANGE | IMMUTABLE + Min=0, Max=UINT_MAX + CRTC + DRM property to gives the size of the lookup + table to be set on the GAMMA_LUT property (the size depends on + the underlying hardware). + + i915 Generic "Broadcast RGB" diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 8fb469c4e4b8..c7e7a955bb1e 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -28,6 +28,7 @@ #include #include +#include #include /** @@ -387,6 +388,59 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, } EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc); +/** + * drm_atomic_replace_property_blob - replace a blob property + * @blob: a pointer to the member blob to be replaced + * @new_blob: the new blob to replace with + * @expected_size: the expected size of the new blob + * @replaced: whether the blob has been replaced + * + * RETURNS: + * Zero on success, error code on failure + */ +static void +drm_atomic_replace_property_blob(struct drm_property_blob **blob, + struct drm_property_blob *new_blob, + bool *replaced) +{ + struct drm_property_blob *old_blob = *blob; + + if (old_blob == new_blob) + return; + + if (old_blob) + drm_property_unreference_blob(old_blob); + if (new_blob) + drm_property_reference_blob(new_blob); + *blob = new_blob; + *replaced = true; + + return; +} + +static int +drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc, + struct drm_property_blob **blob, + uint64_t blob_id, + ssize_t expected_size, + bool *replaced) +{ + struct drm_device *dev = crtc->dev; + struct drm_property_blob *new_blob = NULL; + + if (blob_id != 0) { + new_blob = drm_property_lookup_blob(dev, blob_id); + if (new_blob == NULL) + return -EINVAL; + if (expected_size > 0 && expected_size != new_blob->length) + return -EINVAL; + } + + drm_atomic_replace_property_blob(blob, new_blob, replaced); + + return 0; +} + /** * drm_atomic_crtc_set_property - set property on CRTC * @crtc: the drm CRTC to set a property on @@ -409,6 +463,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct drm_mode_config *config = &dev->mode_config; + bool replaced = false; int ret; if (property == config->prop_active) @@ -419,8 +474,31 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, ret = drm_atomic_set_mode_prop_for_crtc(state, mode); drm_property_unreference_blob(mode); return ret; - } - else if (crtc->funcs->atomic_set_property) + } else if (property == config->degamma_lut_property) { + ret = drm_atomic_replace_property_blob_from_id(crtc, + &state->degamma_lut, + val, + -1, + &replaced); + state->color_mgmt_changed = replaced; + return ret; + } else if (property == config->ctm_property) { + ret = drm_atomic_replace_property_blob_from_id(crtc, + &state->ctm, + val, + sizeof(struct drm_color_ctm), + &replaced); + state->color_mgmt_changed = replaced; + return ret; + } else if (property == config->gamma_lut_property) { + ret = drm_atomic_replace_property_blob_from_id(crtc, + &state->gamma_lut, + val, + -1, + &replaced); + state->color_mgmt_changed = replaced; + return ret; + } else if (crtc->funcs->atomic_set_property) return crtc->funcs->atomic_set_property(crtc, state, property, val); else return -EINVAL; @@ -456,6 +534,12 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc, *val = state->active; else if (property == config->prop_mode_id) *val = (state->mode_blob) ? state->mode_blob->base.id : 0; + else if (property == config->degamma_lut_property) + *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0; + else if (property == config->ctm_property) + *val = (state->ctm) ? state->ctm->base.id : 0; + else if (property == config->gamma_lut_property) + *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0; else if (crtc->funcs->atomic_get_property) return crtc->funcs->atomic_get_property(crtc, state, property, val); else diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 7a034b231792..3e49a0993191 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2495,8 +2495,12 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_dpms); */ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) { - if (crtc->state) + if (crtc->state) { drm_property_unreference_blob(crtc->state->mode_blob); + drm_property_unreference_blob(crtc->state->degamma_lut); + drm_property_unreference_blob(crtc->state->ctm); + drm_property_unreference_blob(crtc->state->gamma_lut); + } kfree(crtc->state); crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); @@ -2520,10 +2524,17 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, if (state->mode_blob) drm_property_reference_blob(state->mode_blob); + if (state->degamma_lut) + drm_property_reference_blob(state->degamma_lut); + if (state->ctm) + drm_property_reference_blob(state->ctm); + if (state->gamma_lut) + drm_property_reference_blob(state->gamma_lut); state->mode_changed = false; state->active_changed = false; state->planes_changed = false; state->connectors_changed = false; + state->color_mgmt_changed = false; state->event = NULL; } EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state); @@ -2564,6 +2575,9 @@ void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) { drm_property_unreference_blob(state->mode_blob); + drm_property_unreference_blob(state->degamma_lut); + drm_property_unreference_blob(state->ctm); + drm_property_unreference_blob(state->gamma_lut); } EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state); @@ -2877,3 +2891,97 @@ void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, kfree(state); } EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state); + +/** + * drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table + * @crtc: CRTC object + * @red: red correction table + * @green: green correction table + * @blue: green correction table + * @start: + * @size: size of the tables + * + * Implements support for legacy gamma correction table for drivers + * that support color management through the DEGAMMA_LUT/GAMMA_LUT + * properties. + */ +void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, + u16 *red, u16 *green, u16 *blue, + uint32_t start, uint32_t size) +{ + struct drm_device *dev = crtc->dev; + struct drm_mode_config *config = &dev->mode_config; + struct drm_atomic_state *state; + struct drm_crtc_state *crtc_state; + struct drm_property_blob *blob = NULL; + struct drm_color_lut *blob_data; + int i, ret = 0; + + state = drm_atomic_state_alloc(crtc->dev); + if (!state) + return; + + blob = drm_property_create_blob(dev, + sizeof(struct drm_color_lut) * size, + NULL); + if (!blob) { + ret = -ENOMEM; + goto fail; + } + + /* Prepare GAMMA_LUT with the legacy values. */ + blob_data = (struct drm_color_lut *) blob->data; + for (i = 0; i < size; i++) { + blob_data[i].red = red[i]; + blob_data[i].green = green[i]; + blob_data[i].blue = blue[i]; + } + + state->acquire_ctx = crtc->dev->mode_config.acquire_ctx; +retry: + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto fail; + } + + /* Reset DEGAMMA_LUT and CTM properties. */ + ret = drm_atomic_crtc_set_property(crtc, crtc_state, + config->degamma_lut_property, 0); + if (ret) + goto fail; + + ret = drm_atomic_crtc_set_property(crtc, crtc_state, + config->ctm_property, 0); + if (ret) + goto fail; + + ret = drm_atomic_crtc_set_property(crtc, crtc_state, + config->gamma_lut_property, blob->base.id); + if (ret) + goto fail; + + ret = drm_atomic_commit(state); + if (ret) + goto fail; + + /* Driver takes ownership of state on successful commit. */ + + drm_property_unreference_blob(blob); + + return; +fail: + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_free(state); + drm_property_unreference_blob(blob); + + return; +backoff: + drm_atomic_state_clear(state); + drm_atomic_legacy_backoff(state); + + goto retry; +} +EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 579505c0a498..49781a9f8a94 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1563,6 +1563,41 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.prop_mode_id = prop; + prop = drm_property_create(dev, + DRM_MODE_PROP_BLOB, + "DEGAMMA_LUT", 0); + if (!prop) + return -ENOMEM; + dev->mode_config.degamma_lut_property = prop; + + prop = drm_property_create_range(dev, + DRM_MODE_PROP_IMMUTABLE, + "DEGAMMA_LUT_SIZE", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.degamma_lut_size_property = prop; + + prop = drm_property_create(dev, + DRM_MODE_PROP_BLOB, + "CTM", 0); + if (!prop) + return -ENOMEM; + dev->mode_config.ctm_property = prop; + + prop = drm_property_create(dev, + DRM_MODE_PROP_BLOB, + "GAMMA_LUT", 0); + if (!prop) + return -ENOMEM; + dev->mode_config.gamma_lut_property = prop; + + prop = drm_property_create_range(dev, + DRM_MODE_PROP_IMMUTABLE, + "GAMMA_LUT_SIZE", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.gamma_lut_size_property = prop; + return 0; } diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 7539eea4ccbc..79555d2b1b87 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -1075,3 +1075,36 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, return drm_plane_helper_commit(plane, plane_state, old_fb); } EXPORT_SYMBOL(drm_helper_crtc_mode_set_base); + +/** + * drm_helper_crtc_enable_color_mgmt - enable color management properties + * @crtc: DRM CRTC + * @degamma_lut_size: the size of the degamma lut (before CSC) + * @gamma_lut_size: the size of the gamma lut (after CSC) + * + * This function lets the driver enable the color correction properties on a + * CRTC. This includes 3 degamma, csc and gamma properties that userspace can + * set and 2 size properties to inform the userspace of the lut sizes. + */ +void drm_helper_crtc_enable_color_mgmt(struct drm_crtc *crtc, + int degamma_lut_size, + int gamma_lut_size) +{ + struct drm_device *dev = crtc->dev; + struct drm_mode_config *config = &dev->mode_config; + + drm_object_attach_property(&crtc->base, + config->degamma_lut_property, 0); + drm_object_attach_property(&crtc->base, + config->ctm_property, 0); + drm_object_attach_property(&crtc->base, + config->gamma_lut_property, 0); + + drm_object_attach_property(&crtc->base, + config->degamma_lut_size_property, + degamma_lut_size); + drm_object_attach_property(&crtc->base, + config->gamma_lut_size_property, + gamma_lut_size); +} +EXPORT_SYMBOL(drm_helper_crtc_enable_color_mgmt); diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index fe5efada9d68..9054598c9a7a 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -146,6 +146,9 @@ __drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state); void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state); +void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, + u16 *red, u16 *green, u16 *blue, + uint32_t start, uint32_t size); /** * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 75b28deeaf24..b10eba23a744 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -305,6 +305,8 @@ struct drm_plane_helper_funcs; * @mode_changed: crtc_state->mode or crtc_state->enable has been changed * @active_changed: crtc_state->active has been toggled. * @connectors_changed: connectors to this crtc have been updated + * @color_mgmt_changed: color management properties have changed (degamma or + * gamma LUT or CSC matrix) * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes * @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors * @encoder_mask: bitmask of (1 << drm_encoder_index(encoder)) of attached encoders @@ -312,6 +314,11 @@ struct drm_plane_helper_funcs; * update to ensure framebuffer cleanup isn't done too early * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings * @mode: current mode timings + * @degamma_lut: Lookup table for converting framebuffer pixel data + * before apply the conversion matrix + * @ctm: Transformation matrix + * @gamma_lut: Lookup table for converting pixel data after the + * conversion matrix * @event: optional pointer to a DRM event to signal upon completion of the * state update * @state: backpointer to global drm_atomic_state @@ -333,6 +340,7 @@ struct drm_crtc_state { bool mode_changed : 1; bool active_changed : 1; bool connectors_changed : 1; + bool color_mgmt_changed : 1; /* attached planes bitmask: * WARNING: transitional helpers do not maintain plane_mask so @@ -355,6 +363,11 @@ struct drm_crtc_state { /* blob property to expose current mode to atomic userspace */ struct drm_property_blob *mode_blob; + /* blob property to expose color management to userspace */ + struct drm_property_blob *degamma_lut; + struct drm_property_blob *ctm; + struct drm_property_blob *gamma_lut; + struct drm_pending_vblank_event *event; struct drm_atomic_state *state; @@ -757,7 +770,7 @@ struct drm_crtc { int x, y; const struct drm_crtc_funcs *funcs; - /* CRTC gamma size for reporting to userspace */ + /* Legacy FB CRTC gamma size for reporting to userspace */ uint32_t gamma_size; uint16_t *gamma_store; @@ -2027,6 +2040,15 @@ struct drm_mode_config_funcs { * @property_blob_list: list of all the blob property objects * @blob_lock: mutex for blob property allocation and management * @*_property: core property tracking + * @degamma_lut_property: LUT used to convert the framebuffer's colors to linear + * gamma + * @degamma_lut_size_property: size of the degamma LUT as supported by the + * driver (read-only) + * @ctm_property: Matrix used to convert colors after the lookup in the + * degamma LUT + * @gamma_lut_property: LUT used to convert the colors, after the CSC matrix, to + * the gamma space of the connected screen (read-only) + * @gamma_lut_size_property: size of the gamma LUT as supported by the driver * @preferred_depth: preferred RBG pixel depth, used by fb helpers * @prefer_shadow: hint to userspace to prefer shadow-fb rendering * @async_page_flip: does this device support async flips on the primary plane? @@ -2128,6 +2150,13 @@ struct drm_mode_config { struct drm_property *aspect_ratio_property; struct drm_property *dirty_info_property; + /* Optional color correction properties */ + struct drm_property *degamma_lut_property; + struct drm_property *degamma_lut_size_property; + struct drm_property *ctm_property; + struct drm_property *gamma_lut_property; + struct drm_property *gamma_lut_size_property; + /* properties for virtual machine layout */ struct drm_property *suggested_x_property; struct drm_property *suggested_y_property; @@ -2550,6 +2579,21 @@ static inline struct drm_property *drm_property_find(struct drm_device *dev, return mo ? obj_to_property(mo) : NULL; } +/* + * Extract a degamma/gamma LUT value provided by user and round it to the + * precision supported by the hardware. + */ +static inline uint32_t drm_color_lut_extract(uint32_t user_input, + uint32_t bit_precision) +{ + uint32_t val = user_input + (1 << (16 - bit_precision - 1)); + uint32_t max = 0xffff >> (16 - bit_precision); + + val >>= 16 - bit_precision; + + return clamp_val(val, 0, max); +} + /* Plane list iterator for legacy (overlay only) planes. */ #define drm_for_each_legacy_plane(plane, dev) \ list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \ diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 4b37afa2b73b..97fa894d4ee2 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -48,6 +48,9 @@ extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb); +extern void drm_helper_crtc_enable_color_mgmt(struct drm_crtc *crtc, + int degamma_lut_size, + int gamma_lut_size); extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder); diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 50adb46204c2..c0217434d28d 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -487,6 +487,21 @@ struct drm_mode_crtc_lut { __u64 blue; }; +struct drm_color_ctm { + /* Conversion matrix in S31.32 format. */ + __s64 matrix[9]; +}; + +struct drm_color_lut { + /* + * Data is U0.16 fixed point format. + */ + __u16 red; + __u16 green; + __u16 blue; + __u16 reserved; +}; + #define DRM_MODE_PAGE_FLIP_EVENT 0x01 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT|DRM_MODE_PAGE_FLIP_ASYNC) From 562c5b4d898613bec97f482098e7507f52c914cb Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Thu, 10 Mar 2016 12:04:21 +0000 Subject: [PATCH 25/27] drm: fix blob pointer check Check properly that the allocated blob's pointer is valid. Signed-off-by: Lionel Landwerlin Reported-by: Dan Carpenter Cc: Daniel Stone Cc: Daniel Vetter Cc: Matt Roper Cc: dri-devel@lists.freedesktop.org Reviewed-by: Daniel Stone Fixes: 5488dc16fde7 ("drm: introduce pipe color correction properties") Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1457611461-9116-1-git-send-email-lionel.g.landwerlin@intel.com --- drivers/gpu/drm/drm_atomic_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 3e49a0993191..67261ca03fbf 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2924,8 +2924,8 @@ void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, blob = drm_property_create_blob(dev, sizeof(struct drm_color_lut) * size, NULL); - if (!blob) { - ret = -ENOMEM; + if (IS_ERR(blob)) { + ret = PTR_ERR(blob); goto fail; } From 7c01878254daadbb91f5b1137b7404d952e3931b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2016 22:07:46 +0200 Subject: [PATCH 26/27] drm/edid: Extract SADs properly from multiple audio data blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SADs may span multiple CEA audio data blocks in the EDID. CEA-861-E says: "The order of the Data Blocks is not constrained. It is also possible to have more than one of a specific type of data block if necessary to include all of the descriptors needed to describe the sink’s capabilities." Each audio data block can carry up to 10 SADs, whereas the ELD SAD limit is 15 according to HDA 1.0a spec. So we should support at least two data blocks. And apparently some devices take a more liberal interpretation and stuff only one SAD per data block even when they would fit into one. So let's try to extract all the SADs we can fit into the ELD even when they span multiple data blocks. While at it, toss in a comment to explain the 13 byte monitor name string limit which confused me at first. Cc: Arturo Pérez Tested-by: Arturo Pérez Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94197 Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1457554066-8739-1-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_edid.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index fdb1eb014586..414d7f61aa05 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3308,7 +3308,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) u8 *cea; u8 *name; u8 *db; - int sad_count = 0; + int total_sad_count = 0; int mnl; int dbl; @@ -3322,6 +3322,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) name = NULL; drm_for_each_detailed_block((u8 *)edid, monitor_name, &name); + /* max: 13 bytes EDID, 16 bytes ELD */ for (mnl = 0; name && mnl < 13; mnl++) { if (name[mnl] == 0x0a) break; @@ -3350,11 +3351,15 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) dbl = cea_db_payload_len(db); switch (cea_db_tag(db)) { + int sad_count; + case AUDIO_BLOCK: /* Audio Data Block, contains SADs */ - sad_count = dbl / 3; - if (dbl >= 1) - memcpy(eld + 20 + mnl, &db[1], dbl); + sad_count = min(dbl / 3, 15 - total_sad_count); + if (sad_count >= 1) + memcpy(eld + 20 + mnl + total_sad_count * 3, + &db[1], sad_count * 3); + total_sad_count += sad_count; break; case SPEAKER_BLOCK: /* Speaker Allocation Data Block */ @@ -3371,13 +3376,13 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) } } } - eld[5] |= sad_count << 4; + eld[5] |= total_sad_count << 4; eld[DRM_ELD_BASELINE_ELD_LEN] = DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4); DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", - drm_eld_size(eld), sad_count); + drm_eld_size(eld), total_sad_count); } EXPORT_SYMBOL(drm_edid_to_eld); From c1f415c9acb5877c408d9311eb837d7d50636a68 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Fri, 11 Mar 2016 12:17:26 +0000 Subject: [PATCH 27/27] drm: atomic helper: do not unreference error pointer 562c5b4d8986 didn't quite fix the issue of dealing with an error pointer. We can't free/unref an error pointer so reset it to NULL. Many thanks to Dan Carpenter for pointing this out again. Signed-off-by: Lionel Landwerlin Cc: Dan Carpenter Cc: Daniel Stone Cc: Daniel Vetter Cc: Matt Roper Cc: dri-devel@lists.freedesktop.org Fixes: 562c5b4d8986 ("drm: fix blob pointer check") Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1457698646-22231-1-git-send-email-lionel.g.landwerlin@intel.com --- drivers/gpu/drm/drm_atomic_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 67261ca03fbf..e93bb0bbdd82 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2926,6 +2926,7 @@ void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, NULL); if (IS_ERR(blob)) { ret = PTR_ERR(blob); + blob = NULL; goto fail; }