From 0922b899f36621126d49c0d86e90fb18d572d8a1 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Thu, 30 Apr 2020 12:24:05 -0400 Subject: drm/amd/display: Don't pass invalid fw_bss_data pointer into DMUB srv [Why] If bss_data_size is 0 then we shouldn't be passing down fw_bss_data into the DMUB service since the region isn't really "valid." [How] Pass NULL instead if the size is 0. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Zhan Liu Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 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 d53c60b37cc6..2b975a1c7665 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1228,10 +1228,10 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) PSP_HEADER_BYTES - PSP_FOOTER_BYTES; region_params.bss_data_size = le32_to_cpu(hdr->bss_data_bytes); region_params.vbios_size = adev->bios_size; - region_params.fw_bss_data = + region_params.fw_bss_data = region_params.bss_data_size ? adev->dm.dmub_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes) + - le32_to_cpu(hdr->inst_const_bytes); + le32_to_cpu(hdr->inst_const_bytes) : NULL; region_params.fw_inst_const = adev->dm.dmub_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes) + -- cgit v1.2.3-70-g09d2 From 2a12c4e9f1674432fa06f73026158a7b4698a0b4 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 28 May 2020 09:44:44 -0400 Subject: Revert "drm/amd/display: disable dcn20 abm feature for bring up" This reverts commit 96cb7cf13d8530099c256c053648ad576588c387. This change was used for DCN2 bringup and is no longer desired. In fact it breaks backlight on DCN2 systems. Cc: Alexander Monakov Cc: Hersen Wu Cc: Anthony Koo Cc: Michael Chiu Signed-off-by: Harry Wentland Acked-by: Alex Deucher Reviewed-by: Nicholas Kazlauskas Reported-and-tested-by: Alexander Monakov Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 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 2b975a1c7665..435bfae8111c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1356,7 +1356,7 @@ static int dm_late_init(void *handle) unsigned int linear_lut[16]; int i; struct dmcu *dmcu = NULL; - bool ret = false; + bool ret; if (!adev->dm.fw_dmcu) return detect_mst_link_for_all_connectors(adev->ddev); @@ -1377,13 +1377,10 @@ static int dm_late_init(void *handle) */ params.min_abm_backlight = 0x28F; - /* todo will enable for navi10 */ - if (adev->asic_type <= CHIP_RAVEN) { - ret = dmcu_load_iram(dmcu, params); + ret = dmcu_load_iram(dmcu, params); - if (!ret) - return -EINVAL; - } + if (!ret) + return -EINVAL; return detect_mst_link_for_all_connectors(adev->ddev); } -- cgit v1.2.3-70-g09d2 From fa7041d9d2fc7401cece43f305eb5b87b7017fc4 Mon Sep 17 00:00:00 2001 From: Stylon Wang Date: Fri, 12 Jun 2020 19:04:18 +0800 Subject: drm/amd/display: Fix ineffective setting of max bpc property [Why] Regression was introduced where setting max bpc property has no effect on the atomic check and final commit. It has the same effect as max bpc being stuck at 8. [How] Correctly propagate max bpc with the new connector state. Signed-off-by: Stylon Wang Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 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 7ced9f87be97..10ac8076d4f2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5024,7 +5024,8 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, struct drm_connector *connector = &aconnector->base; struct amdgpu_device *adev = connector->dev->dev_private; struct dc_stream_state *stream; - int requested_bpc = connector->state ? connector->state->max_requested_bpc : 8; + const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL; + int requested_bpc = drm_state ? drm_state->max_requested_bpc : 8; enum dc_status dc_result = DC_OK; do { -- cgit v1.2.3-70-g09d2 From 790373245ee6d7806f3608060529c94fcd525271 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 21 May 2020 12:48:41 -0400 Subject: drm/amd/display: Add DCN3 Support in DM (v2) Handle DCN3 in amdgpu_dm v2: fix num_pkrs handling Signed-off-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 27 ++++++++++++++++++++++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 20 ++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 1 + drivers/gpu/drm/amd/display/dc/dc_types.h | 9 ++++++++ drivers/gpu/drm/amd/display/dc/dm_helpers.h | 23 ++++++++++++++++++ 5 files changed, 80 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 435bfae8111c..c64beb2d6c5f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -94,6 +94,10 @@ #define FIRMWARE_RENOIR_DMUB "amdgpu/renoir_dmcub.bin" MODULE_FIRMWARE(FIRMWARE_RENOIR_DMUB); +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) +#define FIRMWARE_SIENNA_CICHLID_DMUB "amdgpu/sienna_cichlid_dmcub.bin" +MODULE_FIRMWARE(FIRMWARE_SIENNA_CICHLID_DMUB); +#endif #define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin" MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU); @@ -1070,6 +1074,9 @@ static int load_dmcu_fw(struct amdgpu_device *adev) case CHIP_NAVI10: case CHIP_NAVI14: case CHIP_RENOIR: +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + case CHIP_SIENNA_CICHLID: +#endif return 0; case CHIP_NAVI12: fw_name_dmcu = FIRMWARE_NAVI12_DMCU; @@ -1166,6 +1173,12 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) dmub_asic = DMUB_ASIC_DCN21; fw_name_dmub = FIRMWARE_RENOIR_DMUB; break; +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + case CHIP_SIENNA_CICHLID: + dmub_asic = DMUB_ASIC_DCN30; + fw_name_dmub = FIRMWARE_SIENNA_CICHLID_DMUB; + break; +#endif default: /* ASIC doesn't support DMUB. */ @@ -3205,6 +3218,9 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_NAVI10: case CHIP_NAVI14: case CHIP_RENOIR: +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + case CHIP_SIENNA_CICHLID: +#endif if (dcn10_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); goto fail; @@ -3359,6 +3375,9 @@ static int dm_early_init(void *handle) #endif case CHIP_NAVI10: case CHIP_NAVI12: +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + case CHIP_SIENNA_CICHLID: +#endif adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; adev->mode_info.num_dig = 6; @@ -3679,6 +3698,9 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev, adev->asic_type == CHIP_NAVI10 || adev->asic_type == CHIP_NAVI14 || adev->asic_type == CHIP_NAVI12 || +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + adev->asic_type == CHIP_SIENNA_CICHLID || +#endif adev->asic_type == CHIP_RENOIR || adev->asic_type == CHIP_RAVEN) { /* Fill GFX9 params */ @@ -3698,6 +3720,11 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev, AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE); tiling_info->gfx9.shaderEnable = 1; +#ifdef CONFIG_DRM_AMD_DC_DCN3_0 + if (adev->asic_type == CHIP_SIENNA_CICHLID) + tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs; + +#endif ret = fill_plane_dcc_attributes(adev, afb, format, rotation, plane_size, tiling_info, tiling_flags, dcc, address, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index b086d5c906e0..d839eb14e3f0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -627,3 +627,23 @@ void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks) { /* TODO: something */ } +#ifdef CONFIG_DRM_AMD_DC_DCN3_0 + +void *dm_helpers_allocate_gpu_mem( + struct dc_context *ctx, + enum dc_gpu_mem_alloc_type type, + size_t size, + long long *addr) +{ + // TODO + return NULL; +} + +void dm_helpers_free_gpu_mem( + struct dc_context *ctx, + enum dc_gpu_mem_alloc_type type, + void *pvMem) +{ + // TODO +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 95175471e48d..b7a8c71e3e39 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -390,6 +390,7 @@ union dc_tiling_info { bool meta_linear; bool rb_aligned; bool pipe_aligned; + unsigned int num_pkrs; } gfx9; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index c726fb0695da..d7b9d311d9e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -887,6 +887,15 @@ struct dsc_dec_dpcd_caps { uint32_t branch_max_line_width; }; +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) +enum dc_gpu_mem_alloc_type { + DC_MEM_ALLOC_TYPE_GART, + DC_MEM_ALLOC_TYPE_FRAME_BUFFER, + DC_MEM_ALLOC_TYPE_INVISIBLE_FRAME_BUFFER, + DC_MEM_ALLOC_TYPE_AGP +}; + +#endif enum dc_psr_version { DC_PSR_VERSION_1 = 0, DC_PSR_VERSION_UNSUPPORTED = 0xFFFFFFFF, diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 8bde1d688f2e..b2cc2bf95712 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -35,6 +35,29 @@ struct dp_mst_stream_allocation_table; +#ifdef CONFIG_DRM_AMD_DC_DCN3_0 +/* + * Allocate memory accessible by the GPU + * + * frame buffer allocations must be aligned to a 4096-byte boundary + * + * Returns virtual address, sets addr to physical address + */ +void *dm_helpers_allocate_gpu_mem( + struct dc_context *ctx, + enum dc_gpu_mem_alloc_type type, + size_t size, + long long *addr); + +/* + * Free the GPU-accessible memory at the virtual address pvMem + */ +void dm_helpers_free_gpu_mem( + struct dc_context *ctx, + enum dc_gpu_mem_alloc_type type, + void *pvMem); + +#endif enum dc_edid_status dm_helpers_parse_edid_caps( struct dc_context *ctx, const struct dc_edid *edid, -- cgit v1.2.3-70-g09d2 From 74a166759d692efe18996076736b61533936892b Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 26 May 2020 16:53:38 -0400 Subject: drm/amd/display: Add helper to convert DC status During the debugging process related to a hot-plug problem with 4k display, we realized that we had some issues related to the global state validation. This problem was not explicitly highlighted in the dmesg log, for this reason, this commit adds a function that converts `enum dc_status` to a human-readable string and appends the proper warning message in case of failure. Signed-off-by: Rodrigo Siqueira Reviewed-by: Harry Wentland Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 +++-- drivers/gpu/drm/amd/display/dc/core/dc_debug.c | 59 +++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/inc/core_status.h | 2 + 3 files changed, 69 insertions(+), 5 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 c64beb2d6c5f..461ff7e511c3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5066,11 +5066,12 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, dc_result = dc_validate_stream(adev->dm.dc, stream); if (dc_result != DC_OK) { - DRM_DEBUG_KMS("Mode %dx%d (clk %d) failed DC validation with error %d\n", + DRM_DEBUG_KMS("Mode %dx%d (clk %d) failed DC validation with error %d (%s)\n", drm_mode->hdisplay, drm_mode->vdisplay, drm_mode->clock, - dc_result); + dc_result, + dc_status_to_str(dc_result)); dc_stream_release(stream); stream = NULL; @@ -8504,7 +8505,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_plane_state *old_plane_state, *new_plane_state; enum surface_update_type update_type = UPDATE_TYPE_FAST; enum surface_update_type overall_update_type = UPDATE_TYPE_FAST; - + enum dc_status status; int ret, i; /* @@ -8716,8 +8717,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, ret = drm_dp_mst_atomic_check(state); if (ret) goto fail; - - if (dc_validate_global_state(dc, dm_state->context, false) != DC_OK) { + status = dc_validate_global_state(dc, dm_state->context, false); + if (status != DC_OK) { + DC_LOG_WARNING("DC global validation failure: %s (%d)", + dc_status_to_str(status), status); ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 502ed3c7959d..87d89449b9af 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -365,3 +365,62 @@ void context_clock_trace( context->bw_ctx.bw.dcn.clk.socclk_khz); #endif } + +/** + * dc_status_to_str - convert dc_status to a human readable string + * @status: dc_status to be converted + * + * Return: + * A string describing the DC status. + */ +char *dc_status_to_str(enum dc_status status) +{ + switch (status) { + case DC_OK: + return "DC OK"; + case DC_NO_CONTROLLER_RESOURCE: + return "No controller resource"; + case DC_NO_STREAM_ENC_RESOURCE: + return "No stream encoder"; + case DC_NO_CLOCK_SOURCE_RESOURCE: + return "No clock source"; + case DC_FAIL_CONTROLLER_VALIDATE: + return "Controller validation failure"; + case DC_FAIL_ENC_VALIDATE: + return "Encoder validation failure"; + case DC_FAIL_ATTACH_SURFACES: + return "Surfaces attachment failure"; + case DC_FAIL_DETACH_SURFACES: + return "Surfaces detachment failure"; + case DC_FAIL_SURFACE_VALIDATE: + return "Surface validation failure"; + case DC_NO_DP_LINK_BANDWIDTH: + return "No DP link bandwidth"; + case DC_EXCEED_DONGLE_CAP: + return "Exceed dongle capability"; + case DC_SURFACE_PIXEL_FORMAT_UNSUPPORTED: + return "Unsupported pixel format"; + case DC_FAIL_BANDWIDTH_VALIDATE: + return "Bandwidth validation failure (BW and Watermark)"; + case DC_FAIL_SCALING: + return "Scaling failure"; + case DC_FAIL_DP_LINK_TRAINING: + return "DP link training failure"; + case DC_FAIL_DSC_VALIDATE: + return "DSC validation failure"; + case DC_NO_DSC_RESOURCE: + return "No DSC resource"; + case DC_FAIL_UNSUPPORTED_1: + return "Unsupported"; + case DC_FAIL_CLK_EXCEED_MAX: + return "Clk exceed max failure"; + case DC_FAIL_CLK_BELOW_MIN: + return "Fail clk below minimum"; + case DC_FAIL_CLK_BELOW_CFG_REQUIRED: + return "Fail clk below required CFG (hard_min in PPLIB)"; + case DC_ERROR_UNEXPECTED: + return "Unexpected error"; + } + + return "Unexpected status error"; +} diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index 4ead89dd7c41..f932801235c6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -53,4 +53,6 @@ enum dc_status { DC_ERROR_UNEXPECTED = -1 }; +char *dc_status_to_str(enum dc_status status); + #endif /* _CORE_STATUS_H_ */ -- cgit v1.2.3-70-g09d2 From dfd84d902b078faf511e91158ee8db4c2e055e42 Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Thu, 18 Jun 2020 15:07:13 +0200 Subject: drm/amd/display: label internally used symbols as static Used sparse(make C=1) to find these loose ends. Signed-off-by: Nirmoy Das Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++----- .../drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 24 ++++++++++++---------- .../gpu/drm/amd/display/dc/dce/dce_panel_cntl.c | 10 ++++----- .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 10 ++++----- 4 files changed, 28 insertions(+), 26 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 461ff7e511c3..7094c3b2c4f7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -700,7 +700,7 @@ static void amdgpu_dm_audio_fini(struct amdgpu_device *adev) adev->mode_info.audio.enabled = false; } -void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, int pin) +static void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, int pin) { struct drm_audio_component *acomp = adev->dm.audio_component; @@ -1586,7 +1586,7 @@ static void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev, } -enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc) +static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc) { struct dc_state *context = NULL; enum dc_status res = DC_ERROR_UNEXPECTED; @@ -2706,7 +2706,7 @@ static int dm_atomic_get_state(struct drm_atomic_state *state, return 0; } -struct dm_atomic_state * +static struct dm_atomic_state * dm_atomic_get_new_state(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; @@ -2724,7 +2724,7 @@ dm_atomic_get_new_state(struct drm_atomic_state *state) return NULL; } -struct dm_atomic_state * +static struct dm_atomic_state * dm_atomic_get_old_state(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; @@ -5564,7 +5564,7 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane) return &dm_plane_state->base; } -void dm_drm_plane_destroy_state(struct drm_plane *plane, +static void dm_drm_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state) { struct dm_plane_state *dm_plane_state = to_dm_plane_state(state); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index a2e1a73f66b8..484171241330 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c @@ -660,7 +660,7 @@ void pp_rv_set_hard_min_fclk_by_freq(struct pp_smu *pp, int mhz) pp_funcs->set_hard_min_fclk_by_freq(pp_handle, mhz); } -enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp, +static enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp, struct pp_smu_wm_range_sets *ranges) { const struct dc_context *ctx = pp->dm; @@ -728,7 +728,7 @@ enum pp_smu_status pp_nv_set_pme_wa_enable(struct pp_smu *pp) return PP_SMU_RESULT_OK; } -enum pp_smu_status pp_nv_set_display_count(struct pp_smu *pp, int count) +static enum pp_smu_status pp_nv_set_display_count(struct pp_smu *pp, int count) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; @@ -744,7 +744,8 @@ enum pp_smu_status pp_nv_set_display_count(struct pp_smu *pp, int count) return PP_SMU_RESULT_OK; } -enum pp_smu_status pp_nv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int mhz) +static enum pp_smu_status +pp_nv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int mhz) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; @@ -760,7 +761,7 @@ enum pp_smu_status pp_nv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int mhz) return PP_SMU_RESULT_OK; } -enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq( +static enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq( struct pp_smu *pp, int mhz) { const struct dc_context *ctx = pp->dm; @@ -783,7 +784,8 @@ enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq( return PP_SMU_RESULT_OK; } -enum pp_smu_status pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz) +static enum pp_smu_status +pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; @@ -805,7 +807,7 @@ enum pp_smu_status pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz) return PP_SMU_RESULT_OK; } -enum pp_smu_status pp_nv_set_pstate_handshake_support( +static enum pp_smu_status pp_nv_set_pstate_handshake_support( struct pp_smu *pp, BOOLEAN pstate_handshake_supported) { const struct dc_context *ctx = pp->dm; @@ -818,7 +820,7 @@ enum pp_smu_status pp_nv_set_pstate_handshake_support( return PP_SMU_RESULT_OK; } -enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp, +static enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp, enum pp_smu_nv_clock_id clock_id, int mhz) { const struct dc_context *ctx = pp->dm; @@ -853,7 +855,7 @@ enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp, return PP_SMU_RESULT_OK; } -enum pp_smu_status pp_nv_get_maximum_sustainable_clocks( +static enum pp_smu_status pp_nv_get_maximum_sustainable_clocks( struct pp_smu *pp, struct pp_smu_nv_clock_table *max_clocks) { const struct dc_context *ctx = pp->dm; @@ -872,7 +874,7 @@ enum pp_smu_status pp_nv_get_maximum_sustainable_clocks( return PP_SMU_RESULT_FAIL; } -enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp, +static enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp, unsigned int *clock_values_in_khz, unsigned int *num_states) { const struct dc_context *ctx = pp->dm; @@ -892,7 +894,7 @@ enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp, return PP_SMU_RESULT_FAIL; } -enum pp_smu_status pp_rn_get_dpm_clock_table( +static enum pp_smu_status pp_rn_get_dpm_clock_table( struct pp_smu *pp, struct dpm_clocks *clock_table) { const struct dc_context *ctx = pp->dm; @@ -911,7 +913,7 @@ enum pp_smu_status pp_rn_get_dpm_clock_table( return PP_SMU_RESULT_FAIL; } -enum pp_smu_status pp_rn_set_wm_ranges(struct pp_smu *pp, +static enum pp_smu_status pp_rn_set_wm_ranges(struct pp_smu *pp, struct pp_smu_wm_range_sets *ranges) { const struct dc_context *ctx = pp->dm; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c index ebff9b1e312e..43781e77be43 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c @@ -95,7 +95,7 @@ static unsigned int calculate_16_bit_backlight_from_pwm(struct dce_panel_cntl *d return (uint32_t)(current_backlight); } -uint32_t dce_panel_cntl_hw_init(struct panel_cntl *panel_cntl) +static uint32_t dce_panel_cntl_hw_init(struct panel_cntl *panel_cntl) { struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl); uint32_t value; @@ -155,7 +155,7 @@ uint32_t dce_panel_cntl_hw_init(struct panel_cntl *panel_cntl) return current_backlight; } -bool dce_is_panel_backlight_on(struct panel_cntl *panel_cntl) +static bool dce_is_panel_backlight_on(struct panel_cntl *panel_cntl) { struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl); uint32_t value; @@ -165,7 +165,7 @@ bool dce_is_panel_backlight_on(struct panel_cntl *panel_cntl) return value; } -bool dce_is_panel_powered_on(struct panel_cntl *panel_cntl) +static bool dce_is_panel_powered_on(struct panel_cntl *panel_cntl) { struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl); uint32_t pwr_seq_state, dig_on, dig_on_ovrd; @@ -177,7 +177,7 @@ bool dce_is_panel_powered_on(struct panel_cntl *panel_cntl) return (pwr_seq_state == 1) || (dig_on == 1 && dig_on_ovrd == 1); } -void dce_store_backlight_level(struct panel_cntl *panel_cntl) +static void dce_store_backlight_level(struct panel_cntl *panel_cntl) { struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl); @@ -192,7 +192,7 @@ void dce_store_backlight_level(struct panel_cntl *panel_cntl) &panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); } -void dce_driver_set_backlight(struct panel_cntl *panel_cntl, +static void dce_driver_set_backlight(struct panel_cntl *panel_cntl, uint32_t backlight_pwm_u16_16) { uint32_t backlight_16bit; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index fb167393b8fe..8f51f9cbe32a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -157,7 +157,7 @@ struct _vcs_dpi_ip_params_st dcn2_0_ip = { .number_of_cursors = 1, }; -struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip = { +static struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip = { .odm_capable = 1, .gpuvm_enable = 0, .hostvm_enable = 0, @@ -226,7 +226,7 @@ struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip = { .number_of_cursors = 1, }; -struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = { +static struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = { /* Defaults that get patched on driver load from firmware. */ .clock_limits = { { @@ -338,7 +338,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = { .use_urgent_burst_bw = 0 }; -struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = { +static struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = { .clock_limits = { { .state = 0, @@ -449,7 +449,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = { .use_urgent_burst_bw = 0 }; -struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 0 }; +static struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 0 }; #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f @@ -1323,7 +1323,7 @@ static struct panel_cntl *dcn20_panel_cntl_create(const struct panel_cntl_init_d return &panel_cntl->base; } -struct clock_source *dcn20_clock_source_create( +static struct clock_source *dcn20_clock_source_create( struct dc_context *ctx, struct dc_bios *bios, enum clock_source_id id, -- cgit v1.2.3-70-g09d2 From 03ca960098d227e09e83f09e75e5fdbba48a7187 Mon Sep 17 00:00:00 2001 From: Mikita Lipski Date: Mon, 1 Jun 2020 10:26:11 -0400 Subject: drm/amd/display: Fix calculation of virtual channel payload [why] The calculation of virtual channel payload would not take link settings in account. As we calculate VCPI slots needed both PBN for stream and also PBN per time slot. Before we would use generic PBN per time slot, which would not change with link settings causing wrong Payload allocation. [how] Provide PBN per time slot for each Virtual channel payload calculation. Signed-off-by: Mikita Lipski Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 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 7094c3b2c4f7..991516e5c6cc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5452,7 +5452,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, mst_mgr, mst_port, dm_new_connector_state->pbn, - 0); + dm_mst_get_pbn_divider(aconnector->dc_link)); if (dm_new_connector_state->vcpi_slots < 0) { DRM_DEBUG_ATOMIC("failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots); return dm_new_connector_state->vcpi_slots; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index ae0a7ef1d595..cf15248739f7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -522,6 +522,8 @@ static void increase_dsc_bpp(struct drm_atomic_state *state, int link_timeslots_used; int fair_pbn_alloc; + pbn_per_timeslot = dm_mst_get_pbn_divider(dc_link); + for (i = 0; i < count; i++) { if (vars[i].dsc_enabled) { initial_slack[i] = kbps_to_peak_pbn(params[i].bw_range.max_kbps) - vars[i].pbn; @@ -533,9 +535,6 @@ static void increase_dsc_bpp(struct drm_atomic_state *state, } } - pbn_per_timeslot = dc_link_bandwidth_kbps(dc_link, - dc_link_get_link_cap(dc_link)) / (8 * 1000 * 54); - while (remaining_to_increase) { next_index = -1; min_initial_slack = -1; @@ -564,7 +563,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state, params[next_index].port->mgr, params[next_index].port, vars[next_index].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + pbn_per_timeslot) < 0) return; if (!drm_dp_mst_atomic_check(state)) { vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn); @@ -574,7 +573,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state, params[next_index].port->mgr, params[next_index].port, vars[next_index].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + pbn_per_timeslot) < 0) return; } } else { @@ -583,7 +582,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state, params[next_index].port->mgr, params[next_index].port, vars[next_index].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + pbn_per_timeslot) < 0) return; if (!drm_dp_mst_atomic_check(state)) { vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16; @@ -593,7 +592,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state, params[next_index].port->mgr, params[next_index].port, vars[next_index].pbn, - dm_mst_get_pbn_divider(dc_link)) < 0) + pbn_per_timeslot) < 0) return; } } @@ -647,7 +646,7 @@ static void try_disable_dsc(struct drm_atomic_state *state, params[next_index].port->mgr, params[next_index].port, vars[next_index].pbn, - 0) < 0) + dm_mst_get_pbn_divider(dc_link)) < 0) return; if (!drm_dp_mst_atomic_check(state)) { @@ -718,7 +717,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, params[i].port->mgr, params[i].port, vars[i].pbn, - 0) < 0) + dm_mst_get_pbn_divider(dc_link)) < 0) return false; } if (!drm_dp_mst_atomic_check(state)) { @@ -746,7 +745,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, params[i].port->mgr, params[i].port, vars[i].pbn, - 0) < 0) + dm_mst_get_pbn_divider(dc_link)) < 0) return false; } } -- cgit v1.2.3-70-g09d2 From 8c44515be175a1bc18620284d23efa385daea49f Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Thu, 4 Jun 2020 15:54:39 -0400 Subject: drm/amd/display: clip plane rects in DM before passing into DC [Why] DC global validation can fail when userspace requests to draw large plane without performing the clipping themselves. This is observed in the IGT kms_plane panning tests for 4K displays where they draw an 8K plane without any clipping while expecting only the top 4K to be drawn. [How] DRM already has helpers to take care of the clipping necessary and to mark whether a plane is visible or not, so make use of these helpers in DM before passing the plane to DC. Signed-off-by: Aurabindo Pillai Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 +++++++++++++++++++++++ 1 file changed, 25 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 991516e5c6cc..a19a3ed3ca16 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5693,6 +5693,17 @@ static void dm_plane_helper_cleanup_fb(struct drm_plane *plane, amdgpu_bo_unref(&rbo); } +static int dm_plane_helper_check_state(struct drm_plane_state *state, + struct drm_crtc_state *new_crtc_state) +{ + int max_downscale = 0; + int max_upscale = INT_MAX; + + /* TODO: These should be checked against DC plane caps */ + return drm_atomic_helper_check_plane_state( + state, new_crtc_state, max_downscale, max_upscale, true, true); +} + static int dm_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { @@ -5700,6 +5711,7 @@ static int dm_plane_atomic_check(struct drm_plane *plane, struct dc *dc = adev->dm.dc; struct dm_plane_state *dm_plane_state; struct dc_scaling_info scaling_info; + struct drm_crtc_state *new_crtc_state; int ret; dm_plane_state = to_dm_plane_state(state); @@ -5707,6 +5719,15 @@ static int dm_plane_atomic_check(struct drm_plane *plane, if (!dm_plane_state->dc_state) return 0; + new_crtc_state = + drm_atomic_get_new_crtc_state(state->state, state->crtc); + if (!new_crtc_state) + return -EINVAL; + + ret = dm_plane_helper_check_state(state, new_crtc_state); + if (ret) + return ret; + ret = fill_dc_scaling_info(state, &scaling_info); if (ret) return ret; @@ -8223,6 +8244,10 @@ static int dm_update_plane_state(struct dc *dc, if (!needs_reset) return 0; + ret = dm_plane_helper_check_state(new_plane_state, new_crtc_state); + if (ret) + return ret; + WARN_ON(dm_new_plane_state->dc_state); dc_new_plane_state = dc_create_plane_state(dc); -- cgit v1.2.3-70-g09d2 From 7715fdf3362fa88f3e3620261a6e546f50713a5e Mon Sep 17 00:00:00 2001 From: Derek Lai Date: Thu, 4 Jun 2020 16:29:39 +0800 Subject: drm/amd/display: VSC SDP supported for SST [why] If a typeC to HDMI dongle supports YCbCr420 pass through and VSC colorimetry and pixel encoding formats in the Extended Receiver Capability, we shall allow VSC SDP to be used. [How] The Extended Receiver Capability field shall check the EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT bit in the TRAINING_AUX_RD_INTERVAL register. Removed DPCD rev checking for VSC SDP. Signed-off-by: Derek Lai Reviewed-by: Wenjing Liu Acked-by: Rodrigo Siqueira Acked-by: Tony Cheng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +--- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- 2 files changed, 2 insertions(+), 4 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 a19a3ed3ca16..58bcf9afca6f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4573,10 +4573,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, stream->use_vsc_sdp_for_colorimetry = aconnector->dc_sink->is_vsc_sdp_colorimetry_supported; } else { - if (stream->link->dpcd_caps.dpcd_rev.raw >= 0x14 && - stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) { + if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) stream->use_vsc_sdp_for_colorimetry = true; - } } mod_build_vsc_infopacket(stream, &stream->vsc_infopacket); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index baad087c4f71..4054df1cd1a5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -3376,7 +3376,7 @@ static bool retrieve_link_cap(struct dc_link *link) link->dpcd_caps.dpcd_rev.raw = dpcd_data[DP_DPCD_REV - DP_DPCD_REV]; - if (link->dpcd_caps.dpcd_rev.raw >= 0x14) { + if (link->dpcd_caps.ext_receiver_cap_field_present) { for (i = 0; i < read_dpcd_retry_cnt; i++) { status = core_link_read_dpcd( link, -- cgit v1.2.3-70-g09d2 From 4b7da34bd78803d83ebe82a56093c0877e15a243 Mon Sep 17 00:00:00 2001 From: Stylon Wang Date: Fri, 12 Jun 2020 19:04:18 +0800 Subject: drm/amd/display: Fix ineffective setting of max bpc property [Why] Regression was introduced where setting max bpc property has no effect on the atomic check and final commit. It has the same effect as max bpc being stuck at 8. [How] Correctly propagate max bpc with the new connector state. Signed-off-by: Stylon Wang Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 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 58bcf9afca6f..06a5e8cb3d00 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5049,7 +5049,8 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, struct drm_connector *connector = &aconnector->base; struct amdgpu_device *adev = connector->dev->dev_private; struct dc_stream_state *stream; - int requested_bpc = connector->state ? connector->state->max_requested_bpc : 8; + const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL; + int requested_bpc = drm_state ? drm_state->max_requested_bpc : 8; enum dc_status dc_result = DC_OK; do { -- cgit v1.2.3-70-g09d2 From 75e1658ea0ea78a534b973aefa6a175277fff664 Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Thu, 25 Jun 2020 15:35:07 +0200 Subject: drm/amdgpu: call release_firmware() without a NULL check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The release_firmware() function is NULL tolerant so we do not need to check for NULL param before calling it. Signed-off-by: Nirmoy Das Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 ++---- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 6 ++---- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 4 ++-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 ++++-------- 6 files changed, 14 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2858c09fd8c0..a649e40fd96f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3380,10 +3380,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev) amdgpu_pm_sysfs_fini(adev); amdgpu_fbdev_fini(adev); r = amdgpu_device_ip_fini(adev); - if (adev->firmware.gpu_info_fw) { - release_firmware(adev->firmware.gpu_info_fw); - adev->firmware.gpu_info_fw = NULL; - } + release_firmware(adev->firmware.gpu_info_fw); + adev->firmware.gpu_info_fw = NULL; adev->accel_working = false; /* free i2c buses */ if (!amdgpu_device_has_dc_support(adev)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 0723dee2958b..9342a9e8cadf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -196,10 +196,8 @@ static int psp_sw_fini(void *handle) adev->psp.sos_fw = NULL; release_firmware(adev->psp.asd_fw); adev->psp.asd_fw = NULL; - if (adev->psp.ta_fw) { - release_firmware(adev->psp.ta_fw); - adev->psp.ta_fw = NULL; - } + release_firmware(adev->psp.ta_fw); + adev->psp.ta_fw = NULL; if (adev->asic_type == CHIP_NAVI10) psp_sysfs_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index aaa90a181cad..856c50386c86 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -559,8 +559,8 @@ static void sdma_v4_0_destroy_inst_ctx(struct amdgpu_device *adev) int i; for (i = 0; i < adev->sdma.num_instances; i++) { - if (adev->sdma.instance[i].fw != NULL) - release_firmware(adev->sdma.instance[i].fw); + release_firmware(adev->sdma.instance[i].fw); + adev->sdma.instance[i].fw = NULL; /* arcturus shares the same FW memory across all SDMA isntances */ diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c index 6751ad69ed90..1baeddf2f1e6 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c @@ -1300,8 +1300,8 @@ static int sdma_v5_0_sw_fini(void *handle) int i; for (i = 0; i < adev->sdma.num_instances; i++) { - if (adev->sdma.instance[i].fw != NULL) - release_firmware(adev->sdma.instance[i].fw); + release_firmware(adev->sdma.instance[i].fw); + adev->sdma.instance[i].fw = NULL; amdgpu_ring_fini(&adev->sdma.instance[i].ring); } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c index 95751e7bdfe8..318d32e2bbf6 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c @@ -115,8 +115,8 @@ static void sdma_v5_2_destroy_inst_ctx(struct amdgpu_device *adev) int i; for (i = 0; i < adev->sdma.num_instances; i++) { - if (adev->sdma.instance[i].fw != NULL) - release_firmware(adev->sdma.instance[i].fw); + release_firmware(adev->sdma.instance[i].fw); + adev->sdma.instance[i].fw = NULL; if (adev->asic_type == CHIP_SIENNA_CICHLID) break; 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 06a5e8cb3d00..365c675aa159 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1318,15 +1318,11 @@ static int dm_sw_fini(void *handle) adev->dm.dmub_srv = NULL; } - if (adev->dm.dmub_fw) { - release_firmware(adev->dm.dmub_fw); - adev->dm.dmub_fw = NULL; - } + release_firmware(adev->dm.dmub_fw); + adev->dm.dmub_fw = NULL; - if(adev->dm.fw_dmcu) { - release_firmware(adev->dm.fw_dmcu); - adev->dm.fw_dmcu = NULL; - } + release_firmware(adev->dm.fw_dmcu); + adev->dm.fw_dmcu = NULL; return 0; } -- cgit v1.2.3-70-g09d2 From ecc874a6e7cb398b363b4e078fca4c097cb286ab Mon Sep 17 00:00:00 2001 From: "Pierre-Loup A. Griffais" Date: Thu, 12 Sep 2019 09:44:04 -0700 Subject: drm/amd/display: Create plane rotation property It's otherwise properly supported, just needs exposing to userspace. Reviewed-by: Harry Wentland Signed-off-by: Pierre-Loup A. Griffais Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++++++++ 1 file changed, 8 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 9b1f5244ec87..f4d983947c17 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5866,6 +5866,7 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, uint32_t formats[32]; int num_formats; int res = -EPERM; + unsigned int supported_rotations; num_formats = get_plane_formats(plane, plane_cap, formats, ARRAY_SIZE(formats)); @@ -5900,6 +5901,13 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE); } + supported_rotations = + DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | + DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270; + + drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, + supported_rotations); + drm_plane_helper_add(plane, &dm_plane_helper_funcs); /* Create (reset) the plane state */ -- cgit v1.2.3-70-g09d2 From 8a488f5df32a0483010959c9265bc3484eca83f0 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Fri, 26 Jun 2020 10:27:31 -0400 Subject: drm/amd/display: Remove VSC infoframe dep on DMCU [Why] VSC infoframe is needed for PSR. Previously only DMCU controller supported PSR. Now DMUB also implements PSR. [How] Remove VSC infoframe dependency on DMCU. Signed-off-by: Roman Li Reviewed-by: Rodrigo Siqueira Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 30 ++++++++++------------- 1 file changed, 13 insertions(+), 17 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 f4d983947c17..0e5d99a85307 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4556,24 +4556,20 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket, false, false); - if (stream->link->psr_settings.psr_feature_enabled) { - struct dc *core_dc = stream->link->ctx->dc; - - if (dc_is_dmcu_initialized(core_dc)) { - // - // should decide stream support vsc sdp colorimetry capability - // before building vsc info packet - // - stream->use_vsc_sdp_for_colorimetry = false; - if (aconnector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - stream->use_vsc_sdp_for_colorimetry = - aconnector->dc_sink->is_vsc_sdp_colorimetry_supported; - } else { - if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) - stream->use_vsc_sdp_for_colorimetry = true; - } - mod_build_vsc_infopacket(stream, &stream->vsc_infopacket); + if (stream->link->psr_settings.psr_feature_enabled) { + // + // should decide stream support vsc sdp colorimetry capability + // before building vsc info packet + // + stream->use_vsc_sdp_for_colorimetry = false; + if (aconnector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + stream->use_vsc_sdp_for_colorimetry = + aconnector->dc_sink->is_vsc_sdp_colorimetry_supported; + } else { + if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) + stream->use_vsc_sdp_for_colorimetry = true; } + mod_build_vsc_infopacket(stream, &stream->vsc_infopacket); } finish: dc_sink_release(sink); -- cgit v1.2.3-70-g09d2 From 3b2e973dff59d88bee1d814ddf8762a24fc02b60 Mon Sep 17 00:00:00 2001 From: Aaron Ma Date: Wed, 8 Jul 2020 04:16:22 -0400 Subject: drm/amd/display: add dmcub check on RENOIR RENOIR loads dmub fw not dmcu, check dmcu only will prevent loading iram, it breaks backlight control. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=208277 Acked-by: Alex Deucher Reviewed-by: Nicholas Kazlauskas Signed-off-by: Aaron Ma Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- 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 10ac8076d4f2..db5e0bb0d935 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1358,7 +1358,7 @@ static int dm_late_init(void *handle) struct dmcu *dmcu = NULL; bool ret; - if (!adev->dm.fw_dmcu) + if (!adev->dm.fw_dmcu && !adev->dm.dmub_fw) return detect_mst_link_for_all_connectors(adev->ddev); dmcu = adev->dm.dc->res_pool->dmcu; -- cgit v1.2.3-70-g09d2 From f74367e492ba24be43ba0f440c6bac98a6f3b277 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 10 Jul 2020 17:50:00 -0400 Subject: drm/amdgpu/display: create fake mst encoders ahead of time (v4) Prevents a warning in the MST create connector case. v2: create global fake encoders rather per connector fake encoders to avoid running out of encoder indices. v3: use the actual number of crtcs on the asic rather than the max to conserve encoders. v4: v3 plus missing hunk I forgot to git add. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1108 Fixes: c6385e503aeaf9 ("drm/amdgpu: drop legacy drm load and unload callbacks") Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 11 ++++- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 53 +++++++++++----------- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.h | 3 ++ 4 files changed, 48 insertions(+), 28 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 0e5d99a85307..6f937e25a62c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -978,6 +978,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) /* Update the actual used number of crtc */ adev->mode_info.num_crtc = adev->dm.display_indexes_num; + /* create fake encoders for MST */ + dm_dp_create_fake_mst_encoders(adev); + /* TODO: Add_display_info? */ /* TODO use dynamic cursor width */ @@ -1001,6 +1004,12 @@ error: static void amdgpu_dm_fini(struct amdgpu_device *adev) { + int i; + + for (i = 0; i < adev->dm.display_indexes_num; i++) { + drm_encoder_cleanup(&adev->dm.mst_encoders[i].base); + } + amdgpu_dm_audio_fini(adev); amdgpu_dm_destroy_drm_device(&adev->dm); 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 86c132ddc452..3f50328fe537 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -43,6 +43,9 @@ */ #define AMDGPU_DM_MAX_DISPLAY_INDEX 31 + +#define AMDGPU_DM_MAX_CRTC 6 + /* #include "include/amdgpu_dal_power_if.h" #include "amdgpu_dm_irq.h" @@ -330,6 +333,13 @@ struct amdgpu_display_manager { * available in FW */ const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box; + + /** + * @mst_encoders: + * + * fake encoders used for DP MST. + */ + struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC]; }; struct amdgpu_dm_connector { @@ -358,7 +368,6 @@ struct amdgpu_dm_connector { struct amdgpu_dm_dp_aux dm_dp_aux; struct drm_dp_mst_port *port; struct amdgpu_dm_connector *mst_port; - struct amdgpu_encoder *mst_encoder; struct drm_dp_aux *dsc_aux; /* TODO see if we can merge with ddc_bus or make a dm_connector */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index cf15248739f7..0affd1997fe7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -95,7 +95,6 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct amdgpu_encoder *amdgpu_encoder = aconnector->mst_encoder; if (aconnector->dc_sink) { dc_link_remove_remote_sink(aconnector->dc_link, @@ -105,8 +104,6 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector) kfree(aconnector->edid); - drm_encoder_cleanup(&amdgpu_encoder->base); - kfree(amdgpu_encoder); drm_connector_cleanup(connector); drm_dp_mst_put_port_malloc(aconnector->port); kfree(aconnector); @@ -243,7 +240,11 @@ static struct drm_encoder * dm_mst_atomic_best_encoder(struct drm_connector *connector, struct drm_connector_state *connector_state) { - return &to_amdgpu_dm_connector(connector)->mst_encoder->base; + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(connector_state->crtc); + + return &adev->dm.mst_encoders[acrtc->crtc_id].base; } static int @@ -306,31 +307,27 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { .destroy = amdgpu_dm_encoder_destroy, }; -static struct amdgpu_encoder * -dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector) +void +dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev) { - struct drm_device *dev = connector->base.dev; - struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_encoder *amdgpu_encoder; - struct drm_encoder *encoder; - - amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL); - if (!amdgpu_encoder) - return NULL; + struct drm_device *dev = adev->ddev; + int i; - encoder = &amdgpu_encoder->base; - encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); + for (i = 0; i < adev->dm.display_indexes_num; i++) { + struct amdgpu_encoder *amdgpu_encoder = &adev->dm.mst_encoders[i]; + struct drm_encoder *encoder = &amdgpu_encoder->base; - drm_encoder_init( - dev, - &amdgpu_encoder->base, - &amdgpu_dm_encoder_funcs, - DRM_MODE_ENCODER_DPMST, - NULL); + encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); - drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs); + drm_encoder_init( + dev, + &amdgpu_encoder->base, + &amdgpu_dm_encoder_funcs, + DRM_MODE_ENCODER_DPMST, + NULL); - return amdgpu_encoder; + drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs); + } } static struct drm_connector * @@ -343,6 +340,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct amdgpu_device *adev = dev->dev_private; struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; + int i; aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); if (!aconnector) @@ -369,9 +367,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, master->dc_link, master->connector_id); - aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master); - drm_connector_attach_encoder(&aconnector->base, - &aconnector->mst_encoder->base); + for (i = 0; i < adev->dm.display_indexes_num; i++) { + drm_connector_attach_encoder(&aconnector->base, + &adev->dm.mst_encoders[i].base); + } connector->max_bpc_property = master->base.max_bpc_property; if (connector->max_bpc_property) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index d2c56579a2cc..b38bd68121ce 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -35,6 +35,9 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, struct amdgpu_dm_connector *aconnector, int link_index); +void +dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev); + #if defined(CONFIG_DRM_AMD_DC_DCN) bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, struct dc_state *dc_state); -- cgit v1.2.3-70-g09d2 From ec11fe3705a7d434ec3493bdaddb9b6367e7366a Mon Sep 17 00:00:00 2001 From: hersen wu Date: Mon, 22 Jun 2020 13:29:16 -0400 Subject: drm/amd/display: OLED panel backlight adjust not work with external display connected [Why] amdgpu_dm->backlight_caps is for single eDP only. the caps are upddated for very connector. Real eDP caps will be overwritten by other external display. For OLED panel, caps->aux_support is set to 1 for OLED pnael. after external connected, caps+.aux_support is set to 0. This causes OLED backlight adjustment not work. [How] within update_conector_ext_caps, backlight caps will be updated only for eDP connector. Cc: stable@vger.kernel.org Signed-off-by: hersen wu Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++++ 1 file changed, 5 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 6f937e25a62c..9c283531e1a2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2028,6 +2028,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) struct amdgpu_display_manager *dm; struct drm_connector *conn_base; struct amdgpu_device *adev; + struct dc_link *link = NULL; static const u8 pre_computed_values[] = { 50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69, 71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98}; @@ -2035,6 +2036,10 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) if (!aconnector || !aconnector->dc_link) return; + link = aconnector->dc_link; + if (link->connector_signal != SIGNAL_TYPE_EDP) + return; + conn_base = &aconnector->base; adev = conn_base->dev->dev_private; dm = &adev->dm; -- cgit v1.2.3-70-g09d2 From 8fe684e97c86e35f7e5128e756369df5b72e3dd8 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Mon, 13 Jul 2020 10:41:23 -0400 Subject: drm/amd/display: Allow for vblank enabled with no active planes [Why] CRC capture doesn't work when the active plane count is 0 since we currently tie both vblank and pageflip interrupts to active_plane_count greater than 0. [How] The frontend is what generates the vblank interrupts while the backend is what generates pageflip interrupts. Both have a requirement for the CRTC to be active, so control the overall interrupt state based on that instead. Pageflip interrupts need to be enabled based on active plane count, but we actually rely on power gating to take care of disabling the interrupt for us on pipes that can be power gated. For pipes that can't be power gated it's still fine to leave it enabled since the interrupt only triggers after the address has been written to that particular pipe - which we won't be doing without an active plane. The issue we had before with this setup was that we couldn't force the state back on. We were essentially manipulating the refcount to enable or disable as needed in a two pass approach. However, there is a function that solves this problem more elegantly: amdgpu_irq_update() will unconditionally call the set based on what it thinks the current enablement state is. This leaves two future TODO items for our IRQ handling: - Disabling IRQs in commit tail instead of atomic commit - Mapping the pageflip interrupt to VUPDATE or something that's tied to the frontend instead of the backend since the mapping to CRTC is not correct Signed-off-by: Nicholas Kazlauskas Reviewed-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 168 ++++++++++------------ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 - 2 files changed, 78 insertions(+), 91 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 9c283531e1a2..ba0f53816057 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4651,7 +4651,6 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) } state->active_planes = cur->active_planes; - state->interrupts_enabled = cur->interrupts_enabled; state->vrr_params = cur->vrr_params; state->vrr_infopacket = cur->vrr_infopacket; state->abm_level = cur->abm_level; @@ -5312,29 +5311,19 @@ static int count_crtc_active_planes(struct drm_crtc_state *new_crtc_state) return num_active; } -/* - * Sets whether interrupts should be enabled on a specific CRTC. - * We require that the stream be enabled and that there exist active - * DC planes on the stream. - */ -static void -dm_update_crtc_interrupt_state(struct drm_crtc *crtc, - struct drm_crtc_state *new_crtc_state) +static void dm_update_crtc_active_planes(struct drm_crtc *crtc, + struct drm_crtc_state *new_crtc_state) { struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); dm_new_crtc_state->active_planes = 0; - dm_new_crtc_state->interrupts_enabled = false; if (!dm_new_crtc_state->stream) return; dm_new_crtc_state->active_planes = count_crtc_active_planes(new_crtc_state); - - dm_new_crtc_state->interrupts_enabled = - dm_new_crtc_state->active_planes > 0; } static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, @@ -5345,13 +5334,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); int ret = -EINVAL; - /* - * Update interrupt state for the CRTC. This needs to happen whenever - * the CRTC has changed or whenever any of its planes have changed. - * Atomic check satisfies both of these requirements since the CRTC - * is added to the state by DRM during drm_atomic_helper_check_planes. - */ - dm_update_crtc_interrupt_state(crtc, state); + dm_update_crtc_active_planes(crtc, state); if (unlikely(!dm_crtc_state->stream && modeset_required(state, NULL, dm_crtc_state->stream))) { @@ -6462,8 +6445,10 @@ static void manage_dm_interrupts(struct amdgpu_device *adev, bool enable) { /* - * this is not correct translation but will work as soon as VBLANK - * constant is the same as PFLIP + * We have no guarantee that the frontend index maps to the same + * backend index - some even map to more than one. + * + * TODO: Use a different interrupt or check DC itself for the mapping. */ int irq_type = amdgpu_display_crtc_idx_to_irq_type( @@ -6486,6 +6471,19 @@ static void manage_dm_interrupts(struct amdgpu_device *adev, } } +static void dm_update_pflip_irq_state(struct amdgpu_device *adev, + struct amdgpu_crtc *acrtc) +{ + int irq_type = + amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id); + + /** + * This reads the current state for the IRQ and force reapplies + * the setting to hardware. + */ + amdgpu_irq_update(adev, &adev->pageflip_irq, irq_type); +} + static bool is_scaling_state_different(const struct dm_connector_state *dm_state, const struct dm_connector_state *old_dm_state) @@ -7070,7 +7068,16 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, usleep_range(1000, 1100); } - if (acrtc_attach->base.state->event) { + /** + * Prepare the flip event for the pageflip interrupt to handle. + * + * This only works in the case where we've already turned on the + * appropriate hardware blocks (eg. HUBP) so in the transition case + * from 0 -> n planes we have to skip a hardware generated event + * and rely on sending it from software. + */ + if (acrtc_attach->base.state->event && + acrtc_state->active_planes > 0) { drm_crtc_vblank_get(pcrtc); spin_lock_irqsave(&pcrtc->dev->event_lock, flags); @@ -7139,6 +7146,24 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, &bundle->stream_update, dc_state); + /** + * Enable or disable the interrupts on the backend. + * + * Most pipes are put into power gating when unused. + * + * When power gating is enabled on a pipe we lose the + * interrupt enablement state when power gating is disabled. + * + * So we need to update the IRQ control state in hardware + * whenever the pipe turns on (since it could be previously + * power gated) or off (since some pipes can't be power gated + * on some ASICs). + */ + if (dm_old_crtc_state->active_planes != acrtc_state->active_planes) + dm_update_pflip_irq_state( + (struct amdgpu_device *)dev->dev_private, + acrtc_attach); + if ((acrtc_state->update_type > UPDATE_TYPE_FAST) && acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED && !acrtc_state->stream->link->psr_settings.psr_feature_enabled) @@ -7239,64 +7264,6 @@ static void amdgpu_dm_commit_audio(struct drm_device *dev, } } -/* - * Enable interrupts on CRTCs that are newly active, undergone - * a modeset, or have active planes again. - * - * Done in two passes, based on the for_modeset flag: - * Pass 1: For CRTCs going through modeset - * Pass 2: For CRTCs going from 0 to n active planes - * - * Interrupts can only be enabled after the planes are programmed, - * so this requires a two-pass approach since we don't want to - * just defer the interrupts until after commit planes every time. - */ -static void amdgpu_dm_enable_crtc_interrupts(struct drm_device *dev, - struct drm_atomic_state *state, - bool for_modeset) -{ - struct amdgpu_device *adev = dev->dev_private; - struct drm_crtc *crtc; - struct drm_crtc_state *old_crtc_state, *new_crtc_state; - int i; -#ifdef CONFIG_DEBUG_FS - enum amdgpu_dm_pipe_crc_source source; -#endif - - for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct dm_crtc_state *dm_new_crtc_state = - to_dm_crtc_state(new_crtc_state); - struct dm_crtc_state *dm_old_crtc_state = - to_dm_crtc_state(old_crtc_state); - bool modeset = drm_atomic_crtc_needs_modeset(new_crtc_state); - bool run_pass; - - run_pass = (for_modeset && modeset) || - (!for_modeset && !modeset && - !dm_old_crtc_state->interrupts_enabled); - - if (!run_pass) - continue; - - if (!dm_new_crtc_state->interrupts_enabled) - continue; - - manage_dm_interrupts(adev, acrtc, true); - -#ifdef CONFIG_DEBUG_FS - /* The stream has changed so CRC capture needs to re-enabled. */ - source = dm_new_crtc_state->crc_src; - if (amdgpu_dm_is_valid_crc_source(source)) { - amdgpu_dm_crtc_configure_crc_source( - crtc, dm_new_crtc_state, - dm_new_crtc_state->crc_src); - } -#endif - } -} - /* * amdgpu_dm_crtc_copy_transient_flags - copy mirrored flags from DRM to DC * @crtc_state: the DRM CRTC state @@ -7336,12 +7303,10 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, * in atomic check. */ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - struct dm_crtc_state *dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); - struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - if (dm_old_crtc_state->interrupts_enabled && - (!dm_new_crtc_state->interrupts_enabled || + if (old_crtc_state->active && + (!new_crtc_state->active || drm_atomic_crtc_needs_modeset(new_crtc_state))) manage_dm_interrupts(adev, acrtc, false); } @@ -7620,8 +7585,34 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm_new_crtc_state); } - /* Enable interrupts for CRTCs going through a modeset. */ - amdgpu_dm_enable_crtc_interrupts(dev, state, true); + /** + * Enable interrupts for CRTCs that are newly enabled or went through + * a modeset. It was intentionally deferred until after the front end + * state was modified to wait until the OTG was on and so the IRQ + * handlers didn't access stale or invalid state. + */ + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + if (new_crtc_state->active && + (!old_crtc_state->active || + drm_atomic_crtc_needs_modeset(new_crtc_state))) { + manage_dm_interrupts(adev, acrtc, true); +#ifdef CONFIG_DEBUG_FS + /** + * Frontend may have changed so reapply the CRC capture + * settings for the stream. + */ + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + + if (amdgpu_dm_is_valid_crc_source(dm_new_crtc_state->crc_src)) { + amdgpu_dm_crtc_configure_crc_source( + crtc, dm_new_crtc_state, + dm_new_crtc_state->crc_src); + } +#endif + } + } for_each_new_crtc_in_state(state, crtc, new_crtc_state, j) if (new_crtc_state->async_flip) @@ -7636,9 +7627,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm, crtc, wait_for_vblank); } - /* Enable interrupts for CRTCs going from 0 to n active planes. */ - amdgpu_dm_enable_crtc_interrupts(dev, state, false); - /* Update audio instances for each connector. */ amdgpu_dm_commit_audio(dev, state); 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 3f50328fe537..dd1559c743c2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -414,7 +414,6 @@ struct dm_crtc_state { int update_type; int active_planes; - bool interrupts_enabled; int crc_skip_count; enum amdgpu_dm_pipe_crc_source crc_src; -- cgit v1.2.3-70-g09d2 From 3168470142e0a82b5732c04ed4c031a9322ae170 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 10 Jul 2020 17:50:00 -0400 Subject: drm/amdgpu/display: create fake mst encoders ahead of time (v4) Prevents a warning in the MST create connector case. v2: create global fake encoders rather per connector fake encoders to avoid running out of encoder indices. v3: use the actual number of crtcs on the asic rather than the max to conserve encoders. v4: v3 plus missing hunk I forgot to git add. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1108 Fixes: c6385e503aeaf9 ("drm/amdgpu: drop legacy drm load and unload callbacks") Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 5.7.x --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 11 ++++- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 53 +++++++++++----------- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.h | 3 ++ 4 files changed, 48 insertions(+), 28 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 db5e0bb0d935..b30e31444aef 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -974,6 +974,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) /* Update the actual used number of crtc */ adev->mode_info.num_crtc = adev->dm.display_indexes_num; + /* create fake encoders for MST */ + dm_dp_create_fake_mst_encoders(adev); + /* TODO: Add_display_info? */ /* TODO use dynamic cursor width */ @@ -997,6 +1000,12 @@ error: static void amdgpu_dm_fini(struct amdgpu_device *adev) { + int i; + + for (i = 0; i < adev->dm.display_indexes_num; i++) { + drm_encoder_cleanup(&adev->dm.mst_encoders[i].base); + } + amdgpu_dm_audio_fini(adev); amdgpu_dm_destroy_drm_device(&adev->dm); 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 d61186ff411d..648180ccdc2e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -43,6 +43,9 @@ */ #define AMDGPU_DM_MAX_DISPLAY_INDEX 31 + +#define AMDGPU_DM_MAX_CRTC 6 + /* #include "include/amdgpu_dal_power_if.h" #include "amdgpu_dm_irq.h" @@ -328,6 +331,13 @@ struct amdgpu_display_manager { * available in FW */ const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box; + + /** + * @mst_encoders: + * + * fake encoders used for DP MST. + */ + struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC]; }; struct amdgpu_dm_connector { @@ -356,7 +366,6 @@ struct amdgpu_dm_connector { struct amdgpu_dm_dp_aux dm_dp_aux; struct drm_dp_mst_port *port; struct amdgpu_dm_connector *mst_port; - struct amdgpu_encoder *mst_encoder; struct drm_dp_aux *dsc_aux; /* TODO see if we can merge with ddc_bus or make a dm_connector */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index ae0a7ef1d595..e5ecc5affa1e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -95,7 +95,6 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - struct amdgpu_encoder *amdgpu_encoder = aconnector->mst_encoder; if (aconnector->dc_sink) { dc_link_remove_remote_sink(aconnector->dc_link, @@ -105,8 +104,6 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector) kfree(aconnector->edid); - drm_encoder_cleanup(&amdgpu_encoder->base); - kfree(amdgpu_encoder); drm_connector_cleanup(connector); drm_dp_mst_put_port_malloc(aconnector->port); kfree(aconnector); @@ -243,7 +240,11 @@ static struct drm_encoder * dm_mst_atomic_best_encoder(struct drm_connector *connector, struct drm_connector_state *connector_state) { - return &to_amdgpu_dm_connector(connector)->mst_encoder->base; + struct drm_device *dev = connector->dev; + struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(connector_state->crtc); + + return &adev->dm.mst_encoders[acrtc->crtc_id].base; } static int @@ -306,31 +307,27 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { .destroy = amdgpu_dm_encoder_destroy, }; -static struct amdgpu_encoder * -dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector) +void +dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev) { - struct drm_device *dev = connector->base.dev; - struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_encoder *amdgpu_encoder; - struct drm_encoder *encoder; - - amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL); - if (!amdgpu_encoder) - return NULL; + struct drm_device *dev = adev->ddev; + int i; - encoder = &amdgpu_encoder->base; - encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); + for (i = 0; i < adev->dm.display_indexes_num; i++) { + struct amdgpu_encoder *amdgpu_encoder = &adev->dm.mst_encoders[i]; + struct drm_encoder *encoder = &amdgpu_encoder->base; - drm_encoder_init( - dev, - &amdgpu_encoder->base, - &amdgpu_dm_encoder_funcs, - DRM_MODE_ENCODER_DPMST, - NULL); + encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev); - drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs); + drm_encoder_init( + dev, + &amdgpu_encoder->base, + &amdgpu_dm_encoder_funcs, + DRM_MODE_ENCODER_DPMST, + NULL); - return amdgpu_encoder; + drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs); + } } static struct drm_connector * @@ -343,6 +340,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct amdgpu_device *adev = dev->dev_private; struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; + int i; aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); if (!aconnector) @@ -369,9 +367,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, master->dc_link, master->connector_id); - aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master); - drm_connector_attach_encoder(&aconnector->base, - &aconnector->mst_encoder->base); + for (i = 0; i < adev->dm.display_indexes_num; i++) { + drm_connector_attach_encoder(&aconnector->base, + &adev->dm.mst_encoders[i].base); + } connector->max_bpc_property = master->base.max_bpc_property; if (connector->max_bpc_property) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index d2c56579a2cc..b38bd68121ce 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -35,6 +35,9 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, struct amdgpu_dm_connector *aconnector, int link_index); +void +dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev); + #if defined(CONFIG_DRM_AMD_DC_DCN) bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, struct dc_state *dc_state); -- cgit v1.2.3-70-g09d2 From b448d30b0c303d5454ea572b772d1ffae96bc6e7 Mon Sep 17 00:00:00 2001 From: hersen wu Date: Mon, 22 Jun 2020 13:29:16 -0400 Subject: drm/amd/display: OLED panel backlight adjust not work with external display connected [Why] amdgpu_dm->backlight_caps is for single eDP only. the caps are upddated for very connector. Real eDP caps will be overwritten by other external display. For OLED panel, caps->aux_support is set to 1 for OLED pnael. after external connected, caps+.aux_support is set to 0. This causes OLED backlight adjustment not work. [How] within update_conector_ext_caps, backlight caps will be updated only for eDP connector. Cc: stable@vger.kernel.org Signed-off-by: hersen wu Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++++ 1 file changed, 5 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 b30e31444aef..86ffa0c2880f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2019,6 +2019,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) struct amdgpu_display_manager *dm; struct drm_connector *conn_base; struct amdgpu_device *adev; + struct dc_link *link = NULL; static const u8 pre_computed_values[] = { 50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69, 71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98}; @@ -2026,6 +2027,10 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) if (!aconnector || !aconnector->dc_link) return; + link = aconnector->dc_link; + if (link->connector_signal != SIGNAL_TYPE_EDP) + return; + conn_base = &aconnector->base; adev = conn_base->dev->dev_private; dm = &adev->dm; -- cgit v1.2.3-70-g09d2 From a6c5308f2a7ad2a79fb6fd60b52367c51434c04a Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Wed, 8 Jul 2020 17:11:12 -0400 Subject: drm/amd/display: add DC support for navy flounder Plumb DC support for navy flounder through. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + drivers/gpu/drm/amd/amdgpu/nv.c | 4 ++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 31a7d78cea7c..aa5b54e5a1d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2808,6 +2808,7 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) #endif #if defined(CONFIG_DRM_AMD_DC_DCN3_0) case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: #endif return amdgpu_dc != 0; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 25a75cfbe60a..dc4c360e14b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -534,6 +534,10 @@ int nv_set_ip_blocks(struct amdgpu_device *adev) amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_device_ip_block_add(adev, &dm_ip_block); +#endif amdgpu_device_ip_block_add(adev, &gfx_v10_0_ip_block); amdgpu_device_ip_block_add(adev, &sdma_v5_2_ip_block); amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block); 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 ba0f53816057..02e335a4468e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1085,6 +1085,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev) case CHIP_RENOIR: #if defined(CONFIG_DRM_AMD_DC_DCN3_0) case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: #endif return 0; case CHIP_NAVI12: @@ -1184,6 +1185,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) break; #if defined(CONFIG_DRM_AMD_DC_DCN3_0) case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: dmub_asic = DMUB_ASIC_DCN30; fw_name_dmub = FIRMWARE_SIENNA_CICHLID_DMUB; break; @@ -3230,6 +3232,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case CHIP_RENOIR: #if defined(CONFIG_DRM_AMD_DC_DCN3_0) case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: #endif if (dcn10_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); @@ -3387,6 +3390,7 @@ static int dm_early_init(void *handle) case CHIP_NAVI12: #if defined(CONFIG_DRM_AMD_DC_DCN3_0) case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: #endif adev->mode_info.num_crtc = 6; adev->mode_info.num_hpd = 6; @@ -3710,6 +3714,7 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev, adev->asic_type == CHIP_NAVI12 || #if defined(CONFIG_DRM_AMD_DC_DCN3_0) adev->asic_type == CHIP_SIENNA_CICHLID || + adev->asic_type == CHIP_NAVY_FLOUNDER || #endif adev->asic_type == CHIP_RENOIR || adev->asic_type == CHIP_RAVEN) { @@ -3731,9 +3736,9 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev, tiling_info->gfx9.shaderEnable = 1; #ifdef CONFIG_DRM_AMD_DC_DCN3_0 - if (adev->asic_type == CHIP_SIENNA_CICHLID) + if (adev->asic_type == CHIP_SIENNA_CICHLID || + adev->asic_type == CHIP_NAVY_FLOUNDER) tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs; - #endif ret = fill_plane_dcc_attributes(adev, afb, format, rotation, plane_size, tiling_info, -- cgit v1.2.3-70-g09d2 From e7a95eea22505d1e991141b289af35d485937c03 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 7 Jul 2020 15:52:39 +0800 Subject: drm/amd/powerplay: maximum code sharing around watermarks setting Maximum code sharing. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 +--- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 27 +++-- drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 2 +- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 102 ++++++++++--------- drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 85 ++++++++-------- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 111 ++++++++++----------- drivers/gpu/drm/amd/powerplay/smu_internal.h | 2 +- 7 files changed, 166 insertions(+), 182 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 02e335a4468e..5023df37b921 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1486,23 +1486,12 @@ static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev) return 0; } - mutex_lock(&smu->mutex); - - /* pass data to smu controller */ - if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && - !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { - ret = smu_write_watermarks_table(smu); - - if (ret) { - mutex_unlock(&smu->mutex); - DRM_ERROR("Failed to update WMTABLE!\n"); - return ret; - } - smu->watermarks_bitmap |= WATERMARKS_LOADED; + ret = smu_write_watermarks_table(smu); + if (ret) { + DRM_ERROR("Failed to update WMTABLE!\n"); + return ret; } - mutex_unlock(&smu->mutex); - return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 6006f7a938b3..b9ff398bf2a9 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -1706,35 +1706,34 @@ int smu_allow_xgmi_power_down(struct smu_context *smu, bool en) int smu_write_watermarks_table(struct smu_context *smu) { - void *watermarks_table = smu->smu_table.watermarks_table; + int ret = 0; - if (!watermarks_table) - return -EINVAL; + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; - return smu_update_table(smu, - SMU_TABLE_WATERMARKS, - 0, - watermarks_table, - true); + mutex_lock(&smu->mutex); + + ret = smu_set_watermarks_table(smu, NULL); + + mutex_unlock(&smu->mutex); + + return ret; } int smu_set_watermarks_for_clock_ranges(struct smu_context *smu, struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) { - void *table = smu->smu_table.watermarks_table; + int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - if (!table) - return -EINVAL; - mutex_lock(&smu->mutex); if (!smu->disable_watermark && smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { - smu_set_watermarks_table(smu, table, clock_ranges); + ret = smu_set_watermarks_table(smu, clock_ranges); if (!(smu->watermarks_bitmap & WATERMARKS_EXIST)) { smu->watermarks_bitmap |= WATERMARKS_EXIST; @@ -1744,7 +1743,7 @@ int smu_set_watermarks_for_clock_ranges(struct smu_context *smu, mutex_unlock(&smu->mutex); - return 0; + return ret; } int smu_set_ac_dc(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index 4f571045f8d6..a8f98f393021 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -493,7 +493,7 @@ struct pptable_funcs { int (*tables_init)(struct smu_context *smu, struct smu_table *tables); int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed); int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed); - int (*set_watermarks_table)(struct smu_context *smu, void *watermarks, + int (*set_watermarks_table)(struct smu_context *smu, struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges); int (*get_thermal_temperature_range)(struct smu_context *smu, struct smu_temperature_range *range); int (*get_uclk_dpm_states)(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states); diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 25ca6c4fbb22..4ea2cd589136 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -1577,67 +1577,65 @@ static int navi10_notify_smc_display_config(struct smu_context *smu) } static int navi10_set_watermarks_table(struct smu_context *smu, - void *watermarks, struct - dm_pp_wm_sets_with_clock_ranges_soc15 - *clock_ranges) + struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) { - int i; + Watermarks_t *table = smu->smu_table.watermarks_table; int ret = 0; - Watermarks_t *table = watermarks; + int i; - if (!table || !clock_ranges) - return -EINVAL; + if (clock_ranges) { + if (clock_ranges->num_wm_dmif_sets > 4 || + clock_ranges->num_wm_mcif_sets > 4) + return -EINVAL; - if (clock_ranges->num_wm_dmif_sets > 4 || - clock_ranges->num_wm_mcif_sets > 4) - return -EINVAL; + for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { + table->WatermarkRow[1][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MinUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MaxUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].WmSetting = (uint8_t) + clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; + } - for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { - table->WatermarkRow[1][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].WmSetting = (uint8_t) - clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; - } + for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { + table->WatermarkRow[0][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MinUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MaxUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].WmSetting = (uint8_t) + clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + } - for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { - table->WatermarkRow[0][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].WmSetting = (uint8_t) - clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + smu->watermarks_bitmap |= WATERMARKS_EXIST; } - smu->watermarks_bitmap |= WATERMARKS_EXIST; - /* pass data to smu controller */ - if (!(smu->watermarks_bitmap & WATERMARKS_LOADED)) { + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && + !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { ret = smu_write_watermarks_table(smu); if (ret) { dev_err(smu->adev->dev, "Failed to update WMTABLE!"); diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index 2e0a54074dbe..8763073efcbb 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -841,59 +841,58 @@ static int renoir_set_performance_level(struct smu_context *smu, */ static int renoir_set_watermarks_table( struct smu_context *smu, - void *watermarks, struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) { - int i; + Watermarks_t *table = smu->smu_table.watermarks_table; int ret = 0; - Watermarks_t *table = watermarks; + int i; - if (!table || !clock_ranges) - return -EINVAL; + if (clock_ranges) { + if (clock_ranges->num_wm_dmif_sets > 4 || + clock_ranges->num_wm_mcif_sets > 4) + return -EINVAL; - if (clock_ranges->num_wm_dmif_sets > 4 || - clock_ranges->num_wm_mcif_sets > 4) - return -EINVAL; + /* save into smu->smu_table.tables[SMU_TABLE_WATERMARKS]->cpu_addr*/ + for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { + table->WatermarkRow[WM_DCFCLK][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz)); + table->WatermarkRow[WM_DCFCLK][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz)); + table->WatermarkRow[WM_DCFCLK][i].MinMclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz)); + table->WatermarkRow[WM_DCFCLK][i].MaxMclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz)); + table->WatermarkRow[WM_DCFCLK][i].WmSetting = (uint8_t) + clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; + } - /* save into smu->smu_table.tables[SMU_TABLE_WATERMARKS]->cpu_addr*/ - for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { - table->WatermarkRow[WM_DCFCLK][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz)); - table->WatermarkRow[WM_DCFCLK][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz)); - table->WatermarkRow[WM_DCFCLK][i].MinMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz)); - table->WatermarkRow[WM_DCFCLK][i].MaxMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz)); - table->WatermarkRow[WM_DCFCLK][i].WmSetting = (uint8_t) - clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; - } + for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { + table->WatermarkRow[WM_SOCCLK][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz)); + table->WatermarkRow[WM_SOCCLK][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz)); + table->WatermarkRow[WM_SOCCLK][i].MinMclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz)); + table->WatermarkRow[WM_SOCCLK][i].MaxMclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz)); + table->WatermarkRow[WM_SOCCLK][i].WmSetting = (uint8_t) + clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + } - for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { - table->WatermarkRow[WM_SOCCLK][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz)); - table->WatermarkRow[WM_SOCCLK][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz)); - table->WatermarkRow[WM_SOCCLK][i].MinMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz)); - table->WatermarkRow[WM_SOCCLK][i].MaxMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz)); - table->WatermarkRow[WM_SOCCLK][i].WmSetting = (uint8_t) - clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + smu->watermarks_bitmap |= WATERMARKS_EXIST; } - smu->watermarks_bitmap |= WATERMARKS_EXIST; - /* pass data to smu controller */ - if (!(smu->watermarks_bitmap & WATERMARKS_LOADED)) { + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && + !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { ret = smu_write_watermarks_table(smu); if (ret) { dev_err(smu->adev->dev, "Failed to update WMTABLE!"); diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index 2d49d3039054..830d93a4f739 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -1380,66 +1380,65 @@ static int sienna_cichlid_notify_smc_display_config(struct smu_context *smu) } static int sienna_cichlid_set_watermarks_table(struct smu_context *smu, - void *watermarks, struct - dm_pp_wm_sets_with_clock_ranges_soc15 - *clock_ranges) + struct dm_pp_wm_sets_with_clock_ranges_soc15 + *clock_ranges) { - int i; + Watermarks_t *table = smu->smu_table.watermarks_table; int ret = 0; - Watermarks_t *table = watermarks; + int i; - if (!table || !clock_ranges) - return -EINVAL; + if (clock_ranges) { + if (clock_ranges->num_wm_dmif_sets > 4 || + clock_ranges->num_wm_mcif_sets > 4) + return -EINVAL; + + for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { + table->WatermarkRow[1][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MinUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MaxUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].WmSetting = (uint8_t) + clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; + } - if (clock_ranges->num_wm_dmif_sets > 4 || - clock_ranges->num_wm_mcif_sets > 4) - return -EINVAL; - - for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { - table->WatermarkRow[1][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].WmSetting = (uint8_t) - clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; - } - - for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { - table->WatermarkRow[0][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].WmSetting = (uint8_t) - clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; - } - - smu->watermarks_bitmap |= WATERMARKS_EXIST; - - if (!(smu->watermarks_bitmap & WATERMARKS_LOADED)) { + for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { + table->WatermarkRow[0][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MinUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MaxUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].WmSetting = (uint8_t) + clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + } + + smu->watermarks_bitmap |= WATERMARKS_EXIST; + } + + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && + !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { ret = smu_write_watermarks_table(smu); if (ret) { dev_err(smu->adev->dev, "Failed to update WMTABLE!"); diff --git a/drivers/gpu/drm/amd/powerplay/smu_internal.h b/drivers/gpu/drm/amd/powerplay/smu_internal.h index a27e05a08e32..78472726e606 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_internal.h +++ b/drivers/gpu/drm/amd/powerplay/smu_internal.h @@ -79,7 +79,7 @@ #define smu_get_current_shallow_sleep_clocks(smu, clocks) smu_ppt_funcs(get_current_shallow_sleep_clocks, 0, smu, clocks) #define smu_dpm_set_vcn_enable(smu, enable) smu_ppt_funcs(dpm_set_vcn_enable, 0, smu, enable) #define smu_dpm_set_jpeg_enable(smu, enable) smu_ppt_funcs(dpm_set_jpeg_enable, 0, smu, enable) -#define smu_set_watermarks_table(smu, tab, clock_ranges) smu_ppt_funcs(set_watermarks_table, 0, smu, tab, clock_ranges) +#define smu_set_watermarks_table(smu, clock_ranges) smu_ppt_funcs(set_watermarks_table, 0, smu, clock_ranges) #define smu_thermal_temperature_range_update(smu, range, rw) smu_ppt_funcs(thermal_temperature_range_update, 0, smu, range, rw) #define smu_register_irq_handler(smu) smu_ppt_funcs(register_irq_handler, 0, smu) #define smu_get_dpm_ultimate_freq(smu, param, min, max) smu_ppt_funcs(get_dpm_ultimate_freq, 0, smu, param, min, max) -- cgit v1.2.3-70-g09d2 From 5cb32419cec0388d2daf04376ab5ebfece3bdc13 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Fri, 10 Jul 2020 10:33:05 -0400 Subject: drm/amd/display: Decouple ABM init from dmcu [Why] With ABM implemented on DMUB the ABM enablement shoudn't be solely rely on dmcu. Otherwise it won't work if dmcu is disabled. [How] 1. Decouple dmcub config copy from dmcu iram copy. 2. Set abm connector property if either dmcu or dmub enabled. Signed-off-by: Roman Li Reviewed-by: Nicholas Kazlauskas Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 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 5023df37b921..3a50043b34b1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1376,7 +1376,7 @@ static int dm_late_init(void *handle) unsigned int linear_lut[16]; int i; struct dmcu *dmcu = NULL; - bool ret; + bool ret = true; if (!adev->dm.fw_dmcu) return detect_mst_link_for_all_connectors(adev->ddev); @@ -1397,7 +1397,14 @@ static int dm_late_init(void *handle) */ params.min_abm_backlight = 0x28F; - ret = dmcu_load_iram(dmcu, params); + /* In the case where abm is implemented on dmcub, + * dmcu object will be null. + * ABM 2.4 and up are implemented on dmcub. + */ + if (dmcu) + ret = dmcu_load_iram(dmcu, params); + else if (adev->dm.dc->ctx->dmub_srv) + ret = dmub_init_abm_config(adev->dm.dc->res_pool->abm, params); if (!ret) return -EINVAL; @@ -6226,7 +6233,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc; if (connector_type == DRM_MODE_CONNECTOR_eDP && - dc_is_dmcu_initialized(adev->dm.dc)) { + (dc_is_dmcu_initialized(adev->dm.dc) || adev->dm.dc->ctx->dmub_srv)) { drm_object_attach_property(&aconnector->base.base, adev->mode_info.abm_level_property, 0); } -- cgit v1.2.3-70-g09d2 From 6d824ed524fc081c8cdb08bed3ec891db3d52d65 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Tue, 7 Jul 2020 16:59:31 -0400 Subject: drm/amd/display: rename dsc extended caps as dsc branch decoder caps [why] The capability fields are reserved for DSC branch only to report the capability related to the branch's DSC decoder. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 4 ++-- drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 10 +++++----- 4 files changed, 10 insertions(+), 10 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 3a50043b34b1..99d052f861c9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4542,7 +4542,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, #if defined(CONFIG_DRM_AMD_DC_DCN) dc_dsc_parse_dsc_dpcd(aconnector->dc_link->ctx->dc, aconnector->dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.raw, - aconnector->dc_link->dpcd_caps.dsc_caps.dsc_ext_caps.raw, + aconnector->dc_link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw, &dsc_caps); #endif link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index af3c4b353c37..5cb7b834e459 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -3519,8 +3519,8 @@ static bool retrieve_link_cap(struct dc_link *link) status = core_link_read_dpcd( link, DP_DSC_BRANCH_OVERALL_THROUGHPUT_0, - link->dpcd_caps.dsc_caps.dsc_ext_caps.raw, - sizeof(link->dpcd_caps.dsc_caps.dsc_ext_caps.raw)); + link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw, + sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw)); } if (!dpcd_read_sink_ext_caps(link)) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index af177c087d3b..a8a3b0643505 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -726,7 +726,7 @@ union dpcd_dsc_basic_capabilities { uint8_t raw[16]; }; -union dpcd_dsc_ext_capabilities { +union dpcd_dsc_branch_decoder_capabilities { struct { uint8_t BRANCH_OVERALL_THROUGHPUT_0; uint8_t BRANCH_OVERALL_THROUGHPUT_1; @@ -737,7 +737,7 @@ union dpcd_dsc_ext_capabilities { struct dpcd_dsc_capabilities { union dpcd_dsc_basic_capabilities dsc_basic_caps; - union dpcd_dsc_ext_capabilities dsc_ext_caps; + union dpcd_dsc_branch_decoder_capabilities dsc_branch_decoder_caps; }; /* These parameters are from PSR capabilities reported by Sink DPCD */ diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index 0c7f247bb7de..8cdaa6eef5d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -747,7 +747,7 @@ done: return is_dsc_possible; } -bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_data, const uint8_t *dpcd_dsc_ext_data, struct dsc_dec_dpcd_caps *dsc_sink_caps) +bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_data, const uint8_t *dpcd_dsc_branch_decoder_caps, struct dsc_dec_dpcd_caps *dsc_sink_caps) { if (!dpcd_dsc_basic_data) return false; @@ -818,14 +818,14 @@ bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_da } /* Extended caps */ - if (dpcd_dsc_ext_data == NULL) { // Extended DPCD DSC data can be null, e.g. because it doesn't apply to SST + if (dpcd_dsc_branch_decoder_caps == NULL) { // branch decoder DPCD DSC data can be null for non branch device dsc_sink_caps->branch_overall_throughput_0_mps = 0; dsc_sink_caps->branch_overall_throughput_1_mps = 0; dsc_sink_caps->branch_max_line_width = 0; return true; } - dsc_sink_caps->branch_overall_throughput_0_mps = dpcd_dsc_ext_data[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0]; + dsc_sink_caps->branch_overall_throughput_0_mps = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_0 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0]; if (dsc_sink_caps->branch_overall_throughput_0_mps == 0) dsc_sink_caps->branch_overall_throughput_0_mps = 0; else if (dsc_sink_caps->branch_overall_throughput_0_mps == 1) @@ -835,7 +835,7 @@ bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_da dsc_sink_caps->branch_overall_throughput_0_mps += 600; } - dsc_sink_caps->branch_overall_throughput_1_mps = dpcd_dsc_ext_data[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0]; + dsc_sink_caps->branch_overall_throughput_1_mps = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_OVERALL_THROUGHPUT_1 - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0]; if (dsc_sink_caps->branch_overall_throughput_1_mps == 0) dsc_sink_caps->branch_overall_throughput_1_mps = 0; else if (dsc_sink_caps->branch_overall_throughput_1_mps == 1) @@ -845,7 +845,7 @@ bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_da dsc_sink_caps->branch_overall_throughput_1_mps += 600; } - dsc_sink_caps->branch_max_line_width = dpcd_dsc_ext_data[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320; + dsc_sink_caps->branch_max_line_width = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320; ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120); return true; -- cgit v1.2.3-70-g09d2 From e10517b3cb93f90c8a790def6ae884d1e2b65ee7 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Fri, 3 Jul 2020 12:37:35 -0400 Subject: drm/amd/display: Add additional config guards for DCN [Why&How] Fix build error by protecting code with config guard to enable building amdgpu without CONFIG_DRM_AMD_DC_DCN enabled. This option is disabled by default for allmodconfig. Signed-off-by: Aurabindo Pillai Reviewed-by: Nicholas Kazlauskas Acked-by: Qingqing Zhuo 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 99d052f861c9..45886649cc53 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8469,7 +8469,7 @@ cleanup: *out_type = update_type; return ret; } - +#if defined(CONFIG_DRM_AMD_DC_DCN) static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc) { struct drm_connector *connector; @@ -8492,6 +8492,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_port->mst_mgr); } +#endif /** * amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM. @@ -8545,6 +8546,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; +#if defined(CONFIG_DRM_AMD_DC_DCN) if (adev->asic_type >= CHIP_NAVI10) { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (drm_atomic_crtc_needs_modeset(new_crtc_state)) { @@ -8554,7 +8556,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } } - +#endif for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (!drm_atomic_crtc_needs_modeset(new_crtc_state) && !new_crtc_state->color_mgmt_changed && -- cgit v1.2.3-70-g09d2 From fde9f39ac7f1ffd799a96ffa1e06b2051f0898f1 Mon Sep 17 00:00:00 2001 From: Mazin Rezk Date: Mon, 27 Jul 2020 05:40:46 +0000 Subject: drm/amd/display: Clear dm_state for fast updates This patch fixes a race condition that causes a use-after-free during amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking commits are requested and the second one finishes before the first. Essentially, this bug occurs when the following sequence of events happens: 1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is deferred to the workqueue. 2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is deferred to the workqueue. 3. Commit #2 starts before commit #1, dm_state #1 is used in the commit_tail and commit #2 completes, freeing dm_state #1. 4. Commit #1 starts after commit #2 completes, uses the freed dm_state 1 and dereferences a freelist pointer while setting the context. Since this bug has only been spotted with fast commits, this patch fixes the bug by clearing the dm_state instead of using the old dc_state for fast updates. In addition, since dm_state is only used for its dc_state and amdgpu_dm_atomic_commit_tail will retain the dc_state if none is found, removing the dm_state should not have any consequences in fast updates. This use-after-free bug has existed for a while now, but only caused a noticeable issue starting from 5.7-rc1 due to 3202fa62f ("slub: relocate freelist pointer to middle of object") moving the freelist pointer from dm_state->base (which was unused) to dm_state->context (which is dereferenced). Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=207383 Fixes: bd200d190f45 ("drm/amd/display: Don't replace the dc_state for fast updates") Reported-by: Duncan <1i5t5.duncan@cox.net> Signed-off-by: Mazin Rezk Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 +++++++++++++++++------ 1 file changed, 27 insertions(+), 9 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 86ffa0c2880f..710edc70e37e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8717,20 +8717,38 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, * the same resource. If we have a new DC context as part of * the DM atomic state from validation we need to free it and * retain the existing one instead. + * + * Furthermore, since the DM atomic state only contains the DC + * context and can safely be annulled, we can free the state + * and clear the associated private object now to free + * some memory and avoid a possible use-after-free later. */ - struct dm_atomic_state *new_dm_state, *old_dm_state; - new_dm_state = dm_atomic_get_new_state(state); - old_dm_state = dm_atomic_get_old_state(state); + for (i = 0; i < state->num_private_objs; i++) { + struct drm_private_obj *obj = state->private_objs[i].ptr; - if (new_dm_state && old_dm_state) { - if (new_dm_state->context) - dc_release_state(new_dm_state->context); + if (obj->funcs == adev->dm.atomic_obj.funcs) { + int j = state->num_private_objs-1; - new_dm_state->context = old_dm_state->context; + dm_atomic_destroy_state(obj, + state->private_objs[i].state); + + /* If i is not at the end of the array then the + * last element needs to be moved to where i was + * before the array can safely be truncated. + */ + if (i != j) + state->private_objs[i] = + state->private_objs[j]; - if (old_dm_state->context) - dc_retain_state(old_dm_state->context); + state->private_objs[j].ptr = NULL; + state->private_objs[j].state = NULL; + state->private_objs[j].old_state = NULL; + state->private_objs[j].new_state = NULL; + + state->num_private_objs = j; + break; + } } } -- cgit v1.2.3-70-g09d2 From 5ce868fc474e8797bd16f19e435a538554c371ab Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 21 Jul 2020 13:59:52 -0400 Subject: drm/amd/display: Use seperate dmcub firmware for navy_flounder [Why] Currently navy_flounder is using sienna_cichlid_dmcub.bin. [How] Create a seperate define so navy_flounder will use its own firmware. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++++- 1 file changed, 6 insertions(+), 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 533913bf8410..3067f54b9891 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -97,6 +97,8 @@ MODULE_FIRMWARE(FIRMWARE_RENOIR_DMUB); #if defined(CONFIG_DRM_AMD_DC_DCN3_0) #define FIRMWARE_SIENNA_CICHLID_DMUB "amdgpu/sienna_cichlid_dmcub.bin" MODULE_FIRMWARE(FIRMWARE_SIENNA_CICHLID_DMUB); +#define FIRMWARE_NAVY_FLOUNDER_DMUB "amdgpu/navy_flounder_dmcub.bin" +MODULE_FIRMWARE(FIRMWARE_NAVY_FLOUNDER_DMUB); #endif #define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin" @@ -1185,10 +1187,13 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) break; #if defined(CONFIG_DRM_AMD_DC_DCN3_0) case CHIP_SIENNA_CICHLID: - case CHIP_NAVY_FLOUNDER: dmub_asic = DMUB_ASIC_DCN30; fw_name_dmub = FIRMWARE_SIENNA_CICHLID_DMUB; break; + case CHIP_NAVY_FLOUNDER: + dmub_asic = DMUB_ASIC_DCN30; + fw_name_dmub = FIRMWARE_NAVY_FLOUNDER_DMUB; + break; #endif default: -- cgit v1.2.3-70-g09d2 From c5892a10218214d729699ab61bad6fc109baf0ce Mon Sep 17 00:00:00 2001 From: Stylon Wang Date: Tue, 30 Jun 2020 17:55:29 +0800 Subject: drm/amd/display: Fix dmesg warning from setting abm level [Why] Setting abm level does not correctly update CRTC state. As a result no surface update is added to dc stream state and triggers warning. [How] Correctly update CRTC state when setting abm level property. CC: Stable Signed-off-by: Stylon Wang Reviewed-by: Nicholas Kazlauskas Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 +++++++++++++++++++++++ 1 file changed, 23 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 3067f54b9891..e6833a2d01f8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8549,6 +8549,29 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; + /* Check connector changes */ + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { + struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); + struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); + + /* Skip connectors that are disabled or part of modeset already. */ + if (!old_con_state->crtc && !new_con_state->crtc) + continue; + + if (!new_con_state->crtc) + continue; + + new_crtc_state = drm_atomic_get_crtc_state(state, new_con_state->crtc); + if (IS_ERR(new_crtc_state)) { + ret = PTR_ERR(new_crtc_state); + goto fail; + } + + if (dm_old_con_state->abm_level != + dm_new_con_state->abm_level) + new_crtc_state->connectors_changed = true; + } + #if defined(CONFIG_DRM_AMD_DC_DCN) if (adev->asic_type >= CHIP_NAVI10) { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { -- cgit v1.2.3-70-g09d2