From 88ac3ddab12e2b04dca2958e0bc8b90c703e0397 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Fri, 9 Feb 2018 16:57:38 -0500 Subject: drm/amd/display: Fix active dongle hotplug Clean fake sink flag after detecting link on downstream port. Fixing display light-up after "hot-unplug&plug again" downstream of an active dongle. Signed-off-by: Roman Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 84f6fe9a448b..3af6f0b0836f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1058,6 +1058,10 @@ static void handle_hpd_rx_irq(void *param) !is_mst_root_connector) { /* Downstream Port status changed. */ if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) { + + if (aconnector->fake_enable) + aconnector->fake_enable = false; + amdgpu_dm_update_connector_after_detect(aconnector); -- cgit v1.2.3 From 086247a4b2fba49800b27807f22bb894cd8363fb Mon Sep 17 00:00:00 2001 From: "Leo (Sunpeng) Li" Date: Mon, 12 Feb 2018 13:20:56 -0500 Subject: drm/amd/display: Use 4096 lut entries Points in the DRM LUT are spaced linearly. Points in hardware are spaced exponentially, with greater density towards 0. To maintain low-end accuracy in hardware when sampling the DRM LUT, more points are needed. However, X doesn't seem to play with legacy LUTs of such size. Therefore, check for legacy lut when updating DC states, and update accordingly. v2: Use a macro for the maximum drm LUT value. v3: Update commit to reflect that this does not map 1-1 to HW Signed-off-by: Leo (Sunpeng) Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 4 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_color.c | 77 ++++++++++++++++------ 3 files changed, 61 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 3af6f0b0836f..fa7b2fa25e22 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3197,7 +3197,7 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, dm->adev->mode_info.crtcs[crtc_index] = acrtc; drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES, true, MAX_COLOR_LUT_ENTRIES); - drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LUT_ENTRIES); + drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES); return 0; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index aa7df5775545..b68400c1154b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -268,7 +268,9 @@ void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc); #define amdgpu_dm_crtc_handle_crc_irq(x) #endif -#define MAX_COLOR_LUT_ENTRIES 256 +#define MAX_COLOR_LUT_ENTRIES 4096 +/* Legacy gamm LUT users such as X doesn't like large LUT sizes */ +#define MAX_COLOR_LEGACY_LUT_ENTRIES 256 void amdgpu_dm_init_color_mod(void); int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index 62bb72fe9aa5..e845c511656e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -27,6 +27,8 @@ #include "amdgpu_dm.h" #include "modules/color/color_gamma.h" +#define MAX_DRM_LUT_VALUE 0xFFFF + /* * Initialize the color module. * @@ -47,19 +49,18 @@ void amdgpu_dm_init_color_mod(void) * f(a) = (0xFF00/MAX_COLOR_LUT_ENTRIES-1)a; for integer a in * [0, MAX_COLOR_LUT_ENTRIES) */ -static bool __is_lut_linear(struct drm_color_lut *lut) +static bool __is_lut_linear(struct drm_color_lut *lut, uint32_t size) { int i; - uint32_t max_os = 0xFF00; uint32_t expected; int delta; - for (i = 0; i < MAX_COLOR_LUT_ENTRIES; i++) { + for (i = 0; i < size; i++) { /* All color values should equal */ if ((lut[i].red != lut[i].green) || (lut[i].green != lut[i].blue)) return false; - expected = i * max_os / (MAX_COLOR_LUT_ENTRIES-1); + expected = i * MAX_DRM_LUT_VALUE / (size-1); /* Allow a +/-1 error. */ delta = lut[i].red - expected; @@ -69,6 +70,42 @@ static bool __is_lut_linear(struct drm_color_lut *lut) return true; } +/** + * Convert the drm_color_lut to dc_gamma. The conversion depends on the size + * of the lut - whether or not it's legacy. + */ +static void __drm_lut_to_dc_gamma(struct drm_color_lut *lut, + struct dc_gamma *gamma, + bool is_legacy) +{ + uint32_t r, g, b; + int i; + + if (is_legacy) { + for (i = 0; i < MAX_COLOR_LEGACY_LUT_ENTRIES; i++) { + r = drm_color_lut_extract(lut[i].red, 16); + g = drm_color_lut_extract(lut[i].green, 16); + b = drm_color_lut_extract(lut[i].blue, 16); + + gamma->entries.red[i] = dal_fixed31_32_from_int(r); + gamma->entries.green[i] = dal_fixed31_32_from_int(g); + gamma->entries.blue[i] = dal_fixed31_32_from_int(b); + } + return; + } + + /* else */ + for (i = 0; i < MAX_COLOR_LUT_ENTRIES; i++) { + r = drm_color_lut_extract(lut[i].red, 16); + g = drm_color_lut_extract(lut[i].green, 16); + b = drm_color_lut_extract(lut[i].blue, 16); + + gamma->entries.red[i] = dal_fixed31_32_from_fraction(r, MAX_DRM_LUT_VALUE); + gamma->entries.green[i] = dal_fixed31_32_from_fraction(g, MAX_DRM_LUT_VALUE); + gamma->entries.blue[i] = dal_fixed31_32_from_fraction(b, MAX_DRM_LUT_VALUE); + } +} + /** * amdgpu_dm_set_regamma_lut: Set regamma lut for the given CRTC. * @crtc: amdgpu_dm crtc state @@ -85,11 +122,10 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc) struct drm_property_blob *blob = crtc->base.gamma_lut; struct dc_stream_state *stream = crtc->stream; struct drm_color_lut *lut; + uint32_t lut_size; struct dc_gamma *gamma; enum dc_transfer_func_type old_type = stream->out_transfer_func->type; - uint32_t r, g, b; - int i; bool ret; if (!blob) { @@ -100,8 +136,9 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc) } lut = (struct drm_color_lut *)blob->data; + lut_size = blob->length / sizeof(struct drm_color_lut); - if (__is_lut_linear(lut)) { + if (__is_lut_linear(lut, lut_size)) { /* Set to bypass if lut is set to linear */ stream->out_transfer_func->type = TF_TYPE_BYPASS; stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; @@ -112,20 +149,20 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc) if (!gamma) return -ENOMEM; - gamma->num_entries = MAX_COLOR_LUT_ENTRIES; - gamma->type = GAMMA_RGB_256; - - /* Truncate, and store in dc_gamma for output tf calculation */ - for (i = 0; i < gamma->num_entries; i++) { - r = drm_color_lut_extract(lut[i].red, 16); - g = drm_color_lut_extract(lut[i].green, 16); - b = drm_color_lut_extract(lut[i].blue, 16); - - gamma->entries.red[i] = dal_fixed31_32_from_int(r); - gamma->entries.green[i] = dal_fixed31_32_from_int(g); - gamma->entries.blue[i] = dal_fixed31_32_from_int(b); + gamma->num_entries = lut_size; + if (gamma->num_entries == MAX_COLOR_LEGACY_LUT_ENTRIES) + gamma->type = GAMMA_RGB_256; + else if (gamma->num_entries == MAX_COLOR_LUT_ENTRIES) + gamma->type = GAMMA_CS_TFM_1D; + else { + /* Invalid lut size */ + dc_gamma_release(&gamma); + return -EINVAL; } + /* Convert drm_lut into dc_gamma */ + __drm_lut_to_dc_gamma(lut, gamma, gamma->type == GAMMA_RGB_256); + /* Call color module to translate into something DC understands. Namely * a transfer function. */ @@ -212,7 +249,7 @@ int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state, } lut = (struct drm_color_lut *)blob->data; - if (__is_lut_linear(lut)) { + if (__is_lut_linear(lut, MAX_COLOR_LUT_ENTRIES)) { dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS; dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; return 0; -- cgit v1.2.3 From 0e5916ffb8b1f0158651f5867c150ceea3d06991 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Tue, 20 Feb 2018 14:34:16 +0530 Subject: drm/amd/display: allocate fbc buffer in AMDGPU_GEM_DOMAIN_GTT Currently the FBC buffer is allocated in VRAM, since VRAM usage is dedicatedly for scanouts, by allocating FBC back buffer in GTT shall help in conserving VRAM for other purposes. Signed-off-by: Shirish S Reviewed-by: Charlene Liu Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index fa7b2fa25e22..92fe2111e774 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -374,7 +374,7 @@ static void amdgpu_dm_fbc_init(struct drm_connector *connector) if (max_size) { int r = amdgpu_bo_create_kernel(adev, max_size * 4, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, &compressor->bo_ptr, + AMDGPU_GEM_DOMAIN_GTT, &compressor->bo_ptr, &compressor->gpu_addr, &compressor->cpu_addr); if (r) -- cgit v1.2.3 From 589d2739332db0b8e17e0fc827525311c211a410 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 13 Feb 2018 10:54:26 -0500 Subject: drm/amd/display: Use crtc enable/disable_vblank hooks Signed-off-by: Harry Wentland Reviewed-by: Tony Cheng Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 92fe2111e774..258657d20f88 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2490,6 +2490,28 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) return &state->base; } + +static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) +{ + enum dc_irq_source irq_source; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + struct amdgpu_device *adev = crtc->dev->dev_private; + + irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst; + dc_interrupt_set(adev->dm.dc, irq_source, enable); + return 0; +} + +static int dm_enable_vblank(struct drm_crtc *crtc) +{ + return dm_set_vblank(crtc, true); +} + +static void dm_disable_vblank(struct drm_crtc *crtc) +{ + dm_set_vblank(crtc, false); +} + /* Implemented only the options currently availible for the driver */ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { .reset = dm_crtc_reset_state, @@ -2500,6 +2522,8 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { .atomic_duplicate_state = dm_crtc_duplicate_state, .atomic_destroy_state = dm_crtc_destroy_state, .set_crc_source = amdgpu_dm_crtc_set_crc_source, + .enable_vblank = dm_enable_vblank, + .disable_vblank = dm_disable_vblank, }; static enum drm_connector_status -- cgit v1.2.3 From a0e30392dd03727c069d1cf93ee6582473dd3dd6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 13 Feb 2018 11:03:01 -0500 Subject: drm/amd/display: Return success when enabling interrupt Signed-off-by: Harry Wentland Reviewed-by: Roman Li Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++--- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 258657d20f88..9a1e82305b07 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2498,8 +2498,7 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) struct amdgpu_device *adev = crtc->dev->dev_private; irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst; - dc_interrupt_set(adev->dm.dc, irq_source, enable); - return 0; + return dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY; } static int dm_enable_vblank(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 2bc15a46882a..8394d69b963f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1516,13 +1516,13 @@ enum dc_irq_source dc_interrupt_to_irq_source( return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id); } -void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) +bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) { if (dc == NULL) - return; + return false; - dal_irq_service_set(dc->res_pool->irqs, src, enable); + return dal_irq_service_set(dc->res_pool->irqs, src, enable); } void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7f0dbf6a866a..2cd97342bf0f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -705,7 +705,7 @@ enum dc_irq_source dc_interrupt_to_irq_source( struct dc *dc, uint32_t src_id, uint32_t ext_id); -void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable); +bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable); void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src); enum dc_irq_source dc_get_hpd_irq_source_at_index( struct dc *dc, uint32_t link_index); -- cgit v1.2.3 From c21b68c5ebd9b0267d59c7a899ee4c6a7e0668fc Mon Sep 17 00:00:00 2001 From: Shirish S Date: Fri, 16 Feb 2018 11:44:22 +0530 Subject: drm/amd/display: defer modeset check in dm_update_planes_state amdgpu_dm_atomic_check() is used to validate the entire configuration of planes and crtc's that the user space wants to commit. However amdgpu_dm_atomic_check() depends upon DRM_MODE_ATOMIC_ALLOW_MODESET flag else its mostly dummy. Its not mandatory for the user space to set DRM_MODE_ATOMIC_ALLOW_MODESET, and in general its not set either along with DRM_MODE_ATOMIC_TEST_ONLY. Considering its importantance, this patch defers the allow_modeset check in dm_update_planes_state(), so that there shall be scope to validate the configuration sent from user space, without impacting the population of dc/dm related data structures. Signed-off-by: Shirish S Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9a1e82305b07..2c5ef6619b17 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4687,8 +4687,6 @@ static int dm_update_planes_state(struct dc *dc, bool pflip_needed = !state->allow_modeset; int ret = 0; - if (pflip_needed) - return ret; /* Add new planes */ for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { @@ -4703,6 +4701,8 @@ static int dm_update_planes_state(struct dc *dc, /* Remove any changed/removed planes */ if (!enable) { + if (pflip_needed) + continue; if (!old_plane_crtc) continue; @@ -4747,6 +4747,8 @@ static int dm_update_planes_state(struct dc *dc, if (!dm_new_crtc_state->stream) continue; + if (pflip_needed) + continue; WARN_ON(dm_new_plane_state->dc_state); -- cgit v1.2.3 From a05bcff10426841351010e8648e4d9d95e9b65a1 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Tue, 13 Feb 2018 14:15:17 +0530 Subject: drm/amd/display: update plane params before validation This patch updates the dc's plane state with the parameters set by the user side. This is needed to validate the plane capabilities with the parameters user space wants to set. Signed-off-by: Shirish S Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 2c5ef6619b17..5b175b7c507c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3086,6 +3086,9 @@ static int dm_plane_atomic_check(struct drm_plane *plane, if (!dm_plane_state->dc_state) return 0; + if (!fill_rects_from_plane_state(state, dm_plane_state->dc_state)) + return -EINVAL; + if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK) return 0; -- cgit v1.2.3 From b58f0c81e9ab40ebed723ac71c34d87769540ad2 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Wed, 28 Feb 2018 12:14:58 +0530 Subject: drm/amd/display: disable CRTCs with NULL FB on their primary plane (V2) The below commit "drm/atomic: Try to preserve the crtc enabled state in drm_atomic_remove_fb, v2" introduces a slight behavioral change to rmfb. Instead of disabling a crtc when the primary plane is disabled, it now preserves it. This change leads to BUG hit while performing atomic commit on amd driver. As a fix this patch ensures that we disable the CRTC's with NULL FB by returning -EINVAL and hence triggering fall back to the old behavior and turning off the crtc in atomic_remove_fb(). V2: Added error check for plane_state and removed sanity check for crtc. Signed-off-by: Shirish S Signed-off-by: Pratik Vishwakarma Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 5b175b7c507c..8b5489f0e5e7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4796,6 +4796,30 @@ static int dm_update_planes_state(struct dc *dc, return ret; } +static int dm_atomic_check_plane_state_fb(struct drm_atomic_state *state, + struct drm_crtc *crtc) +{ + struct drm_plane *plane; + struct drm_crtc_state *crtc_state; + + WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc)); + + drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) { + struct drm_plane_state *plane_state = + drm_atomic_get_plane_state(state, plane); + + if (IS_ERR(plane_state)) + return -EDEADLK; + + crtc_state = drm_atomic_get_crtc_state(plane_state->state, crtc); + if (crtc->primary == plane && crtc_state->active) { + if (!plane_state->fb) + return -EINVAL; + } + } + return 0; +} + static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { @@ -4819,6 +4843,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + ret = dm_atomic_check_plane_state_fb(state, crtc); + if (ret) + goto fail; + if (!drm_atomic_crtc_needs_modeset(new_crtc_state) && !new_crtc_state->color_mgmt_changed) continue; -- cgit v1.2.3