diff options
author | Dave Airlie <airlied@redhat.com> | 2020-05-14 06:21:30 +0300 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2020-05-14 06:21:33 +0300 |
commit | 49eea1c6573a6e31d79783c716b9001c968e5662 (patch) | |
tree | 6cee26398c8ae357388a570af155b7992f60a441 /drivers/gpu/drm/amd/display | |
parent | a1fb548962397bb8609bb46e566809a9a1b30044 (diff) | |
parent | 37e4f052cc9749db608ad63e53acc49354c98200 (diff) | |
download | linux-49eea1c6573a6e31d79783c716b9001c968e5662.tar.xz |
Merge tag 'amd-drm-next-5.8-2020-05-12' of git://people.freedesktop.org/~agd5f/linux into drm-next
amd-drm-next-5.8-2020-05-12:
amdgpu:
- Misc cleanups
- RAS fixes
- Expose FP16 for modesetting
- DP 1.4 compliance test fixes
- Clockgating fixes
- MAINTAINERS update
- Soft recovery for gfx10
- Runtime PM cleanups
- PSP code cleanups
amdkfd:
- Track GPU memory utilization per process
- Report PCI domain in topology
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexdeucher@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200512213703.4039-1-alexander.deucher@amd.com
Diffstat (limited to 'drivers/gpu/drm/amd/display')
52 files changed, 679 insertions, 1257 deletions
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 71309ee3aca3..48f2b3710e7c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -30,7 +30,7 @@ #include "dc.h" #include "dc/inc/core_types.h" #include "dal_asic_id.h" -#include "dmub/inc/dmub_srv.h" +#include "dmub/dmub_srv.h" #include "dc/inc/hw/dmcu.h" #include "dc/inc/hw/abm.h" #include "dc/dc_dmub_srv.h" @@ -441,7 +441,7 @@ static void dm_vupdate_high_irq(void *interrupt_params) /** * dm_crtc_high_irq() - Handles CRTC interrupt - * @interrupt_params: ignored + * @interrupt_params: used for determining the CRTC instance * * Handles the CRTC/VSYNC interrupt by notfying DRM's VBLANK * event handler. @@ -455,70 +455,6 @@ static void dm_crtc_high_irq(void *interrupt_params) unsigned long flags; acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK); - - if (acrtc) { - acrtc_state = to_dm_crtc_state(acrtc->base.state); - - DRM_DEBUG_VBL("crtc:%d, vupdate-vrr:%d\n", - acrtc->crtc_id, - amdgpu_dm_vrr_active(acrtc_state)); - - /* Core vblank handling at start of front-porch is only possible - * in non-vrr mode, as only there vblank timestamping will give - * valid results while done in front-porch. Otherwise defer it - * to dm_vupdate_high_irq after end of front-porch. - */ - if (!amdgpu_dm_vrr_active(acrtc_state)) - drm_crtc_handle_vblank(&acrtc->base); - - /* Following stuff must happen at start of vblank, for crc - * computation and below-the-range btr support in vrr mode. - */ - amdgpu_dm_crtc_handle_crc_irq(&acrtc->base); - - if (acrtc_state->stream && adev->family >= AMDGPU_FAMILY_AI && - acrtc_state->vrr_params.supported && - acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) { - spin_lock_irqsave(&adev->ddev->event_lock, flags); - mod_freesync_handle_v_update( - adev->dm.freesync_module, - acrtc_state->stream, - &acrtc_state->vrr_params); - - dc_stream_adjust_vmin_vmax( - adev->dm.dc, - acrtc_state->stream, - &acrtc_state->vrr_params.adjust); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); - } - } -} - -#if defined(CONFIG_DRM_AMD_DC_DCN) -/** - * dm_dcn_crtc_high_irq() - Handles VStartup interrupt for DCN generation ASICs - * @interrupt params - interrupt parameters - * - * Notify DRM's vblank event handler at VSTARTUP - * - * Unlike DCE hardware, we trigger the handler at VSTARTUP. at which: - * * We are close enough to VUPDATE - the point of no return for hw - * * We are in the fixed portion of variable front porch when vrr is enabled - * * We are before VUPDATE, where double-buffered vrr registers are swapped - * - * It is therefore the correct place to signal vblank, send user flip events, - * and update VRR. - */ -static void dm_dcn_crtc_high_irq(void *interrupt_params) -{ - struct common_irq_params *irq_params = interrupt_params; - struct amdgpu_device *adev = irq_params->adev; - struct amdgpu_crtc *acrtc; - struct dm_crtc_state *acrtc_state; - unsigned long flags; - - acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK); - if (!acrtc) return; @@ -528,22 +464,35 @@ static void dm_dcn_crtc_high_irq(void *interrupt_params) amdgpu_dm_vrr_active(acrtc_state), acrtc_state->active_planes); + /** + * Core vblank handling at start of front-porch is only possible + * in non-vrr mode, as only there vblank timestamping will give + * valid results while done in front-porch. Otherwise defer it + * to dm_vupdate_high_irq after end of front-porch. + */ + if (!amdgpu_dm_vrr_active(acrtc_state)) + drm_crtc_handle_vblank(&acrtc->base); + + /** + * Following stuff must happen at start of vblank, for crc + * computation and below-the-range btr support in vrr mode. + */ amdgpu_dm_crtc_handle_crc_irq(&acrtc->base); - drm_crtc_handle_vblank(&acrtc->base); + + /* BTR updates need to happen before VUPDATE on Vega and above. */ + if (adev->family < AMDGPU_FAMILY_AI) + return; spin_lock_irqsave(&adev->ddev->event_lock, flags); - if (acrtc_state->vrr_params.supported && + if (acrtc_state->stream && acrtc_state->vrr_params.supported && acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) { - mod_freesync_handle_v_update( - adev->dm.freesync_module, - acrtc_state->stream, - &acrtc_state->vrr_params); + mod_freesync_handle_v_update(adev->dm.freesync_module, + acrtc_state->stream, + &acrtc_state->vrr_params); - dc_stream_adjust_vmin_vmax( - adev->dm.dc, - acrtc_state->stream, - &acrtc_state->vrr_params.adjust); + dc_stream_adjust_vmin_vmax(adev->dm.dc, acrtc_state->stream, + &acrtc_state->vrr_params.adjust); } /* @@ -556,7 +505,8 @@ static void dm_dcn_crtc_high_irq(void *interrupt_params) * avoid race conditions between flip programming and completion, * which could cause too early flip completion events. */ - if (acrtc->pflip_status == AMDGPU_FLIP_SUBMITTED && + if (adev->family >= AMDGPU_FAMILY_RV && + acrtc->pflip_status == AMDGPU_FLIP_SUBMITTED && acrtc_state->active_planes == 0) { if (acrtc->event) { drm_crtc_send_vblank_event(&acrtc->base, acrtc->event); @@ -568,7 +518,6 @@ static void dm_dcn_crtc_high_irq(void *interrupt_params) spin_unlock_irqrestore(&adev->ddev->event_lock, flags); } -#endif static int dm_set_clockgating_state(void *handle, enum amd_clockgating_state state) @@ -1389,9 +1338,14 @@ static int dm_late_init(void *handle) struct dmcu_iram_parameters params; unsigned int linear_lut[16]; int i; - struct dmcu *dmcu = adev->dm.dc->res_pool->dmcu; + struct dmcu *dmcu = NULL; bool ret = false; + if (!adev->dm.fw_dmcu) + return detect_mst_link_for_all_connectors(adev->ddev); + + dmcu = adev->dm.dc->res_pool->dmcu; + for (i = 0; i < 16; i++) linear_lut[i] = 0xFFFF * i / 15; @@ -1571,7 +1525,6 @@ static int dm_suspend(void *handle) { struct amdgpu_device *adev = handle; struct amdgpu_display_manager *dm = &adev->dm; - int ret = 0; WARN_ON(adev->dm.cached_state); adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); @@ -1583,7 +1536,7 @@ static int dm_suspend(void *handle) dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); - return ret; + return 0; } static struct amdgpu_dm_connector * @@ -2013,17 +1966,22 @@ void amdgpu_dm_update_connector_after_detect( dc_sink_retain(aconnector->dc_sink); if (sink->dc_edid.length == 0) { aconnector->edid = NULL; - drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux); + if (aconnector->dc_link->aux_mode) { + drm_dp_cec_unset_edid( + &aconnector->dm_dp_aux.aux); + } } else { aconnector->edid = - (struct edid *) sink->dc_edid.raw_edid; - + (struct edid *)sink->dc_edid.raw_edid; drm_connector_update_edid_property(connector, - aconnector->edid); - drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux, - aconnector->edid); + aconnector->edid); + + if (aconnector->dc_link->aux_mode) + drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux, + aconnector->edid); } + amdgpu_dm_update_freesync_caps(connector, aconnector->edid); update_connector_ext_caps(aconnector); } else { @@ -2445,8 +2403,36 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev) c_irq_params->adev = adev; c_irq_params->irq_src = int_params.irq_source; + amdgpu_dm_irq_register_interrupt( + adev, &int_params, dm_crtc_high_irq, c_irq_params); + } + + /* Use VUPDATE_NO_LOCK interrupt on DCN, which seems to correspond to + * the regular VUPDATE interrupt on DCE. We want DC_IRQ_SOURCE_VUPDATEx + * to trigger at end of each vblank, regardless of state of the lock, + * matching DCE behaviour. + */ + for (i = DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT; + i <= DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT + adev->mode_info.num_crtc - 1; + i++) { + r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->vupdate_irq); + + if (r) { + DRM_ERROR("Failed to add vupdate irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i, 0); + + c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + amdgpu_dm_irq_register_interrupt(adev, &int_params, - dm_dcn_crtc_high_irq, c_irq_params); + dm_vupdate_high_irq, c_irq_params); } /* Use GRPH_PFLIP interrupt */ @@ -3661,6 +3647,10 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev, case DRM_FORMAT_P010: plane_info->format = SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb; break; + case DRM_FORMAT_XRGB16161616F: + case DRM_FORMAT_ARGB16161616F: + plane_info->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F; + break; default: DRM_ERROR( "Unsupported screen format %s\n", @@ -4458,10 +4448,6 @@ static inline int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable) struct amdgpu_device *adev = crtc->dev->dev_private; int rc; - /* Do not set vupdate for DCN hardware */ - if (adev->family > AMDGPU_FAMILY_AI) - return 0; - irq_source = IRQ_TYPE_VUPDATE + acrtc->otg_inst; rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY; @@ -5577,6 +5563,10 @@ static int get_plane_formats(const struct drm_plane *plane, formats[num_formats++] = DRM_FORMAT_NV12; if (plane_cap && plane_cap->pixel_format_support.p010) formats[num_formats++] = DRM_FORMAT_P010; + if (plane_cap && plane_cap->pixel_format_support.fp16) { + formats[num_formats++] = DRM_FORMAT_XRGB16161616F; + formats[num_formats++] = DRM_FORMAT_ARGB16161616F; + } break; case DRM_PLANE_TYPE_OVERLAY: @@ -6865,7 +6855,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, dc_state); if ((acrtc_state->update_type > UPDATE_TYPE_FAST) && - acrtc_state->stream->link->psr_settings.psr_version != PSR_VERSION_UNSUPPORTED && + acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED && !acrtc_state->stream->link->psr_settings.psr_feature_enabled) amdgpu_dm_link_setup_psr(acrtc_state->stream); else if ((acrtc_state->update_type == UPDATE_TYPE_FAST) && @@ -7895,6 +7885,7 @@ static int dm_update_plane_state(struct dc *dc, struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state; struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state; + struct amdgpu_crtc *new_acrtc; bool needs_reset; int ret = 0; @@ -7904,9 +7895,30 @@ static int dm_update_plane_state(struct dc *dc, dm_new_plane_state = to_dm_plane_state(new_plane_state); dm_old_plane_state = to_dm_plane_state(old_plane_state); - /*TODO Implement atomic check for cursor plane */ - if (plane->type == DRM_PLANE_TYPE_CURSOR) + /*TODO Implement better atomic check for cursor plane */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) { + if (!enable || !new_plane_crtc || + drm_atomic_plane_disabling(plane->state, new_plane_state)) + return 0; + + new_acrtc = to_amdgpu_crtc(new_plane_crtc); + + if ((new_plane_state->crtc_w > new_acrtc->max_cursor_width) || + (new_plane_state->crtc_h > new_acrtc->max_cursor_height)) { + DRM_DEBUG_ATOMIC("Bad cursor size %d x %d\n", + new_plane_state->crtc_w, new_plane_state->crtc_h); + return -EINVAL; + } + + if (new_plane_state->crtc_x <= -new_acrtc->max_cursor_width || + new_plane_state->crtc_y <= -new_acrtc->max_cursor_height) { + DRM_DEBUG_ATOMIC("Bad cursor position %d, %d\n", + new_plane_state->crtc_x, new_plane_state->crtc_y); + return -EINVAL; + } + return 0; + } needs_reset = should_reset_plane(state, plane, old_plane_state, new_plane_state); @@ -8640,10 +8652,10 @@ static void amdgpu_dm_set_psr_caps(struct dc_link *link) link->dpcd_caps.psr_caps.psr_version = dpcd_data[0]; if (dpcd_data[0] == 0) { - link->psr_settings.psr_version = PSR_VERSION_UNSUPPORTED; + link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; link->psr_settings.psr_feature_enabled = false; } else { - link->psr_settings.psr_version = PSR_VERSION_1; + link->psr_settings.psr_version = DC_PSR_VERSION_1; link->psr_settings.psr_feature_enabled = true; } @@ -8662,14 +8674,12 @@ static bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream) struct dc_link *link = NULL; struct psr_config psr_config = {0}; struct psr_context psr_context = {0}; - struct dc *dc = NULL; bool ret = false; if (stream == NULL) return false; link = stream->link; - dc = link->ctx->dc; psr_config.psr_version = link->dpcd_caps.psr_caps.psr_version; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index b3b7efd973ca..076af267b488 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -32,7 +32,7 @@ #include "amdgpu_dm.h" #include "amdgpu_dm_debugfs.h" #include "dm_helpers.h" -#include "dmub/inc/dmub_srv.h" +#include "dmub/dmub_srv.h" struct dmub_debugfs_trace_header { uint32_t entry_count; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index 78e1c11d4ae5..dcf84a61de37 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -398,15 +398,15 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) struct mod_hdcp_display *display = &hdcp_work[link_index].display; struct mod_hdcp_link *link = &hdcp_work[link_index].link; - memset(display, 0, sizeof(*display)); - memset(link, 0, sizeof(*link)); - - display->index = aconnector->base.index; - if (config->dpms_off) { hdcp_remove_display(hdcp_work, link_index, aconnector); return; } + + memset(display, 0, sizeof(*display)); + memset(link, 0, sizeof(*link)); + + display->index = aconnector->base.index; display->state = MOD_HDCP_DISPLAY_ACTIVE; if (aconnector->dc_sink != NULL) 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 c407f06cd1f5..b086d5c906e0 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 @@ -554,6 +554,7 @@ enum dc_edid_status dm_helpers_read_local_edid( struct dc_sink *sink) { struct amdgpu_dm_connector *aconnector = link->priv; + struct drm_connector *connector = &aconnector->base; struct i2c_adapter *ddc; int retry = 3; enum dc_edid_status edid_status; @@ -571,6 +572,15 @@ enum dc_edid_status dm_helpers_read_local_edid( edid = drm_get_edid(&aconnector->base, ddc); + /* DP Compliance Test 4.2.2.6 */ + if (link->aux_mode && connector->edid_corrupt) + drm_dp_send_real_edid_checksum(&aconnector->dm_dp_aux.aux, connector->real_edid_checksum); + + if (!edid && connector->edid_corrupt) { + connector->edid_corrupt = false; + return EDID_BAD_CHECKSUM; + } + if (!edid) return EDID_NO_RESPONSE; @@ -605,34 +615,10 @@ enum dc_edid_status dm_helpers_read_local_edid( DRM_ERROR("EDID err: %d, on connector: %s", edid_status, aconnector->base.name); - if (link->aux_mode) { - union test_request test_request = { {0} }; - union test_response test_response = { {0} }; - - dm_helpers_dp_read_dpcd(ctx, - link, - DP_TEST_REQUEST, - &test_request.raw, - sizeof(union test_request)); - - if (!test_request.bits.EDID_READ) - return edid_status; - test_response.bits.EDID_CHECKSUM_WRITE = 1; - - dm_helpers_dp_write_dpcd(ctx, - link, - DP_TEST_EDID_CHECKSUM, - &sink->dc_edid.raw_edid[sink->dc_edid.length-1], - 1); - - dm_helpers_dp_write_dpcd(ctx, - link, - DP_TEST_RESPONSE, - &test_response.raw, - sizeof(test_response)); - - } + /* DP Compliance Test 4.2.2.3 */ + if (link->aux_mode) + drm_dp_send_real_edid_checksum(&aconnector->dm_dp_aux.aux, sink->dc_edid.raw_edid[sink->dc_edid.length-1]); return edid_status; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ad817bd74586..45cfb7c45566 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -66,7 +66,7 @@ #include "dce/dce_i2c.h" -#include "dmub/inc/dmub_cmd_dal.h" +#include "dmub/dmub_srv.h" #define CTX \ dc->ctx @@ -839,11 +839,10 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context) { int i; - int count = 0; - struct pipe_ctx *pipe; PERF_TRACE(); for (i = 0; i < MAX_PIPES; i++) { - pipe = &context->res_ctx.pipe_ctx[i]; + int count = 0; + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; if (!pipe->plane_state) continue; @@ -2210,9 +2209,7 @@ static void commit_planes_do_stream_update(struct dc *dc, if (should_program_abm) { if (*stream_update->abm_level == ABM_LEVEL_IMMEDIATE_DISABLE) { - pipe_ctx->stream_res.abm->funcs->set_abm_immediate_disable( - pipe_ctx->stream_res.abm, - pipe_ctx->stream->link->panel_cntl->inst); + dc->hwss.set_abm_immediate_disable(pipe_ctx); } else { pipe_ctx->stream_res.abm->funcs->set_abm_level( pipe_ctx->stream_res.abm, stream->abm_level); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 67c5342cf89a..c08de6823db4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -26,7 +26,7 @@ #include <linux/slab.h> #include "dm_services.h" -#include "atom.h" +#include "atomfirmware.h" #include "dm_helpers.h" #include "dc.h" #include "grph_object_id.h" @@ -46,7 +46,7 @@ #include "dmcu.h" #include "hw/clk_mgr.h" #include "dce/dmub_psr.h" -#include "dmub/inc/dmub_cmd_dal.h" +#include "dmub/dmub_srv.h" #include "inc/hw/panel_cntl.h" #define DC_LOGGER_INIT(logger) @@ -1552,7 +1552,7 @@ static bool dc_link_construct(struct dc_link *link, */ program_hpd_filter(link); - link->psr_settings.psr_version = PSR_VERSION_UNSUPPORTED; + link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; return true; device_tag_fail: @@ -2504,59 +2504,56 @@ int dc_link_get_target_backlight_pwm(const struct dc_link *link) return (int) abm->funcs->get_target_backlight(abm); } +static struct pipe_ctx *get_pipe_from_link(const struct dc_link *link) +{ + int i; + struct dc *dc = link->ctx->dc; + struct pipe_ctx *pipe_ctx = NULL; + + for (i = 0; i < MAX_PIPES; i++) { + if (dc->current_state->res_ctx.pipe_ctx[i].stream) { + if (dc->current_state->res_ctx.pipe_ctx[i].stream->link == link) { + pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + break; + } + } + } + + return pipe_ctx; +} + bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t backlight_pwm_u16_16, uint32_t frame_ramp) { struct dc *dc = link->ctx->dc; - int i; DC_LOGGER_INIT(link->ctx->logger); DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n", backlight_pwm_u16_16, backlight_pwm_u16_16); if (dc_is_embedded_signal(link->connector_signal)) { - struct pipe_ctx *pipe_ctx = NULL; - - for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream) { - if (dc->current_state->res_ctx. - pipe_ctx[i].stream->link - == link) { - pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - - /* Disable brightness ramping when the display is blanked - * as it can hang the DMCU - */ - if (dc->current_state->res_ctx.pipe_ctx[i].plane_state == NULL) - frame_ramp = 0; - } - } - } + struct pipe_ctx *pipe_ctx = get_pipe_from_link(link); - if (pipe_ctx == NULL) + if (pipe_ctx) { + /* Disable brightness ramping when the display is blanked + * as it can hang the DMCU + */ + if (pipe_ctx->plane_state == NULL) + frame_ramp = 0; + } else { ASSERT(false); + return false; + } dc->hwss.set_backlight_level( pipe_ctx, backlight_pwm_u16_16, frame_ramp); } - return true; } -bool dc_link_set_abm_disable(const struct dc_link *link) -{ - struct abm *abm = get_abm_from_stream_res(link); - bool success = false; - - if (abm) - success = abm->funcs->set_abm_immediate_disable(abm, link->panel_cntl->inst); - - return success; -} - bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool wait) { struct dc *dc = link->ctx->dc; 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 9ef9e50a34fa..1db592372435 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 @@ -13,7 +13,6 @@ #include "core_status.h" #include "dpcd_defs.h" -#include "resource.h" #define DC_LOGGER \ link->ctx->logger diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 1a01c038632b..cb5d11f11cad 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1547,35 +1547,6 @@ bool dc_add_all_planes_for_stream( return add_all_planes_for_stream(dc, stream, &set, 1, context); } - -static bool is_hdr_static_meta_changed(struct dc_stream_state *cur_stream, - struct dc_stream_state *new_stream) -{ - if (cur_stream == NULL) - return true; - - if (memcmp(&cur_stream->hdr_static_metadata, - &new_stream->hdr_static_metadata, - sizeof(struct dc_info_packet)) != 0) - return true; - - return false; -} - -static bool is_vsc_info_packet_changed(struct dc_stream_state *cur_stream, - struct dc_stream_state *new_stream) -{ - if (cur_stream == NULL) - return true; - - if (memcmp(&cur_stream->vsc_infopacket, - &new_stream->vsc_infopacket, - sizeof(struct dc_info_packet)) != 0) - return true; - - return false; -} - static bool is_timing_changed(struct dc_stream_state *cur_stream, struct dc_stream_state *new_stream) { @@ -1610,15 +1581,9 @@ static bool are_stream_backends_same( if (is_timing_changed(stream_a, stream_b)) return false; - if (is_hdr_static_meta_changed(stream_a, stream_b)) - return false; - if (stream_a->dpms_off != stream_b->dpms_off) return false; - if (is_vsc_info_packet_changed(stream_a, stream_b)) - return false; - return true; } @@ -1758,21 +1723,6 @@ static struct audio *find_first_free_audio( return 0; } -bool resource_is_stream_unchanged( - struct dc_state *old_context, struct dc_stream_state *stream) -{ - int i; - - for (i = 0; i < old_context->stream_count; i++) { - struct dc_stream_state *old_stream = old_context->streams[i]; - - if (are_stream_backends_same(old_stream, stream)) - return true; - } - - return false; -} - /** * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state. */ @@ -2027,17 +1977,6 @@ enum dc_status resource_map_pool_resources( int pipe_idx = -1; struct dc_bios *dcb = dc->ctx->dc_bios; - /* TODO Check if this is needed */ - /*if (!resource_is_stream_unchanged(old_context, stream)) { - if (stream != NULL && old_context->streams[i] != NULL) { - stream->bit_depth_params = - old_context->streams[i]->bit_depth_params; - stream->clamping = old_context->streams[i]->clamping; - continue; - } - } - */ - calculate_phy_pix_clks(stream); /* TODO: Check Linux */ @@ -2720,15 +2659,9 @@ bool pipe_need_reprogram( if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) return true; - if (is_hdr_static_meta_changed(pipe_ctx_old->stream, pipe_ctx->stream)) - return true; - if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off) return true; - if (is_vsc_info_packet_changed(pipe_ctx_old->stream, pipe_ctx->stream)) - return true; - if (false == pipe_ctx_old->stream->link->link_state_valid && false == pipe_ctx_old->stream->dpms_off) return true; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 17075f99bc54..85908561c741 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.83.1" +#define DC_VER "3.2.84" #define MAX_SURFACES 3 #define MAX_PLANES 6 @@ -277,6 +277,7 @@ struct dc_config { bool disable_extended_timeout_support; // Used to disable extended timeout and lttpr feature as well bool multi_mon_pp_mclk_switch; bool disable_dmcu; + bool enable_4to1MPC; }; enum visual_confirm { @@ -476,6 +477,7 @@ struct dc_debug_options { bool enable_dmcub_surface_flip; bool usbc_combo_phy_reset_wa; bool disable_dsc; + bool enable_dram_clock_change_one_display_vactive; }; struct dc_debug_data { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 907e0c5374bb..eea2429ac67d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -25,7 +25,7 @@ #include "dc.h" #include "dc_dmub_srv.h" -#include "../dmub/inc/dmub_srv.h" +#include "../dmub/dmub_srv.h" static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc, struct dmub_srv *dmub) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index 6689ae33dee8..a3a09ccb6d26 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -27,7 +27,7 @@ #define _DMUB_DC_SRV_H_ #include "os_types.h" -#include "dmub/inc/dmub_cmd.h" +#include "dmub/dmub_srv.h" struct dmub_srv; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 80fb4149f36a..f63fc25aa6c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -29,7 +29,6 @@ #include "dc.h" #include "dc_types.h" #include "grph_object_defs.h" -#include "dmub/inc/dmub_cmd_dal.h" enum dc_link_fec_state { dc_link_fec_not_ready, @@ -72,7 +71,7 @@ struct link_trace { struct psr_settings { bool psr_feature_enabled; // PSR is supported by sink bool psr_allow_active; // PSR is currently active - enum psr_version psr_version; // Internal PSR version, determined based on DPCD + enum dc_psr_version psr_version; // Internal PSR version, determined based on DPCD /* These parameters are calculated in Driver, * based on display timing and Sink capabilities. @@ -220,8 +219,6 @@ int dc_link_get_backlight_level(const struct dc_link *dc_link); int dc_link_get_target_backlight_pwm(const struct dc_link *link); -bool dc_link_set_abm_disable(const struct dc_link *dc_link); - bool dc_link_set_psr_allow_active(struct dc_link *dc_link, bool enable, bool wait); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 0d210104ba0a..f236da1c1859 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -862,4 +862,9 @@ struct dsc_dec_dpcd_caps { uint32_t branch_max_line_width; }; +enum dc_psr_version { + DC_PSR_VERSION_1 = 0, + DC_PSR_VERSION_UNSUPPORTED = 0xFFFFFFFF, +}; + #endif /* DC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index c15e60fb5ebc..4e87e70237e3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -83,120 +83,6 @@ static bool dce_abm_set_pipe(struct abm *abm, uint32_t controller_id, uint32_t p return true; } -static unsigned int calculate_16_bit_backlight_from_pwm(struct dce_abm *abm_dce) -{ - uint64_t current_backlight; - uint32_t round_result; - uint32_t pwm_period_cntl, bl_period, bl_int_count; - uint32_t bl_pwm_cntl, bl_pwm, fractional_duty_cycle_en; - uint32_t bl_period_mask, bl_pwm_mask; - - pwm_period_cntl = REG_READ(BL_PWM_PERIOD_CNTL); - REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, &bl_period); - REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, &bl_int_count); - - bl_pwm_cntl = REG_READ(BL_PWM_CNTL); - REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, (uint32_t *)(&bl_pwm)); - REG_GET(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, &fractional_duty_cycle_en); - - if (bl_int_count == 0) - bl_int_count = 16; - - bl_period_mask = (1 << bl_int_count) - 1; - bl_period &= bl_period_mask; - - bl_pwm_mask = bl_period_mask << (16 - bl_int_count); - - if (fractional_duty_cycle_en == 0) - bl_pwm &= bl_pwm_mask; - else - bl_pwm &= 0xFFFF; - - current_backlight = bl_pwm << (1 + bl_int_count); - - if (bl_period == 0) - bl_period = 0xFFFF; - - current_backlight = div_u64(current_backlight, bl_period); - current_backlight = (current_backlight + 1) >> 1; - - current_backlight = (uint64_t)(current_backlight) * bl_period; - - round_result = (uint32_t)(current_backlight & 0xFFFFFFFF); - - round_result = (round_result >> (bl_int_count-1)) & 1; - - current_backlight >>= bl_int_count; - current_backlight += round_result; - - return (uint32_t)(current_backlight); -} - -static void driver_set_backlight_level(struct dce_abm *abm_dce, - uint32_t backlight_pwm_u16_16) -{ - uint32_t backlight_16bit; - uint32_t masked_pwm_period; - uint8_t bit_count; - uint64_t active_duty_cycle; - uint32_t pwm_period_bitcnt; - - /* - * 1. Find 16 bit backlight active duty cycle, where 0 <= backlight - * active duty cycle <= backlight period - */ - - /* 1.1 Apply bitmask for backlight period value based on value of BITCNT - */ - REG_GET_2(BL_PWM_PERIOD_CNTL, - BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt, - BL_PWM_PERIOD, &masked_pwm_period); - - if (pwm_period_bitcnt == 0) - bit_count = 16; - else - bit_count = pwm_period_bitcnt; - - /* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */ - masked_pwm_period = masked_pwm_period & ((1 << bit_count) - 1); - - /* 1.2 Calculate integer active duty cycle required upper 16 bits - * contain integer component, lower 16 bits contain fractional component - * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24 - */ - active_duty_cycle = backlight_pwm_u16_16 * masked_pwm_period; - - /* 1.3 Calculate 16 bit active duty cycle from integer and fractional - * components shift by bitCount then mask 16 bits and add rounding bit - * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0 - */ - backlight_16bit = active_duty_cycle >> bit_count; - backlight_16bit &= 0xFFFF; - backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1; - - /* - * 2. Program register with updated value - */ - - /* 2.1 Lock group 2 backlight registers */ - - REG_UPDATE_2(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1, - BL_PWM_GRP1_REG_LOCK, 1); - - // 2.2 Write new active duty cycle - REG_UPDATE(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, backlight_16bit); - - /* 2.3 Unlock group 2 backlight registers */ - REG_UPDATE(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_REG_LOCK, 0); - - /* 3 Wait for pending bit to be cleared */ - REG_WAIT(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_REG_UPDATE_PENDING, 0, - 1, 10000); -} - static void dmcu_set_backlight_level( struct dce_abm *abm_dce, uint32_t backlight_pwm_u16_16, @@ -249,10 +135,9 @@ static void dmcu_set_backlight_level( 0, 1, 80000); } -static void dce_abm_init(struct abm *abm) +static void dce_abm_init(struct abm *abm, uint32_t backlight) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); - unsigned int backlight = calculate_16_bit_backlight_from_pwm(abm_dce); REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103); REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101); @@ -334,85 +219,11 @@ static bool dce_abm_set_level(struct abm *abm, uint32_t level) static bool dce_abm_immediate_disable(struct abm *abm, uint32_t panel_inst) { - struct dce_abm *abm_dce = TO_DCE_ABM(abm); - if (abm->dmcu_is_running == false) return true; dce_abm_set_pipe(abm, MCP_DISABLE_ABM_IMMEDIATELY, panel_inst); - abm->stored_backlight_registers.BL_PWM_CNTL = - REG_READ(BL_PWM_CNTL); - abm->stored_backlight_registers.BL_PWM_CNTL2 = - REG_READ(BL_PWM_CNTL2); - abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL = - REG_READ(BL_PWM_PERIOD_CNTL); - - REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, - &abm->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); - return true; -} - -static bool dce_abm_init_backlight(struct abm *abm) -{ - struct dce_abm *abm_dce = TO_DCE_ABM(abm); - uint32_t value; - - /* It must not be 0, so we have to restore them - * Bios bug w/a - period resets to zero, - * restoring to cache values which is always correct - */ - REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); - if (value == 0 || value == 1) { - if (abm->stored_backlight_registers.BL_PWM_CNTL != 0) { - REG_WRITE(BL_PWM_CNTL, - abm->stored_backlight_registers.BL_PWM_CNTL); - REG_WRITE(BL_PWM_CNTL2, - abm->stored_backlight_registers.BL_PWM_CNTL2); - REG_WRITE(BL_PWM_PERIOD_CNTL, - abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL); - REG_UPDATE(LVTMA_PWRSEQ_REF_DIV, - BL_PWM_REF_DIV, - abm->stored_backlight_registers. - LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); - } else { - /* TODO: Note: This should not really happen since VBIOS - * should have initialized PWM registers on boot. - */ - REG_WRITE(BL_PWM_CNTL, 0xC000FA00); - REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0); - } - } else { - abm->stored_backlight_registers.BL_PWM_CNTL = - REG_READ(BL_PWM_CNTL); - abm->stored_backlight_registers.BL_PWM_CNTL2 = - REG_READ(BL_PWM_CNTL2); - abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL = - REG_READ(BL_PWM_PERIOD_CNTL); - - REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, - &abm->stored_backlight_registers. - LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); - } - - /* Have driver take backlight control - * TakeBacklightControl(true) - */ - value = REG_READ(BIOS_SCRATCH_2); - value |= ATOM_S2_VRI_BRIGHT_ENABLE; - REG_WRITE(BIOS_SCRATCH_2, value); - - /* Enable the backlight output */ - REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); - - /* Disable fractional pwm if configured */ - REG_UPDATE(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, - abm->ctx->dc->config.disable_fractional_pwm ? 0 : 1); - - /* Unlock group 2 backlight registers */ - REG_UPDATE(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_REG_LOCK, 0); - return true; } @@ -421,23 +232,18 @@ static bool dce_abm_set_backlight_level_pwm( unsigned int backlight_pwm_u16_16, unsigned int frame_ramp, unsigned int controller_id, - unsigned int panel_inst, - bool fw_set_brightness) + unsigned int panel_inst) { struct dce_abm *abm_dce = TO_DCE_ABM(abm); DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n", backlight_pwm_u16_16, backlight_pwm_u16_16); - /* If DMCU is in reset state, DMCU is uninitialized */ - if (fw_set_brightness) - dmcu_set_backlight_level(abm_dce, - backlight_pwm_u16_16, - frame_ramp, - controller_id, - panel_inst); - else - driver_set_backlight_level(abm_dce, backlight_pwm_u16_16); + dmcu_set_backlight_level(abm_dce, + backlight_pwm_u16_16, + frame_ramp, + controller_id, + panel_inst); return true; } @@ -445,13 +251,12 @@ static bool dce_abm_set_backlight_level_pwm( static const struct abm_funcs dce_funcs = { .abm_init = dce_abm_init, .set_abm_level = dce_abm_set_level, - .init_backlight = dce_abm_init_backlight, .set_pipe = dce_abm_set_pipe, .set_backlight_level_pwm = dce_abm_set_backlight_level_pwm, .get_current_backlight = dce_abm_get_current_backlight, .get_target_backlight = dce_abm_get_target_backlight, .init_abm_config = NULL, - .set_abm_immediate_disable = dce_abm_immediate_disable + .set_abm_immediate_disable = dce_abm_immediate_disable, }; static void dce_abm_construct( @@ -465,10 +270,6 @@ static void dce_abm_construct( base->ctx = ctx; base->funcs = &dce_funcs; - base->stored_backlight_registers.BL_PWM_CNTL = 0; - base->stored_backlight_registers.BL_PWM_CNTL2 = 0; - base->stored_backlight_registers.BL_PWM_PERIOD_CNTL = 0; - base->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV = 0; base->dmcu_is_running = false; abm_dce->regs = regs; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index ba0caaffa24b..9718a4823372 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -30,11 +30,6 @@ #include "abm.h" #define ABM_COMMON_REG_LIST_DCE_BASE() \ - SR(BL_PWM_PERIOD_CNTL), \ - SR(BL_PWM_CNTL), \ - SR(BL_PWM_CNTL2), \ - SR(BL_PWM_GRP1_REG_LOCK), \ - SR(LVTMA_PWRSEQ_REF_DIV), \ SR(MASTER_COMM_CNTL_REG), \ SR(MASTER_COMM_CMD_REG), \ SR(MASTER_COMM_DATA_REG1) @@ -85,15 +80,6 @@ .field_name = reg_name ## __ ## field_name ## post_fix #define ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ - ABM_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, mask_sh), \ - ABM_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, mask_sh), \ - ABM_SF(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, mask_sh), \ - ABM_SF(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, mask_sh), \ - ABM_SF(BL_PWM_CNTL, BL_PWM_EN, mask_sh), \ - ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, mask_sh), \ - ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_LOCK, mask_sh), \ - ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING, mask_sh), \ - ABM_SF(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, mask_sh), \ ABM_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \ ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE1, mask_sh), \ @@ -178,19 +164,10 @@ type ABM1_HG_REG_READ_MISSED_FRAME_CLEAR; \ type ABM1_LS_REG_READ_MISSED_FRAME_CLEAR; \ type ABM1_BL_REG_READ_MISSED_FRAME_CLEAR; \ - type BL_PWM_PERIOD; \ - type BL_PWM_PERIOD_BITCNT; \ - type BL_ACTIVE_INT_FRAC_CNT; \ - type BL_PWM_FRACTIONAL_EN; \ type MASTER_COMM_INTERRUPT; \ type MASTER_COMM_CMD_REG_BYTE0; \ type MASTER_COMM_CMD_REG_BYTE1; \ - type MASTER_COMM_CMD_REG_BYTE2; \ - type BL_PWM_REF_DIV; \ - type BL_PWM_EN; \ - type BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN; \ - type BL_PWM_GRP1_REG_LOCK; \ - type BL_PWM_GRP1_REG_UPDATE_PENDING + type MASTER_COMM_CMD_REG_BYTE2 struct dce_abm_shift { ABM_REG_FIELD_LIST(uint8_t); @@ -201,10 +178,6 @@ struct dce_abm_mask { }; struct dce_abm_registers { - uint32_t BL_PWM_PERIOD_CNTL; - uint32_t BL_PWM_CNTL; - uint32_t BL_PWM_CNTL2; - uint32_t LVTMA_PWRSEQ_REF_DIV; uint32_t DC_ABM1_HG_SAMPLE_RATE; uint32_t DC_ABM1_LS_SAMPLE_RATE; uint32_t BL1_PWM_BL_UPDATE_SAMPLE_RATE; @@ -219,7 +192,6 @@ struct dce_abm_registers { uint32_t MASTER_COMM_CMD_REG; uint32_t MASTER_COMM_DATA_REG1; uint32_t BIOS_SCRATCH_2; - uint32_t BL_PWM_GRP1_REG_LOCK; }; struct dce_abm { 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 d9b0ff7eb2a4..ebff9b1e312e 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 @@ -28,6 +28,7 @@ #include "dc_dmub_srv.h" #include "panel_cntl.h" #include "dce_panel_cntl.h" +#include "atom.h" #define TO_DCE_PANEL_CNTL(panel_cntl)\ container_of(panel_cntl, struct dce_panel_cntl, base) @@ -45,9 +46,113 @@ #define FN(reg_name, field_name) \ dce_panel_cntl->shift->field_name, dce_panel_cntl->mask->field_name -void dce_panel_cntl_hw_init(struct panel_cntl *panel_cntl) +static unsigned int calculate_16_bit_backlight_from_pwm(struct dce_panel_cntl *dce_panel_cntl) { + uint64_t current_backlight; + uint32_t round_result; + uint32_t pwm_period_cntl, bl_period, bl_int_count; + uint32_t bl_pwm_cntl, bl_pwm, fractional_duty_cycle_en; + uint32_t bl_period_mask, bl_pwm_mask; + pwm_period_cntl = REG_READ(BL_PWM_PERIOD_CNTL); + REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, &bl_period); + REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, &bl_int_count); + + bl_pwm_cntl = REG_READ(BL_PWM_CNTL); + REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, (uint32_t *)(&bl_pwm)); + REG_GET(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, &fractional_duty_cycle_en); + + if (bl_int_count == 0) + bl_int_count = 16; + + bl_period_mask = (1 << bl_int_count) - 1; + bl_period &= bl_period_mask; + + bl_pwm_mask = bl_period_mask << (16 - bl_int_count); + + if (fractional_duty_cycle_en == 0) + bl_pwm &= bl_pwm_mask; + else + bl_pwm &= 0xFFFF; + + current_backlight = bl_pwm << (1 + bl_int_count); + + if (bl_period == 0) + bl_period = 0xFFFF; + + current_backlight = div_u64(current_backlight, bl_period); + current_backlight = (current_backlight + 1) >> 1; + + current_backlight = (uint64_t)(current_backlight) * bl_period; + + round_result = (uint32_t)(current_backlight & 0xFFFFFFFF); + + round_result = (round_result >> (bl_int_count-1)) & 1; + + current_backlight >>= bl_int_count; + current_backlight += round_result; + + return (uint32_t)(current_backlight); +} + +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; + uint32_t current_backlight; + + /* It must not be 0, so we have to restore them + * Bios bug w/a - period resets to zero, + * restoring to cache values which is always correct + */ + REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); + + if (value == 0 || value == 1) { + if (panel_cntl->stored_backlight_registers.BL_PWM_CNTL != 0) { + REG_WRITE(BL_PWM_CNTL, + panel_cntl->stored_backlight_registers.BL_PWM_CNTL); + REG_WRITE(BL_PWM_CNTL2, + panel_cntl->stored_backlight_registers.BL_PWM_CNTL2); + REG_WRITE(BL_PWM_PERIOD_CNTL, + panel_cntl->stored_backlight_registers.BL_PWM_PERIOD_CNTL); + REG_UPDATE(PWRSEQ_REF_DIV, + BL_PWM_REF_DIV, + panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } else { + /* TODO: Note: This should not really happen since VBIOS + * should have initialized PWM registers on boot. + */ + REG_WRITE(BL_PWM_CNTL, 0xC000FA00); + REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0); + } + } else { + panel_cntl->stored_backlight_registers.BL_PWM_CNTL = + REG_READ(BL_PWM_CNTL); + panel_cntl->stored_backlight_registers.BL_PWM_CNTL2 = + REG_READ(BL_PWM_CNTL2); + panel_cntl->stored_backlight_registers.BL_PWM_PERIOD_CNTL = + REG_READ(BL_PWM_PERIOD_CNTL); + + REG_GET(PWRSEQ_REF_DIV, BL_PWM_REF_DIV, + &panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); + } + + // Have driver take backlight control + // TakeBacklightControl(true) + value = REG_READ(BIOS_SCRATCH_2); + value |= ATOM_S2_VRI_BRIGHT_ENABLE; + REG_WRITE(BIOS_SCRATCH_2, value); + + // Enable the backlight output + REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); + + // Unlock group 2 backlight registers + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_LOCK, 0); + + current_backlight = calculate_16_bit_backlight_from_pwm(dce_panel_cntl); + + return current_backlight; } bool dce_is_panel_backlight_on(struct panel_cntl *panel_cntl) @@ -55,7 +160,7 @@ 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; - REG_GET(PWRSEQ_CNTL, BLON, &value); + REG_GET(PWRSEQ_CNTL, LVTMA_BLON, &value); return value; } @@ -65,13 +170,94 @@ 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; - REG_GET(PWRSEQ_STATE, PWRSEQ_TARGET_STATE_R, &pwr_seq_state); + REG_GET(PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &pwr_seq_state); - REG_GET_2(PWRSEQ_CNTL, DIGON, &dig_on, DIGON_OVRD, &dig_on_ovrd); + REG_GET_2(PWRSEQ_CNTL, LVTMA_DIGON, &dig_on, LVTMA_DIGON_OVRD, &dig_on_ovrd); return (pwr_seq_state == 1) || (dig_on == 1 && dig_on_ovrd == 1); } +void dce_store_backlight_level(struct panel_cntl *panel_cntl) +{ + struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl); + + panel_cntl->stored_backlight_registers.BL_PWM_CNTL = + REG_READ(BL_PWM_CNTL); + panel_cntl->stored_backlight_registers.BL_PWM_CNTL2 = + REG_READ(BL_PWM_CNTL2); + panel_cntl->stored_backlight_registers.BL_PWM_PERIOD_CNTL = + REG_READ(BL_PWM_PERIOD_CNTL); + + REG_GET(PWRSEQ_REF_DIV, BL_PWM_REF_DIV, + &panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); +} + +void dce_driver_set_backlight(struct panel_cntl *panel_cntl, + uint32_t backlight_pwm_u16_16) +{ + uint32_t backlight_16bit; + uint32_t masked_pwm_period; + uint8_t bit_count; + uint64_t active_duty_cycle; + uint32_t pwm_period_bitcnt; + struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl); + + /* + * 1. Find 16 bit backlight active duty cycle, where 0 <= backlight + * active duty cycle <= backlight period + */ + + /* 1.1 Apply bitmask for backlight period value based on value of BITCNT + */ + REG_GET_2(BL_PWM_PERIOD_CNTL, + BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt, + BL_PWM_PERIOD, &masked_pwm_period); + + if (pwm_period_bitcnt == 0) + bit_count = 16; + else + bit_count = pwm_period_bitcnt; + + /* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */ + masked_pwm_period = masked_pwm_period & ((1 << bit_count) - 1); + + /* 1.2 Calculate integer active duty cycle required upper 16 bits + * contain integer component, lower 16 bits contain fractional component + * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24 + */ + active_duty_cycle = backlight_pwm_u16_16 * masked_pwm_period; + + /* 1.3 Calculate 16 bit active duty cycle from integer and fractional + * components shift by bitCount then mask 16 bits and add rounding bit + * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0 + */ + backlight_16bit = active_duty_cycle >> bit_count; + backlight_16bit &= 0xFFFF; + backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1; + + /* + * 2. Program register with updated value + */ + + /* 2.1 Lock group 2 backlight registers */ + + REG_UPDATE_2(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1, + BL_PWM_GRP1_REG_LOCK, 1); + + // 2.2 Write new active duty cycle + REG_UPDATE(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, backlight_16bit); + + /* 2.3 Unlock group 2 backlight registers */ + REG_UPDATE(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_LOCK, 0); + + /* 3 Wait for pending bit to be cleared */ + REG_WAIT(BL_PWM_GRP1_REG_LOCK, + BL_PWM_GRP1_REG_UPDATE_PENDING, 0, + 1, 10000); +} + static void dce_panel_cntl_destroy(struct panel_cntl **panel_cntl) { struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(*panel_cntl); @@ -85,7 +271,8 @@ static const struct panel_cntl_funcs dce_link_panel_cntl_funcs = { .hw_init = dce_panel_cntl_hw_init, .is_panel_backlight_on = dce_is_panel_backlight_on, .is_panel_powered_on = dce_is_panel_powered_on, - + .store_backlight_level = dce_store_backlight_level, + .driver_set_backlight = dce_driver_set_backlight, }; void dce_panel_cntl_construct( @@ -95,6 +282,13 @@ void dce_panel_cntl_construct( const struct dce_panel_cntl_shift *shift, const struct dce_panel_cntl_mask *mask) { + struct panel_cntl *base = &dce_panel_cntl->base; + + base->stored_backlight_registers.BL_PWM_CNTL = 0; + base->stored_backlight_registers.BL_PWM_CNTL2 = 0; + base->stored_backlight_registers.BL_PWM_PERIOD_CNTL = 0; + base->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV = 0; + dce_panel_cntl->regs = regs; dce_panel_cntl->shift = shift; dce_panel_cntl->mask = mask; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h index 6dc6984f9248..70ec691e14d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h @@ -35,10 +35,12 @@ #define DCE_PANEL_CNTL_REG_LIST()\ DCE_PANEL_CNTL_SR(PWRSEQ_CNTL, LVTMA), \ DCE_PANEL_CNTL_SR(PWRSEQ_STATE, LVTMA), \ + DCE_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \ SR(BL_PWM_CNTL), \ SR(BL_PWM_CNTL2), \ SR(BL_PWM_PERIOD_CNTL), \ - SR(BL_PWM_GRP1_REG_LOCK) + SR(BL_PWM_GRP1_REG_LOCK), \ + SR(BIOS_SCRATCH_2) #define DCN_PANEL_CNTL_SR(reg_name, block)\ .reg_name = BASE(mm ## block ## _ ## reg_name ## _BASE_IDX) + \ @@ -47,33 +49,37 @@ #define DCN_PANEL_CNTL_REG_LIST()\ DCN_PANEL_CNTL_SR(PWRSEQ_CNTL, LVTMA), \ DCN_PANEL_CNTL_SR(PWRSEQ_STATE, LVTMA), \ + DCE_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \ SR(BL_PWM_CNTL), \ SR(BL_PWM_CNTL2), \ SR(BL_PWM_PERIOD_CNTL), \ - SR(BL_PWM_GRP1_REG_LOCK) + SR(BL_PWM_GRP1_REG_LOCK), \ + SR(BIOS_SCRATCH_2) -#define DCE_PANEL_CNTL_SF(block, reg_name, field_name, post_fix)\ - .field_name = block ## reg_name ## __ ## block ## field_name ## post_fix +#define DCE_PANEL_CNTL_SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix #define DCE_PANEL_CNTL_MASK_SH_LIST(mask_sh) \ - DCE_PANEL_CNTL_SF(LVTMA_, PWRSEQ_CNTL, BLON, mask_sh),\ - DCE_PANEL_CNTL_SF(LVTMA_, PWRSEQ_CNTL, DIGON, mask_sh),\ - DCE_PANEL_CNTL_SF(LVTMA_, PWRSEQ_CNTL, DIGON_OVRD, mask_sh),\ - DCE_PANEL_CNTL_SF(LVTMA_, PWRSEQ_STATE, PWRSEQ_TARGET_STATE_R, mask_sh), \ - DCE_PANEL_CNTL_SF(, BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, mask_sh), \ - DCE_PANEL_CNTL_SF(, BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, mask_sh), \ - DCE_PANEL_CNTL_SF(, BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, mask_sh), \ - DCE_PANEL_CNTL_SF(, BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, mask_sh), \ - DCE_PANEL_CNTL_SF(, BL_PWM_CNTL, BL_PWM_EN, mask_sh), \ - DCE_PANEL_CNTL_SF(, BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, mask_sh), \ - DCE_PANEL_CNTL_SF(, BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_LOCK, mask_sh), \ - DCE_PANEL_CNTL_SF(, BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING, mask_sh) + DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ + DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, mask_sh),\ + DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON_OVRD, mask_sh),\ + DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh), \ + DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, mask_sh), \ + DCE_PANEL_CNTL_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, mask_sh), \ + DCE_PANEL_CNTL_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, mask_sh), \ + DCE_PANEL_CNTL_SF(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, mask_sh), \ + DCE_PANEL_CNTL_SF(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, mask_sh), \ + DCE_PANEL_CNTL_SF(BL_PWM_CNTL, BL_PWM_EN, mask_sh), \ + DCE_PANEL_CNTL_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, mask_sh), \ + DCE_PANEL_CNTL_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_LOCK, mask_sh), \ + DCE_PANEL_CNTL_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING, mask_sh) #define DCE_PANEL_CNTL_REG_FIELD_LIST(type) \ - type BLON;\ - type DIGON;\ - type DIGON_OVRD;\ - type PWRSEQ_TARGET_STATE_R; \ + type LVTMA_BLON;\ + type LVTMA_DIGON;\ + type LVTMA_DIGON_OVRD;\ + type LVTMA_PWRSEQ_TARGET_STATE_R; \ + type BL_PWM_REF_DIV; \ type BL_PWM_EN; \ type BL_ACTIVE_INT_FRAC_CNT; \ type BL_PWM_FRACTIONAL_EN; \ @@ -98,6 +104,8 @@ struct dce_panel_cntl_registers { uint32_t BL_PWM_CNTL2; uint32_t BL_PWM_PERIOD_CNTL; uint32_t BL_PWM_GRP1_REG_LOCK; + uint32_t PWRSEQ_REF_DIV; + uint32_t BIOS_SCRATCH_2; }; struct dce_panel_cntl { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 451574971b96..4cdaaf4d881c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -1336,7 +1336,6 @@ static void dce110_se_audio_setup( { struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); - uint32_t speakers = 0; uint32_t channels = 0; ASSERT(audio_info); @@ -1344,7 +1343,6 @@ static void dce110_se_audio_setup( /* This should not happen.it does so we don't get BSOD*/ return; - speakers = audio_info->flags.info.ALLSPEAKERS; channels = speakers_to_channels(audio_info->flags.speaker_flags).all; /* setup the audio stream source select (audio -> dig mapping) */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c index 06d39d529c09..da0b29abfbda 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c @@ -27,7 +27,7 @@ #include "dce_abm.h" #include "dc.h" #include "dc_dmub_srv.h" -#include "dmub/inc/dmub_srv.h" +#include "dmub/dmub_srv.h" #include "core_types.h" #include "dm_services.h" #include "reg_helper.h" @@ -70,53 +70,6 @@ static bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t panel return true; } -static unsigned int calculate_16_bit_backlight_from_pwm(struct dce_abm *dce_abm) -{ - uint64_t current_backlight; - uint32_t round_result; - uint32_t bl_period, bl_int_count; - uint32_t bl_pwm, fractional_duty_cycle_en; - uint32_t bl_period_mask, bl_pwm_mask; - - REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, &bl_period); - REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, &bl_int_count); - - REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &bl_pwm); - REG_GET(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, &fractional_duty_cycle_en); - - if (bl_int_count == 0) - bl_int_count = 16; - - bl_period_mask = (1 << bl_int_count) - 1; - bl_period &= bl_period_mask; - - bl_pwm_mask = bl_period_mask << (16 - bl_int_count); - - if (fractional_duty_cycle_en == 0) - bl_pwm &= bl_pwm_mask; - else - bl_pwm &= 0xFFFF; - - current_backlight = (uint64_t)bl_pwm << (1 + bl_int_count); - - if (bl_period == 0) - bl_period = 0xFFFF; - - current_backlight = div_u64(current_backlight, bl_period); - current_backlight = (current_backlight + 1) >> 1; - - current_backlight = (uint64_t)(current_backlight) * bl_period; - - round_result = (uint32_t)(current_backlight & 0xFFFFFFFF); - - round_result = (round_result >> (bl_int_count-1)) & 1; - - current_backlight >>= bl_int_count; - current_backlight += round_result; - - return (uint32_t)(current_backlight); -} - static void dmcub_set_backlight_level( struct dce_abm *dce_abm, uint32_t backlight_pwm_u16_16, @@ -178,10 +131,9 @@ static void dmub_abm_enable_fractional_pwm(struct dc_context *dc) dc_dmub_srv_wait_idle(dc->dmub_srv); } -static void dmub_abm_init(struct abm *abm) +static void dmub_abm_init(struct abm *abm, uint32_t backlight) { struct dce_abm *dce_abm = TO_DMUB_ABM(abm); - unsigned int backlight = calculate_16_bit_backlight_from_pwm(dce_abm); REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103); REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101); @@ -261,77 +213,8 @@ static bool dmub_abm_set_level(struct abm *abm, uint32_t level) static bool dmub_abm_immediate_disable(struct abm *abm, uint32_t panel_inst) { - struct dce_abm *dce_abm = TO_DMUB_ABM(abm); - dmub_abm_set_pipe(abm, DISABLE_ABM_IMMEDIATELY, panel_inst); - abm->stored_backlight_registers.BL_PWM_CNTL = - REG_READ(BL_PWM_CNTL); - abm->stored_backlight_registers.BL_PWM_CNTL2 = - REG_READ(BL_PWM_CNTL2); - abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL = - REG_READ(BL_PWM_PERIOD_CNTL); - - REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, - &abm->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); - - return true; -} - -static bool dmub_abm_init_backlight(struct abm *abm) -{ - struct dce_abm *dce_abm = TO_DMUB_ABM(abm); - uint32_t value; - - /* It must not be 0, so we have to restore them - * Bios bug w/a - period resets to zero, - * restoring to cache values which is always correct - */ - REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value); - - if (value == 0 || value == 1) { - if (abm->stored_backlight_registers.BL_PWM_CNTL != 0) { - REG_WRITE(BL_PWM_CNTL, - abm->stored_backlight_registers.BL_PWM_CNTL); - REG_WRITE(BL_PWM_CNTL2, - abm->stored_backlight_registers.BL_PWM_CNTL2); - REG_WRITE(BL_PWM_PERIOD_CNTL, - abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL); - REG_UPDATE(LVTMA_PWRSEQ_REF_DIV, - BL_PWM_REF_DIV, - abm->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); - } else { - /* TODO: Note: This should not really happen since VBIOS - * should have initialized PWM registers on boot. - */ - REG_WRITE(BL_PWM_CNTL, 0xC000FA00); - REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0); - } - } else { - abm->stored_backlight_registers.BL_PWM_CNTL = - REG_READ(BL_PWM_CNTL); - abm->stored_backlight_registers.BL_PWM_CNTL2 = - REG_READ(BL_PWM_CNTL2); - abm->stored_backlight_registers.BL_PWM_PERIOD_CNTL = - REG_READ(BL_PWM_PERIOD_CNTL); - - REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, - &abm->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV); - } - - // Have driver take backlight control - // TakeBacklightControl(true) - value = REG_READ(BIOS_SCRATCH_2); - value |= ATOM_S2_VRI_BRIGHT_ENABLE; - REG_WRITE(BIOS_SCRATCH_2, value); - - // Enable the backlight output - REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1); - - // Unlock group 2 backlight registers - REG_UPDATE(BL_PWM_GRP1_REG_LOCK, - BL_PWM_GRP1_REG_LOCK, 0); - return true; } @@ -340,8 +223,7 @@ static bool dmub_abm_set_backlight_level_pwm( unsigned int backlight_pwm_u16_16, unsigned int frame_ramp, unsigned int otg_inst, - uint32_t panel_inst, - bool fw_set_brightness) + uint32_t panel_inst) { struct dce_abm *dce_abm = TO_DMUB_ABM(abm); @@ -384,7 +266,6 @@ static bool dmub_abm_init_config(struct abm *abm, static const struct abm_funcs abm_funcs = { .abm_init = dmub_abm_init, .set_abm_level = dmub_abm_set_level, - .init_backlight = dmub_abm_init_backlight, .set_pipe = dmub_abm_set_pipe, .set_backlight_level_pwm = dmub_abm_set_backlight_level_pwm, .get_current_backlight = dmub_abm_get_current_backlight, @@ -404,10 +285,6 @@ static void dmub_abm_construct( base->ctx = ctx; base->funcs = &abm_funcs; - base->stored_backlight_registers.BL_PWM_CNTL = 0; - base->stored_backlight_registers.BL_PWM_CNTL2 = 0; - base->stored_backlight_registers.BL_PWM_PERIOD_CNTL = 0; - base->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV = 0; base->dmcu_is_running = false; abm_dce->regs = regs; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 9f12c76f21ab..044a0133ebb1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -26,8 +26,7 @@ #include "dmub_psr.h" #include "dc.h" #include "dc_dmub_srv.h" -#include "dmub/inc/dmub_srv.h" -#include "dmub/inc/dmub_gpint_cmd.h" +#include "dmub/dmub_srv.h" #include "core_types.h" #define MAX_PIPES 6 @@ -94,12 +93,20 @@ static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state * union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx; - if (stream->link->psr_settings.psr_version == PSR_VERSION_UNSUPPORTED) + if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED) return false; cmd.psr_set_version.header.type = DMUB_CMD__PSR; cmd.psr_set_version.header.sub_type = DMUB_CMD__PSR_SET_VERSION; - cmd.psr_set_version.psr_set_version_data.version = stream->link->psr_settings.psr_version; + switch (stream->link->psr_settings.psr_version) { + case DC_PSR_VERSION_1: + cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_1; + break; + case DC_PSR_VERSION_UNSUPPORTED: + default: + cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_UNSUPPORTED; + break; + } cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data); dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 6bd8d4e1c294..b77e9dc16086 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1066,7 +1066,7 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { hws->funcs.edp_backlight_control(link, false); - dc_link_set_abm_disable(link); + link->dc->hwss.set_abm_immediate_disable(pipe_ctx); } if (dc_is_dp_signal(pipe_ctx->stream->signal)) @@ -2355,6 +2355,7 @@ static void init_hw(struct dc *dc) struct abm *abm; struct dmcu *dmcu; struct dce_hwseq *hws = dc->hwseq; + uint32_t backlight = MAX_BACKLIGHT_LEVEL; bp = dc->ctx->dc_bios; for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -2401,12 +2402,17 @@ static void init_hw(struct dc *dc) audio->funcs->hw_init(audio); } - abm = dc->res_pool->abm; - if (abm != NULL) { - abm->funcs->init_backlight(abm); - abm->funcs->abm_init(abm); + for (i = 0; i < dc->link_count; i++) { + struct dc_link *link = dc->links[i]; + + if (link->panel_cntl) + backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); } + abm = dc->res_pool->abm; + if (abm != NULL) + abm->funcs->abm_init(abm, backlight); + dmcu = dc->res_pool->dmcu; if (dmcu != NULL && abm != NULL) abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu); @@ -2721,6 +2727,7 @@ bool dce110_set_backlight_level(struct pipe_ctx *pipe_ctx, struct dc_link *link = pipe_ctx->stream->link; struct dc *dc = link->ctx->dc; struct abm *abm = pipe_ctx->stream_res.abm; + struct panel_cntl *panel_cntl = link->panel_cntl; struct dmcu *dmcu = dc->res_pool->dmcu; bool fw_set_brightness = true; /* DMCU -1 for all controller id values, @@ -2728,23 +2735,38 @@ bool dce110_set_backlight_level(struct pipe_ctx *pipe_ctx, */ uint32_t controller_id = pipe_ctx->stream_res.tg->inst + 1; - if (abm == NULL || (abm->funcs->set_backlight_level_pwm == NULL)) + if (abm == NULL || panel_cntl == NULL || (abm->funcs->set_backlight_level_pwm == NULL)) return false; if (dmcu) fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); - abm->funcs->set_backlight_level_pwm( - abm, - backlight_pwm_u16_16, - frame_ramp, - controller_id, - link->panel_cntl->inst, - fw_set_brightness); + if (!fw_set_brightness && panel_cntl->funcs->driver_set_backlight) + panel_cntl->funcs->driver_set_backlight(panel_cntl, backlight_pwm_u16_16); + else + abm->funcs->set_backlight_level_pwm( + abm, + backlight_pwm_u16_16, + frame_ramp, + controller_id, + link->panel_cntl->inst); return true; } +void dce110_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx) +{ + struct abm *abm = pipe_ctx->stream_res.abm; + struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl; + + if (abm) + abm->funcs->set_abm_immediate_disable(abm, + pipe_ctx->stream->link->panel_cntl->inst); + + if (panel_cntl) + panel_cntl->funcs->store_backlight_level(panel_cntl); +} + static const struct hw_sequencer_funcs dce110_funcs = { .program_gamut_remap = program_gamut_remap, .program_output_csc = program_output_csc, @@ -2781,6 +2803,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .set_cursor_position = dce110_set_cursor_position, .set_cursor_attribute = dce110_set_cursor_attribute, .set_backlight_level = dce110_set_backlight_level, + .set_abm_immediate_disable = dce110_set_abm_immediate_disable, }; static const struct hwseq_private_funcs dce110_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index e609a72b4634..fe5326df00f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -88,6 +88,7 @@ void dce110_edp_wait_for_hpd_ready( bool dce110_set_backlight_level(struct pipe_ctx *pipe_ctx, uint32_t backlight_pwm_u16_16, uint32_t frame_ramp); +void dce110_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx); #endif /* __DC_HWSS_DCE110_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index 0e682b5aa3eb..7f8456b9988b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -134,13 +134,6 @@ bool dpp1_get_optimal_number_of_taps( struct scaler_data *scl_data, const struct scaling_taps *in_taps) { - uint32_t pixel_width; - - if (scl_data->viewport.width > scl_data->recout.width) - pixel_width = scl_data->recout.width; - else - pixel_width = scl_data->viewport.width; - /* Some ASICs does not support FP16 scaling, so we reject modes require this*/ if (scl_data->format == PIXEL_FORMAT_FP16 && dpp->caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT && diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 2eb5d0e3e425..f36d1f57b846 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -826,6 +826,14 @@ enum dc_status dcn10_enable_stream_timing( color_space = stream->output_color_space; color_space_to_black_color(dc, color_space, &black_color); + /* + * The way 420 is packed, 2 channels carry Y component, 1 channel + * alternate between Cb and Cr, so both channels need the pixel + * value for Y + */ + if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + black_color.color_r_cr = black_color.color_g_y; + if (pipe_ctx->stream_res.tg->funcs->set_blank_color) pipe_ctx->stream_res.tg->funcs->set_blank_color( pipe_ctx->stream_res.tg, @@ -903,8 +911,7 @@ static void dcn10_reset_back_end_for_pipe( if (pipe_ctx->top_pipe == NULL) { if (pipe_ctx->stream_res.abm) - pipe_ctx->stream_res.abm->funcs->set_abm_immediate_disable(pipe_ctx->stream_res.abm, - pipe_ctx->stream->link->panel_cntl->inst); + dc->hwss.set_abm_immediate_disable(pipe_ctx); pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); @@ -1245,6 +1252,7 @@ void dcn10_init_hw(struct dc *dc) struct dce_hwseq *hws = dc->hwseq; struct dc_bios *dcb = dc->ctx->dc_bios; struct resource_pool *res_pool = dc->res_pool; + uint32_t backlight = MAX_BACKLIGHT_LEVEL; if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); @@ -1411,11 +1419,16 @@ void dcn10_init_hw(struct dc *dc) audio->funcs->hw_init(audio); } - if (abm != NULL) { - abm->funcs->init_backlight(abm); - abm->funcs->abm_init(abm); + for (i = 0; i < dc->link_count; i++) { + struct dc_link *link = dc->links[i]; + + if (link->panel_cntl) + backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl); } + if (abm != NULL) + abm->funcs->abm_init(abm, backlight); + if (dmcu != NULL && !dmcu->auto_load_dmcu) dmcu->funcs->dmcu_init(dmcu); @@ -2249,6 +2262,14 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) &blnd_cfg.black_color); } + /* + * The way 420 is packed, 2 channels carry Y component, 1 channel + * alternate between Cb and Cr, so both channels need the pixel + * value for Y + */ + if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + blnd_cfg.black_color.color_r_cr = blnd_cfg.black_color.color_g_y; + if (per_pixel_alpha) blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA; else @@ -2490,9 +2511,7 @@ void dcn10_blank_pixel_data( stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level); } } else if (blank) { - if (stream_res->abm) - stream_res->abm->funcs->set_abm_immediate_disable(stream_res->abm, - stream->link->panel_cntl->inst); + dc->hwss.set_abm_immediate_disable(pipe_ctx); if (stream_res->tg->funcs->set_blank) stream_res->tg->funcs->set_blank(stream_res->tg, blank); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c index 6ff7e2bd1d4a..897a3d25685a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c @@ -73,6 +73,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .get_clock = dcn10_get_clock, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .set_backlight_level = dce110_set_backlight_level, + .set_abm_immediate_disable = dce110_set_abm_immediate_disable, }; static const struct hwseq_private_funcs dcn10_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index bacf865f55c0..17d5cb422025 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1121,24 +1121,6 @@ static enum dc_status build_mapped_resource( { struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - /*TODO Seems unneeded anymore */ - /* if (old_context && resource_is_stream_unchanged(old_context, stream)) { - if (stream != NULL && old_context->streams[i] != NULL) { - todo: shouldn't have to copy missing parameter here - resource_build_bit_depth_reduction_params(stream, - &stream->bit_depth_params); - stream->clamping.pixel_encoding = - stream->timing.pixel_encoding; - - resource_build_bit_depth_reduction_params(stream, - &stream->bit_depth_params); - build_clamping_params(stream); - - continue; - } - } - */ - if (!pipe_ctx) return DC_ERROR_UNEXPECTED; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index 7eba9333c328..07b2f9399671 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -1274,7 +1274,6 @@ static void enc1_se_audio_setup( { struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - uint32_t speakers = 0; uint32_t channels = 0; ASSERT(audio_info); @@ -1282,7 +1281,6 @@ static void enc1_se_audio_setup( /* This should not happen.it does so we don't get BSOD*/ return; - speakers = audio_info->flags.info.ALLSPEAKERS; channels = speakers_to_channels(audio_info->flags.speaker_flags).all; /* setup the audio stream source select (audio -> dig mapping) */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 3a290ccaeb82..da5333d165ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -961,9 +961,7 @@ void dcn20_blank_pixel_data( width = width / odm_cnt; if (blank) { - if (stream_res->abm) - stream_res->abm->funcs->set_abm_immediate_disable(stream_res->abm, - stream->link->panel_cntl->inst); + dc->hwss.set_abm_immediate_disable(pipe_ctx); if (dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) { test_pattern = CONTROLLER_DP_TEST_PATTERN_COLORSQUARES; @@ -2042,9 +2040,7 @@ static void dcn20_reset_back_end_for_pipe( */ if (pipe_ctx->top_pipe == NULL) { - if (pipe_ctx->stream_res.abm) - pipe_ctx->stream_res.abm->funcs->set_abm_immediate_disable(pipe_ctx->stream_res.abm, - pipe_ctx->stream->link->panel_cntl->inst); + dc->hwss.set_abm_immediate_disable(pipe_ctx); pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index c83d98e0d211..a8bcd747d7ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -84,6 +84,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .set_flip_control_gsl = dcn20_set_flip_control_gsl, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .set_backlight_level = dce110_set_backlight_level, + .set_abm_immediate_disable = dce110_set_abm_immediate_disable, }; static const struct hwseq_private_funcs dcn20_private_funcs = { 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 60ea499c1ca8..778e2e8fd2c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1653,24 +1653,6 @@ enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state enum dc_status status = DC_OK; struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream); - /*TODO Seems unneeded anymore */ - /* if (old_context && resource_is_stream_unchanged(old_context, stream)) { - if (stream != NULL && old_context->streams[i] != NULL) { - todo: shouldn't have to copy missing parameter here - resource_build_bit_depth_reduction_params(stream, - &stream->bit_depth_params); - stream->clamping.pixel_encoding = - stream->timing.pixel_encoding; - - resource_build_bit_depth_reduction_params(stream, - &stream->bit_depth_params); - build_clamping_params(stream); - - continue; - } - } - */ - if (!pipe_ctx) return DC_ERROR_UNEXPECTED; @@ -1940,7 +1922,7 @@ bool dcn20_split_stream_for_odm( return true; } -bool dcn20_split_stream_for_mpc( +void dcn20_split_stream_for_mpc( struct resource_context *res_ctx, const struct resource_pool *pool, struct pipe_ctx *primary_pipe, @@ -1969,11 +1951,6 @@ bool dcn20_split_stream_for_mpc( secondary_pipe->top_pipe = primary_pipe; ASSERT(primary_pipe->plane_state); - if (!resource_build_scaling_params(primary_pipe) || - !resource_build_scaling_params(secondary_pipe)) - return false; - - return true; } void dcn20_populate_dml_writeback_from_context( @@ -2599,11 +2576,32 @@ static void dcn20_merge_pipes_for_validate( } } +int dcn20_find_previous_split_count(struct pipe_ctx *pipe) +{ + int previous_split = 1; + struct pipe_ctx *current_pipe = pipe; + + while (current_pipe->bottom_pipe) { + if (current_pipe->plane_state != current_pipe->bottom_pipe->plane_state) + break; + previous_split++; + current_pipe = current_pipe->bottom_pipe; + } + current_pipe = pipe; + while (current_pipe->top_pipe) { + if (current_pipe->plane_state != current_pipe->top_pipe->plane_state) + break; + previous_split++; + current_pipe = current_pipe->top_pipe; + } + return previous_split; +} + int dcn20_validate_apply_pipe_split_flags( struct dc *dc, struct dc_state *context, int vlevel, - bool *split, + int *split, bool *merge) { int i, pipe_idx, vlevel_split; @@ -2658,8 +2656,14 @@ int dcn20_validate_apply_pipe_split_flags( if (!context->res_ctx.pipe_ctx[i].stream) continue; - if (force_split || context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_plane] > 1) - split[i] = true; + if (force_split + || context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_plane] > 1) { + if (context->stream_count == 1 && plane_count == 1 + && dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4) + split[i] = 4; + else + split[i] = 2; + } if ((pipe->stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || pipe->stream->view_format == @@ -2668,9 +2672,9 @@ int dcn20_validate_apply_pipe_split_flags( TIMING_3D_FORMAT_TOP_AND_BOTTOM || pipe->stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE)) - split[i] = true; + split[i] = 2; if (dc->debug.force_odm_combine & (1 << pipe->stream_res.tg->inst)) { - split[i] = true; + split[i] = 2; context->bw_ctx.dml.vba.ODMCombineEnablePerState[vlevel][pipe_plane] = dm_odm_combine_mode_2to1; } context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] = @@ -2678,39 +2682,58 @@ int dcn20_validate_apply_pipe_split_flags( if (pipe->prev_odm_pipe && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] != dm_odm_combine_mode_disabled) { /*Already split odm pipe tree, don't try to split again*/ - split[i] = false; - split[pipe->prev_odm_pipe->pipe_idx] = false; + split[i] = 0; + split[pipe->prev_odm_pipe->pipe_idx] = 0; } else if (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_plane] == dm_odm_combine_mode_disabled) { - /*Already split mpc tree, don't try to split again, assumes only 2x mpc combine*/ - split[i] = false; - split[pipe->top_pipe->pipe_idx] = false; - } else if (pipe->prev_odm_pipe || (pipe->top_pipe && pipe->plane_state == pipe->top_pipe->plane_state)) { - if (split[i] == false) { + /*If 2 way split but can support 4 way split, then split each pipe again*/ + if (context->stream_count == 1 && plane_count == 1 + && dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4) { + split[i] = 2; + } else { + split[i] = 0; + split[pipe->top_pipe->pipe_idx] = 0; + } + } else if (pipe->prev_odm_pipe || (dcn20_find_previous_split_count(pipe) == 2 && pipe->top_pipe)) { + if (split[i] == 0) { /*Exiting mpc/odm combine*/ merge[i] = true; - if (pipe->prev_odm_pipe) { - ASSERT(0); /*should not actually happen yet*/ - merge[pipe->prev_odm_pipe->pipe_idx] = true; - } else - merge[pipe->top_pipe->pipe_idx] = true; } else { /*Transition from mpc combine to odm combine or vice versa*/ ASSERT(0); /*should not actually happen yet*/ - split[i] = true; + split[i] = 2; merge[i] = true; if (pipe->prev_odm_pipe) { - split[pipe->prev_odm_pipe->pipe_idx] = true; + split[pipe->prev_odm_pipe->pipe_idx] = 2; merge[pipe->prev_odm_pipe->pipe_idx] = true; } else { - split[pipe->top_pipe->pipe_idx] = true; + split[pipe->top_pipe->pipe_idx] = 2; merge[pipe->top_pipe->pipe_idx] = true; } } + } else if (dcn20_find_previous_split_count(pipe) == 3) { + if (split[i] == 0 && !pipe->top_pipe) { + merge[pipe->bottom_pipe->pipe_idx] = true; + merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; + } else if (split[i] == 2 && !pipe->top_pipe) { + merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; + split[i] = 0; + } + } else if (dcn20_find_previous_split_count(pipe) == 4) { + if (split[i] == 0 && !pipe->top_pipe) { + merge[pipe->bottom_pipe->pipe_idx] = true; + merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; + merge[pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; + } else if (split[i] == 2 && !pipe->top_pipe) { + merge[pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; + merge[pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx] = true; + split[i] = 0; + } } /* Adjust dppclk when split is forced, do not bother with dispclk */ - if (split[i] && context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] == 1) + if (split[i] != 0 + && context->bw_ctx.dml.vba.NoOfDPP[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] == 1) context->bw_ctx.dml.vba.RequiredDPPCLK[vlevel][context->bw_ctx.dml.vba.maxMpcComb][pipe_idx] /= 2; pipe_idx++; } @@ -2727,7 +2750,7 @@ bool dcn20_fast_validate_bw( int *vlevel_out) { bool out = false; - bool split[MAX_PIPES] = { false }; + int split[MAX_PIPES] = { 0 }; int pipe_cnt, i, pipe_idx, vlevel; ASSERT(pipes); @@ -2787,7 +2810,7 @@ bool dcn20_fast_validate_bw( && context->bw_ctx.dml.vba.ODMCombineEnabled[pipe_idx]) goto validate_fail; - if (split[i]) { + if (split[i] == 2) { if (!hsplit_pipe || hsplit_pipe->plane_state != pipe->plane_state) { /* pipe not split previously needs split */ hsplit_pipe = dcn20_find_secondary_pipe(dc, &context->res_ctx, dc->res_pool, pipe); @@ -2802,11 +2825,13 @@ bool dcn20_fast_validate_bw( pipe, hsplit_pipe)) goto validate_fail; dcn20_build_mapped_resource(dc, context, pipe->stream); - } else - if (!dcn20_split_stream_for_mpc( + } else { + dcn20_split_stream_for_mpc( &context->res_ctx, dc->res_pool, - pipe, hsplit_pipe)) + pipe, hsplit_pipe); + if (!resource_build_scaling_params(pipe) || !resource_build_scaling_params(hsplit_pipe)) goto validate_fail; + } pipe_split_from[hsplit_pipe->pipe_idx] = pipe_idx; } } else if (hsplit_pipe && hsplit_pipe->plane_state == pipe->plane_state) { @@ -3107,25 +3132,34 @@ validate_out: return out; } - -bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, - bool fast_validate) +/* + * This must be noinline to ensure anything that deals with FP registers + * is contained within this call; previously our compiling with hard-float + * would result in fp instructions being emitted outside of the boundaries + * of the DC_FP_START/END macros, which makes sense as the compiler has no + * idea about what is wrapped and what is not + * + * This is largely just a workaround to avoid breakage introduced with 5.6, + * ideally all fp-using code should be moved into its own file, only that + * should be compiled with hard-float, and all code exported from there + * should be strictly wrapped with DC_FP_START/END + */ +static noinline bool dcn20_validate_bandwidth_fp(struct dc *dc, + struct dc_state *context, bool fast_validate) { bool voltage_supported = false; bool full_pstate_supported = false; bool dummy_pstate_supported = false; double p_state_latency_us; - DC_FP_START(); p_state_latency_us = context->bw_ctx.dml.soc.dram_clock_change_latency_us; context->bw_ctx.dml.soc.disable_dram_clock_change_vactive_support = dc->debug.disable_dram_clock_change_vactive_support; + context->bw_ctx.dml.soc.allow_dram_clock_one_display_vactive = + dc->debug.enable_dram_clock_change_one_display_vactive; if (fast_validate) { - voltage_supported = dcn20_validate_bandwidth_internal(dc, context, true); - - DC_FP_END(); - return voltage_supported; + return dcn20_validate_bandwidth_internal(dc, context, true); } // Best case, we support full UCLK switch latency @@ -3154,7 +3188,15 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, restore_dml_state: context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us; + return voltage_supported; +} +bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, + bool fast_validate) +{ + bool voltage_supported = false; + DC_FP_START(); + voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate); DC_FP_END(); return voltage_supported; } @@ -3213,8 +3255,6 @@ static struct dc_cap_funcs cap_funcs = { enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_state) { - enum dc_status result = DC_OK; - enum surface_pixel_format surf_pix_format = plane_state->format; unsigned int bpp = resource_pixel_format_to_bpp(surf_pix_format); @@ -3226,7 +3266,7 @@ enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_stat swizzle = DC_SW_64KB_S; plane_state->tiling_info.gfx9.swizzle = swizzle; - return result; + return DC_OK; } static struct resource_funcs dcn20_res_pool_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h index 578265ccbf5b..d5448c9b0e15 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h @@ -119,17 +119,18 @@ void dcn20_set_mcif_arb_params( display_e2e_pipe_params_st *pipes, int pipe_cnt); bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate); +int dcn20_find_previous_split_count(struct pipe_ctx *pipe); int dcn20_validate_apply_pipe_split_flags( struct dc *dc, struct dc_state *context, int vlevel, - bool *split, + int *split, bool *merge); void dcn20_release_dsc(struct resource_context *res_ctx, const struct resource_pool *pool, struct display_stream_compressor **dsc); bool dcn20_validate_dsc(struct dc *dc, struct dc_state *new_ctx); -bool dcn20_split_stream_for_mpc( +void dcn20_split_stream_for_mpc( struct resource_context *res_ctx, const struct resource_pool *pool, struct pipe_ctx *primary_pipe, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index ae05a8bfdae1..e97dfaa656e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -86,13 +86,9 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .optimize_pwr_state = dcn21_optimize_pwr_state, .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, - .set_cursor_position = dcn10_set_cursor_position, - .set_cursor_attribute = dcn10_set_cursor_attribute, - .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level, - .optimize_pwr_state = dcn21_optimize_pwr_state, - .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, .power_down = dce110_power_down, .set_backlight_level = dce110_set_backlight_level, + .set_abm_immediate_disable = dce110_set_abm_immediate_disable, }; static const struct hwseq_private_funcs dcn21_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index ceaf70a934c3..419cdde624f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1384,7 +1384,8 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param struct dcn21_resource_pool *pool = TO_DCN21_RES_POOL(dc->res_pool); struct clk_limit_table *clk_table = &bw_params->clk_table; struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; - unsigned int i, j, closest_clk_lvl; + unsigned int i, closest_clk_lvl; + int j; // Default clock levels are used for diags, which may lead to overclocking. if (!IS_DIAG_DC(dc->ctx->dce_environment)) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c index 922ab7169e52..80170f9721ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c @@ -2599,18 +2599,40 @@ static void dml20v2_DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndP } } + { + float SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank = 999999; + int PlaneWithMinActiveDRAMClockChangeMargin = -1; + mode_lib->vba.MinActiveDRAMClockChangeMargin = 999999; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] < mode_lib->vba.MinActiveDRAMClockChangeMargin) { mode_lib->vba.MinActiveDRAMClockChangeMargin = mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]; + if (mode_lib->vba.BlendingAndTiming[k] == k) { + PlaneWithMinActiveDRAMClockChangeMargin = k; + } else { + for (j = 0; j < mode_lib->vba.NumberOfActivePlanes; ++j) { + if (mode_lib->vba.BlendingAndTiming[k] == j) { + PlaneWithMinActiveDRAMClockChangeMargin = j; + } + } + } } } mode_lib->vba.MinActiveDRAMClockChangeLatencySupported = mode_lib->vba.MinActiveDRAMClockChangeMargin + mode_lib->vba.DRAMClockChangeLatency; + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { + if (!((k == PlaneWithMinActiveDRAMClockChangeMargin) && (mode_lib->vba.BlendingAndTiming[k] == k)) + && !(mode_lib->vba.BlendingAndTiming[k] == PlaneWithMinActiveDRAMClockChangeMargin) + && mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] + < SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank) { + SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank = + mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]; + } + } if (mode_lib->vba.DRAMClockChangeSupportsVActive && mode_lib->vba.MinActiveDRAMClockChangeMargin > 60) { @@ -2629,7 +2651,11 @@ static void dml20v2_DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndP mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) { mode_lib->vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive; } else { - if (mode_lib->vba.SynchronizedVBlank || mode_lib->vba.NumberOfActivePlanes == 1) { + if ((mode_lib->vba.SynchronizedVBlank + || mode_lib->vba.NumberOfActivePlanes == 1 + || (SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank > 0 && + mode_lib->vba.AllowDramClockChangeOneDisplayVactive)) + && mode_lib->vba.PrefetchMode[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb] == 0) { mode_lib->vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vblank; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { if (!mode_lib->vba.AllowDRAMClockChangeDuringVBlank[k]) { @@ -2641,6 +2667,7 @@ static void dml20v2_DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndP mode_lib->vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_unsupported; } } + } for (k = 0; k <= mode_lib->vba.soc.num_states; k++) for (j = 0; j < 2; j++) mode_lib->vba.DRAMClockChangeSupport[k][j] = mode_lib->vba.DRAMClockChangeSupport[0][0]; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c index 5bc80b6084da..a576eed94d9b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c @@ -3190,6 +3190,7 @@ static void CalculateFlipSchedule( double TimeForFetchingRowInVBlankImmediateFlip; double ImmediateFlipBW; double HostVMInefficiencyFactor; + double VRatioClamped; if (GPUVMEnable == true && HostVMEnable == true) { HostVMInefficiencyFactor = @@ -3222,31 +3223,32 @@ static void CalculateFlipSchedule( *DestinationLinesToRequestRowInImmediateFlip = dml_ceil(4.0 * (TimeForFetchingRowInVBlankImmediateFlip / LineTime), 1) / 4.0; *final_flip_bw = dml_max(PDEAndMetaPTEBytesPerFrame * HostVMInefficiencyFactor / (*DestinationLinesToRequestVMInImmediateFlip * LineTime), (MetaRowBytes + DPTEBytesPerRow) * HostVMInefficiencyFactor / (*DestinationLinesToRequestRowInImmediateFlip * LineTime)); + VRatioClamped = (VRatio < 1.0) ? 1.0 : VRatio; if (SourcePixelFormat == dm_420_8 || SourcePixelFormat == dm_420_10) { if (GPUVMEnable == true && DCCEnable != true) { min_row_time = dml_min( - dpte_row_height * LineTime / VRatio, - dpte_row_height_chroma * LineTime / (VRatio / 2)); + dpte_row_height * LineTime / VRatioClamped, + dpte_row_height_chroma * LineTime / (VRatioClamped / 2)); } else if (GPUVMEnable != true && DCCEnable == true) { min_row_time = dml_min( - meta_row_height * LineTime / VRatio, - meta_row_height_chroma * LineTime / (VRatio / 2)); + meta_row_height * LineTime / VRatioClamped, + meta_row_height_chroma * LineTime / (VRatioClamped / 2)); } else { min_row_time = dml_min4( - dpte_row_height * LineTime / VRatio, - meta_row_height * LineTime / VRatio, - dpte_row_height_chroma * LineTime / (VRatio / 2), - meta_row_height_chroma * LineTime / (VRatio / 2)); + dpte_row_height * LineTime / VRatioClamped, + meta_row_height * LineTime / VRatioClamped, + dpte_row_height_chroma * LineTime / (VRatioClamped / 2), + meta_row_height_chroma * LineTime / (VRatioClamped / 2)); } } else { if (GPUVMEnable == true && DCCEnable != true) { - min_row_time = dpte_row_height * LineTime / VRatio; + min_row_time = dpte_row_height * LineTime / VRatioClamped; } else if (GPUVMEnable != true && DCCEnable == true) { - min_row_time = meta_row_height * LineTime / VRatio; + min_row_time = meta_row_height * LineTime / VRatioClamped; } else { min_row_time = dml_min( - dpte_row_height * LineTime / VRatio, - meta_row_height * LineTime / VRatio); + dpte_row_height * LineTime / VRatioClamped, + meta_row_height * LineTime / VRatioClamped); } } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c index 193f31b8ac4a..90a5fefef05b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c @@ -1200,7 +1200,7 @@ static void dml_rq_dlg_get_dlg_params( min_hratio_fact_l = 1.0; min_hratio_fact_c = 1.0; - if (htaps_l <= 1) + if (hratio_l <= 1) min_hratio_fact_l = 2.0; else if (htaps_l <= 6) { if ((hratio_l * 2.0) > 4.0) @@ -1216,7 +1216,7 @@ static void dml_rq_dlg_get_dlg_params( hscale_pixel_rate_l = min_hratio_fact_l * dppclk_freq_in_mhz; - if (htaps_c <= 1) + if (hratio_c <= 1) min_hratio_fact_c = 2.0; else if (htaps_c <= 6) { if ((hratio_c * 2.0) > 4.0) @@ -1533,8 +1533,8 @@ static void dml_rq_dlg_get_dlg_params( disp_dlg_regs->refcyc_per_vm_group_vblank = get_refcyc_per_vm_group_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz; disp_dlg_regs->refcyc_per_vm_group_flip = get_refcyc_per_vm_group_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz; - disp_dlg_regs->refcyc_per_vm_req_vblank = get_refcyc_per_vm_req_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz; - disp_dlg_regs->refcyc_per_vm_req_flip = get_refcyc_per_vm_req_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz; + disp_dlg_regs->refcyc_per_vm_req_vblank = get_refcyc_per_vm_req_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz * dml_pow(2, 10); + disp_dlg_regs->refcyc_per_vm_req_flip = get_refcyc_per_vm_req_flip(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz * dml_pow(2, 10); // Clamp to max for now if (disp_dlg_regs->refcyc_per_vm_group_vblank >= (unsigned int)dml_pow(2, 23)) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index b2ecb174a93f..439ffd04be34 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -118,6 +118,7 @@ struct _vcs_dpi_soc_bounding_box_st { double urgent_latency_adjustment_fabric_clock_component_us; double urgent_latency_adjustment_fabric_clock_reference_mhz; bool disable_dram_clock_change_vactive_support; + bool allow_dram_clock_one_display_vactive; }; struct _vcs_dpi_ip_params_st { diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 6e4e8a452e66..b19988f54721 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -224,6 +224,7 @@ static void fetch_socbb_params(struct display_mode_lib *mode_lib) mode_lib->vba.DummyPStateCheck = soc->dram_clock_change_latency_us == soc->dummy_pstate_latency_us; mode_lib->vba.DRAMClockChangeSupportsVActive = !soc->disable_dram_clock_change_vactive_support || mode_lib->vba.DummyPStateCheck; + mode_lib->vba.AllowDramClockChangeOneDisplayVactive = soc->allow_dram_clock_one_display_vactive; mode_lib->vba.Downspreading = soc->downspread_percent; mode_lib->vba.DRAMChannelWidth = soc->dram_channel_width_bytes; // new! diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index a1884ffe63ae..6a7b20927a6b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -899,6 +899,7 @@ struct vba_vars_st { double BPP; enum odm_combine_policy ODMCombinePolicy; bool UseMinimumRequiredDCFCLK; + bool AllowDramClockChangeOneDisplayVactive; }; bool CalculateMinAndMaxPrefetchMode( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h index 91a42f0f1fc4..e8ce8c85adf1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h @@ -27,27 +27,17 @@ #include "dm_services_types.h" -struct abm_backlight_registers { - unsigned int BL_PWM_CNTL; - unsigned int BL_PWM_CNTL2; - unsigned int BL_PWM_PERIOD_CNTL; - unsigned int LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; -}; - struct abm { struct dc_context *ctx; const struct abm_funcs *funcs; bool dmcu_is_running; - /* registers setting needs to be saved and restored at InitBacklight */ - struct abm_backlight_registers stored_backlight_registers; }; struct abm_funcs { - void (*abm_init)(struct abm *abm); + void (*abm_init)(struct abm *abm, uint32_t back_light); bool (*set_abm_level)(struct abm *abm, unsigned int abm_level); bool (*set_abm_immediate_disable)(struct abm *abm, unsigned int panel_inst); bool (*set_pipe)(struct abm *abm, unsigned int controller_id, unsigned int panel_inst); - bool (*init_backlight)(struct abm *abm); /* backlight_pwm_u16_16 is unsigned 32 bit, * 16 bit integer + 16 fractional, where 1.0 is max backlight value. @@ -56,8 +46,7 @@ struct abm_funcs { unsigned int backlight_pwm_u16_16, unsigned int frame_ramp, unsigned int controller_id, - unsigned int panel_inst, - bool fw_set_brightness); + unsigned int panel_inst); unsigned int (*get_current_backlight)(struct abm *abm); unsigned int (*get_target_backlight)(struct abm *abm); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h b/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h index 5a75d035f1fa..f9ab5abb6462 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h @@ -32,11 +32,23 @@ #include "dc_types.h" +#define MAX_BACKLIGHT_LEVEL 0xFFFF + +struct panel_cntl_backlight_registers { + unsigned int BL_PWM_CNTL; + unsigned int BL_PWM_CNTL2; + unsigned int BL_PWM_PERIOD_CNTL; + unsigned int LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; +}; + struct panel_cntl_funcs { void (*destroy)(struct panel_cntl **panel_cntl); - void (*hw_init)(struct panel_cntl *panel_cntl); + uint32_t (*hw_init)(struct panel_cntl *panel_cntl); bool (*is_panel_backlight_on)(struct panel_cntl *panel_cntl); bool (*is_panel_powered_on)(struct panel_cntl *panel_cntl); + void (*store_backlight_level)(struct panel_cntl *panel_cntl); + void (*driver_set_backlight)(struct panel_cntl *panel_cntl, + uint32_t backlight_pwm_u16_16); }; struct panel_cntl_init_data { @@ -48,6 +60,8 @@ struct panel_cntl { const struct panel_cntl_funcs *funcs; struct dc_context *ctx; uint32_t inst; + /* registers setting needs to be saved and restored at InitBacklight */ + struct panel_cntl_backlight_registers stored_backlight_registers; }; #endif /* DC_PANEL_CNTL_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 1570fed20de0..3b2ea9bdb62c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -196,6 +196,8 @@ struct hw_sequencer_funcs { uint32_t backlight_pwm_u16_16, uint32_t frame_ramp); + void (*set_abm_immediate_disable)(struct pipe_ctx *pipe_ctx); + }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index ca4c36c0c9bc..109c589eb97c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -138,9 +138,6 @@ struct pipe_ctx *find_idle_secondary_pipe( const struct resource_pool *pool, const struct pipe_ctx *primary_pipe); -bool resource_is_stream_unchanged( - struct dc_state *old_context, struct dc_stream_state *stream); - bool resource_validate_attach_surfaces( const struct dc_validation_set set[], int set_count, diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index c34eba19860a..6d7bca562eec 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -108,7 +108,7 @@ #define ASSERT(expr) ASSERT_CRITICAL(expr) #else -#define ASSERT(expr) WARN_ON(!(expr)) +#define ASSERT(expr) WARN_ON_ONCE(!(expr)) #endif #define BREAK_TO_DEBUGGER() ASSERT(0) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 9f10bfe3d2df..26d94eb5ab58 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -64,10 +64,11 @@ * other component within DAL. */ -#include "dmub_types.h" -#include "dmub_cmd.h" -#include "dmub_gpint_cmd.h" -#include "dmub_rb.h" +#include "inc/dmub_types.h" +#include "inc/dmub_cmd.h" +#include "inc/dmub_gpint_cmd.h" +#include "inc/dmub_cmd_dal.h" +#include "inc/dmub_rb.h" #if defined(__cplusplus) extern "C" { diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index eb10518dc058..599bf2055bcb 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -262,6 +262,7 @@ struct dmub_cmd_abm_set_pipe_data { uint32_t ramping_boundary; uint32_t otg_inst; uint32_t panel_inst; + uint32_t set_pipe_option; }; struct dmub_rb_cmd_abm_set_pipe { diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c index 45638d61b73d..edc73d6d7ba2 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c @@ -23,7 +23,7 @@ * */ -#include "../inc/dmub_srv.h" +#include "../dmub_srv.h" #include "dmub_reg.h" #include "dmub_dcn20.h" diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c index 5bed9fcd6b5c..e8f488232e34 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn21.c @@ -23,7 +23,7 @@ * */ -#include "../inc/dmub_srv.h" +#include "../dmub_srv.h" #include "dmub_reg.h" #include "dmub_dcn21.h" diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c index 4094eca212f0..ca0c8a54b635 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c @@ -24,7 +24,7 @@ */ #include "dmub_reg.h" -#include "../inc/dmub_srv.h" +#include "../dmub_srv.h" struct dmub_reg_value_masks { uint32_t value; diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 66ba0b2d80d2..0e3751d94cb0 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -23,7 +23,7 @@ * */ -#include "../inc/dmub_srv.h" +#include "../dmub_srv.h" #include "dmub_dcn20.h" #include "dmub_dcn21.h" #include "dmub_fw_meta.h" diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index 22a5484d9f28..7cd8a43d1889 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -29,7 +29,6 @@ #include "mod_shared.h" #include "mod_freesync.h" #include "dc.h" -#include "dmub/inc/dmub_cmd_dal.h" enum vsc_packet_revision { vsc_packet_undefined = 0, @@ -145,7 +144,7 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, } /*VSC packet set to 2 when DP revision >= 1.2*/ - if (stream->link->psr_settings.psr_version != PSR_VERSION_UNSUPPORTED) + if (stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED) vsc_packet_revision = vsc_packet_rev2; /* Update to revision 5 for extended colorimetry support */ diff --git a/drivers/gpu/drm/amd/display/modules/stats/stats.c b/drivers/gpu/drm/amd/display/modules/stats/stats.c deleted file mode 100644 index 03121ca64fe4..000000000000 --- a/drivers/gpu/drm/amd/display/modules/stats/stats.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright 2016 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#include "mod_stats.h" -#include "dm_services.h" -#include "dc.h" -#include "core_types.h" - -#define DAL_STATS_ENABLE_REGKEY "DalStatsEnable" -#define DAL_STATS_ENABLE_REGKEY_DEFAULT 0x00000000 -#define DAL_STATS_ENABLE_REGKEY_ENABLED 0x00000001 - -#define DAL_STATS_ENTRIES_REGKEY "DalStatsEntries" -#define DAL_STATS_ENTRIES_REGKEY_DEFAULT 0x00350000 -#define DAL_STATS_ENTRIES_REGKEY_MAX 0x01000000 - -#define DAL_STATS_EVENT_ENTRIES_DEFAULT 0x00000100 - -#define MOD_STATS_NUM_VSYNCS 5 -#define MOD_STATS_EVENT_STRING_MAX 512 - -struct stats_time_cache { - unsigned int entry_id; - - unsigned long flip_timestamp_in_ns; - unsigned long vupdate_timestamp_in_ns; - - unsigned int render_time_in_us; - unsigned int avg_render_time_in_us_last_ten; - unsigned int v_sync_time_in_us[MOD_STATS_NUM_VSYNCS]; - unsigned int num_vsync_between_flips; - - unsigned int flip_to_vsync_time_in_us; - unsigned int vsync_to_flip_time_in_us; - - unsigned int min_window; - unsigned int max_window; - unsigned int v_total_min; - unsigned int v_total_max; - unsigned int event_triggers; - - unsigned int lfc_mid_point_in_us; - unsigned int num_frames_inserted; - unsigned int inserted_duration_in_us; - - unsigned int flags; -}; - -struct stats_event_cache { - unsigned int entry_id; - char event_string[MOD_STATS_EVENT_STRING_MAX]; -}; - -struct core_stats { - struct mod_stats public; - struct dc *dc; - - bool enabled; - unsigned int entries; - unsigned int event_entries; - unsigned int entry_id; - - struct stats_time_cache *time; - unsigned int index; - - struct stats_event_cache *events; - unsigned int event_index; - -}; - -#define MOD_STATS_TO_CORE(mod_stats)\ - container_of(mod_stats, struct core_stats, public) - -bool mod_stats_init(struct mod_stats *mod_stats) -{ - bool result = false; - struct core_stats *core_stats = NULL; - struct dc *dc = NULL; - - if (mod_stats == NULL) - return false; - - core_stats = MOD_STATS_TO_CORE(mod_stats); - dc = core_stats->dc; - - return result; -} - -struct mod_stats *mod_stats_create(struct dc *dc) -{ - struct core_stats *core_stats = NULL; - struct persistent_data_flag flag; - unsigned int reg_data; - int i = 0; - - if (dc == NULL) - goto fail_construct; - - core_stats = kzalloc(sizeof(struct core_stats), GFP_KERNEL); - - if (core_stats == NULL) - goto fail_construct; - - core_stats->dc = dc; - - core_stats->enabled = DAL_STATS_ENABLE_REGKEY_DEFAULT; - if (dm_read_persistent_data(dc->ctx, NULL, NULL, - DAL_STATS_ENABLE_REGKEY, - ®_data, sizeof(unsigned int), &flag)) - core_stats->enabled = reg_data; - - if (core_stats->enabled) { - core_stats->entries = DAL_STATS_ENTRIES_REGKEY_DEFAULT; - if (dm_read_persistent_data(dc->ctx, NULL, NULL, - DAL_STATS_ENTRIES_REGKEY, - ®_data, sizeof(unsigned int), &flag)) { - if (reg_data > DAL_STATS_ENTRIES_REGKEY_MAX) - core_stats->entries = DAL_STATS_ENTRIES_REGKEY_MAX; - else - core_stats->entries = reg_data; - } - core_stats->time = kcalloc(core_stats->entries, - sizeof(struct stats_time_cache), - GFP_KERNEL); - - if (core_stats->time == NULL) - goto fail_construct_time; - - core_stats->event_entries = DAL_STATS_EVENT_ENTRIES_DEFAULT; - core_stats->events = kcalloc(core_stats->event_entries, - sizeof(struct stats_event_cache), - GFP_KERNEL); - - if (core_stats->events == NULL) - goto fail_construct_events; - - } else { - core_stats->entries = 0; - } - - /* Purposely leave index 0 unused so we don't need special logic to - * handle calculation cases that depend on previous flip data. - */ - core_stats->index = 1; - core_stats->event_index = 0; - - // Keeps track of ordering within the different stats structures - core_stats->entry_id = 0; - - return &core_stats->public; - -fail_construct_events: - kfree(core_stats->time); - -fail_construct_time: - kfree(core_stats); - -fail_construct: - return NULL; -} - -void mod_stats_destroy(struct mod_stats *mod_stats) -{ - if (mod_stats != NULL) { - struct core_stats *core_stats = MOD_STATS_TO_CORE(mod_stats); - - kfree(core_stats->time); - kfree(core_stats->events); - kfree(core_stats); - } -} - -void mod_stats_dump(struct mod_stats *mod_stats) -{ - struct dc *dc = NULL; - struct dal_logger *logger = NULL; - struct core_stats *core_stats = NULL; - struct stats_time_cache *time = NULL; - struct stats_event_cache *events = NULL; - unsigned int time_index = 1; - unsigned int event_index = 0; - unsigned int index = 0; - struct log_entry log_entry; - - if (mod_stats == NULL) - return; - - core_stats = MOD_STATS_TO_CORE(mod_stats); - dc = core_stats->dc; - logger = dc->ctx->logger; - time = core_stats->time; - events = core_stats->events; - - DISPLAY_STATS_BEGIN(log_entry); - - DISPLAY_STATS("==Display Caps==\n"); - - DISPLAY_STATS("==Display Stats==\n"); - - DISPLAY_STATS("%10s %10s %10s %10s %10s" - " %11s %11s %17s %10s %14s" - " %10s %10s %10s %10s %10s" - " %10s %10s %10s %10s\n", - "render", "avgRender", - "minWindow", "midPoint", "maxWindow", - "vsyncToFlip", "flipToVsync", "vsyncsBetweenFlip", - "numFrame", "insertDuration", - "vTotalMin", "vTotalMax", "eventTrigs", - "vSyncTime1", "vSyncTime2", "vSyncTime3", - "vSyncTime4", "vSyncTime5", "flags"); - - for (int i = 0; i < core_stats->entry_id; i++) { - if (event_index < core_stats->event_index && - i == events[event_index].entry_id) { - DISPLAY_STATS("==Event==%s\n", events[event_index].event_string); - event_index++; - } else if (time_index < core_stats->index && - i == time[time_index].entry_id) { - DISPLAY_STATS("%10u %10u %10u %10u %10u" - " %11u %11u %17u %10u %14u" - " %10u %10u %10u %10u %10u" - " %10u %10u %10u %10u\n", - time[time_index].render_time_in_us, - time[time_index].avg_render_time_in_us_last_ten, - time[time_index].min_window, - time[time_index].lfc_mid_point_in_us, - time[time_index].max_window, - time[time_index].vsync_to_flip_time_in_us, - time[time_index].flip_to_vsync_time_in_us, - time[time_index].num_vsync_between_flips, - time[time_index].num_frames_inserted, - time[time_index].inserted_duration_in_us, - time[time_index].v_total_min, - time[time_index].v_total_max, - time[time_index].event_triggers, - time[time_index].v_sync_time_in_us[0], - time[time_index].v_sync_time_in_us[1], - time[time_index].v_sync_time_in_us[2], - time[time_index].v_sync_time_in_us[3], - time[time_index].v_sync_time_in_us[4], - time[time_index].flags); - - time_index++; - } - } - - DISPLAY_STATS_END(log_entry); -} - -void mod_stats_reset_data(struct mod_stats *mod_stats) -{ - struct core_stats *core_stats = NULL; - struct stats_time_cache *time = NULL; - unsigned int index = 0; - - if (mod_stats == NULL) - return; - - core_stats = MOD_STATS_TO_CORE(mod_stats); - - memset(core_stats->time, 0, - sizeof(struct stats_time_cache) * core_stats->entries); - - memset(core_stats->events, 0, - sizeof(struct stats_event_cache) * core_stats->event_entries); - - core_stats->index = 1; - core_stats->event_index = 0; - - // Keeps track of ordering within the different stats structures - core_stats->entry_id = 0; -} - -void mod_stats_update_event(struct mod_stats *mod_stats, - char *event_string, - unsigned int length) -{ - struct core_stats *core_stats = NULL; - struct stats_event_cache *events = NULL; - unsigned int index = 0; - unsigned int copy_length = 0; - - if (mod_stats == NULL) - return; - - core_stats = MOD_STATS_TO_CORE(mod_stats); - - if (core_stats->event_index >= core_stats->event_entries) - return; - - events = core_stats->events; - index = core_stats->event_index; - - copy_length = length; - if (length > MOD_STATS_EVENT_STRING_MAX) - copy_length = MOD_STATS_EVENT_STRING_MAX; - - memcpy(&events[index].event_string, event_string, copy_length); - events[index].event_string[copy_length - 1] = '\0'; - - events[index].entry_id = core_stats->entry_id; - core_stats->event_index++; - core_stats->entry_id++; -} - -void mod_stats_update_flip(struct mod_stats *mod_stats, - unsigned long timestamp_in_ns) -{ - struct core_stats *core_stats = NULL; - struct stats_time_cache *time = NULL; - unsigned int index = 0; - - if (mod_stats == NULL) - return; - - core_stats = MOD_STATS_TO_CORE(mod_stats); - - if (core_stats->index >= core_stats->entries) - return; - - time = core_stats->time; - index = core_stats->index; - - time[index].flip_timestamp_in_ns = timestamp_in_ns; - time[index].render_time_in_us = - (timestamp_in_ns - time[index - 1].flip_timestamp_in_ns) / 1000; - - if (index >= 10) { - for (unsigned int i = 0; i < 10; i++) - time[index].avg_render_time_in_us_last_ten += - time[index - i].render_time_in_us; - time[index].avg_render_time_in_us_last_ten /= 10; - } - - if (time[index].num_vsync_between_flips > 0) - time[index].vsync_to_flip_time_in_us = - (timestamp_in_ns - - time[index].vupdate_timestamp_in_ns) / 1000; - else - time[index].vsync_to_flip_time_in_us = - (timestamp_in_ns - - time[index - 1].vupdate_timestamp_in_ns) / 1000; - - time[index].entry_id = core_stats->entry_id; - core_stats->index++; - core_stats->entry_id++; -} - -void mod_stats_update_vupdate(struct mod_stats *mod_stats, - unsigned long timestamp_in_ns) -{ - struct core_stats *core_stats = NULL; - struct stats_time_cache *time = NULL; - unsigned int index = 0; - unsigned int num_vsyncs = 0; - unsigned int prev_vsync_in_ns = 0; - - if (mod_stats == NULL) - return; - - core_stats = MOD_STATS_TO_CORE(mod_stats); - - if (core_stats->index >= core_stats->entries) - return; - - time = core_stats->time; - index = core_stats->index; - num_vsyncs = time[index].num_vsync_between_flips; - - if (num_vsyncs < MOD_STATS_NUM_VSYNCS) { - if (num_vsyncs == 0) { - prev_vsync_in_ns = - time[index - 1].vupdate_timestamp_in_ns; - - time[index].flip_to_vsync_time_in_us = - (timestamp_in_ns - - time[index - 1].flip_timestamp_in_ns) / - 1000; - } else { - prev_vsync_in_ns = - time[index].vupdate_timestamp_in_ns; - } - - time[index].v_sync_time_in_us[num_vsyncs] = - (timestamp_in_ns - prev_vsync_in_ns) / 1000; - } - - time[index].vupdate_timestamp_in_ns = timestamp_in_ns; - time[index].num_vsync_between_flips++; -} - -void mod_stats_update_freesync(struct mod_stats *mod_stats, - unsigned int v_total_min, - unsigned int v_total_max, - unsigned int event_triggers, - unsigned int window_min, - unsigned int window_max, - unsigned int lfc_mid_point_in_us, - unsigned int inserted_frames, - unsigned int inserted_duration_in_us) -{ - struct core_stats *core_stats = NULL; - struct stats_time_cache *time = NULL; - unsigned int index = 0; - - if (mod_stats == NULL) - return; - - core_stats = MOD_STATS_TO_CORE(mod_stats); - - if (core_stats->index >= core_stats->entries) - return; - - time = core_stats->time; - index = core_stats->index; - - time[index].v_total_min = v_total_min; - time[index].v_total_max = v_total_max; - time[index].event_triggers = event_triggers; - time[index].min_window = window_min; - time[index].max_window = window_max; - time[index].lfc_mid_point_in_us = lfc_mid_point_in_us; - time[index].num_frames_inserted = inserted_frames; - time[index].inserted_duration_in_us = inserted_duration_in_us; -} - |