aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.19.8/0165-drm-amd-display-implement-DPMS-DTN-test-v2.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/0165-drm-amd-display-implement-DPMS-DTN-test-v2.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.19.8/0165-drm-amd-display-implement-DPMS-DTN-test-v2.patch607
1 files changed, 607 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/0165-drm-amd-display-implement-DPMS-DTN-test-v2.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/0165-drm-amd-display-implement-DPMS-DTN-test-v2.patch
new file mode 100644
index 00000000..bfa30ac9
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/0165-drm-amd-display-implement-DPMS-DTN-test-v2.patch
@@ -0,0 +1,607 @@
+From 09511ec40bf0428d9a39135a093b2f2820a03e07 Mon Sep 17 00:00:00 2001
+From: Jun Lei <Jun.Lei@amd.com>
+Date: Wed, 8 Aug 2018 11:53:39 -0400
+Subject: [PATCH 0165/2940] drm/amd/display: implement DPMS DTN test v2
+
+[why]
+Existing DTN infrastructure in driver is hacky. It uses implicit log
+names, and also incorrect escape ID.
+
+[how]
+- Implement using generic DTN escape ID.
+- Move file logging functionality from driver to to script; driver now outputs to string/buffer
+- Move HWSS debug functionality to separate c file
+- Add debug functionalty for per-block logging as CSV
+- Add pretty print in python
+
+Signed-off-by: Jun Lei <Jun.Lei@amd.com>
+Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
+Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +-
+ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +-
+ .../amd/display/dc/dcn10/dcn10_hw_sequencer.h | 5 +
+ .../dc/dcn10/dcn10_hw_sequencer_debug.c | 510 ++++++++++++++++++
+ .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 1 +
+ 5 files changed, 518 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile
+index 84f52c63d95c..032f872be89c 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile
+@@ -22,7 +22,7 @@
+ #
+ # Makefile for DCN.
+
+-DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \
++DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o dcn10_hw_sequencer_debug.o \
+ dcn10_dpp.o dcn10_opp.o dcn10_optc.o \
+ dcn10_hubp.o dcn10_mpc.o \
+ dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o \
+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 4b8bedb625b4..051f427868ca 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
+@@ -71,7 +71,6 @@ void print_microsec(struct dc_context *dc_ctx, uint32_t ref_cycle)
+ us_x10 % frac);
+ }
+
+-
+ static void log_mpc_crc(struct dc *dc)
+ {
+ struct dc_context *dc_ctx = dc->ctx;
+@@ -2712,6 +2711,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
+ .setup_stereo = dcn10_setup_stereo,
+ .set_avmute = dce110_set_avmute,
+ .log_hw_state = dcn10_log_hw_state,
++ .get_hw_state = dcn10_get_hw_state,
+ .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
+ .ready_shared_resources = ready_shared_resources,
+ .optimize_shared_resources = optimize_shared_resources,
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
+index 7139fb73e966..84d461e0ed3e 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
+@@ -46,4 +46,9 @@ void dcn10_program_pipe(
+ struct pipe_ctx *pipe_ctx,
+ struct dc_state *context);
+
++void dcn10_get_hw_state(
++ struct dc *dc,
++ char *pBuf, unsigned int bufSize,
++ unsigned int mask);
++
+ #endif /* __DC_HWSS_DCN10_H__ */
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
+new file mode 100644
+index 000000000000..9288b00e49b4
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
+@@ -0,0 +1,510 @@
++/*
++ * 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 "dm_services.h"
++#include "core_types.h"
++#include "resource.h"
++#include "custom_float.h"
++#include "dcn10_hw_sequencer.h"
++#include "dce110/dce110_hw_sequencer.h"
++#include "dce/dce_hwseq.h"
++#include "abm.h"
++#include "dmcu.h"
++#include "dcn10_optc.h"
++#include "dcn10/dcn10_dpp.h"
++#include "dcn10/dcn10_mpc.h"
++#include "timing_generator.h"
++#include "opp.h"
++#include "ipp.h"
++#include "mpc.h"
++#include "reg_helper.h"
++#include "custom_float.h"
++#include "dcn10_hubp.h"
++#include "dcn10_hubbub.h"
++#include "dcn10_cm_common.h"
++
++static unsigned int snprintf_count(char *pBuf, unsigned int bufSize, char *fmt, ...)
++{
++ unsigned int ret_vsnprintf;
++ unsigned int chars_printed;
++
++ va_list args;
++ va_start(args, fmt);
++
++ ret_vsnprintf = vsnprintf(pBuf, bufSize, fmt, args);
++
++ va_end(args);
++
++ if (ret_vsnprintf > 0) {
++ if (ret_vsnprintf < bufSize)
++ chars_printed = ret_vsnprintf;
++ else
++ chars_printed = bufSize - 1;
++ } else
++ chars_printed = 0;
++
++ return chars_printed;
++}
++
++static unsigned int dcn10_get_hubbub_state(struct dc *dc, char *pBuf, unsigned int bufSize)
++{
++ struct dc_context *dc_ctx = dc->ctx;
++ struct dcn_hubbub_wm wm = {0};
++ int i;
++
++ unsigned int chars_printed = 0;
++ unsigned int remaining_buffer = bufSize;
++
++ const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clock_inKhz / 1000;
++ static const unsigned int frac = 1000;
++
++ hubbub1_wm_read_state(dc->res_pool->hubbub, &wm);
++
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "wm_set_index,data_urgent,pte_meta_urgent,sr_enter,sr_exit,dram_clk_chanage\n");
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++
++ for (i = 0; i < 4; i++) {
++ struct dcn_hubbub_wm_set *s;
++
++ s = &wm.sets[i];
++
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%d.%03d,%d.%03d,%d.%03d,%d.%03d,%d.%03d\n",
++ s->wm_set,
++ (s->data_urgent * frac) / ref_clk_mhz / frac, (s->data_urgent * frac) / ref_clk_mhz % frac,
++ (s->pte_meta_urgent * frac) / ref_clk_mhz / frac, (s->pte_meta_urgent * frac) / ref_clk_mhz % frac,
++ (s->sr_enter * frac) / ref_clk_mhz / frac, (s->sr_enter * frac) / ref_clk_mhz % frac,
++ (s->sr_exit * frac) / ref_clk_mhz / frac, (s->sr_exit * frac) / ref_clk_mhz % frac,
++ (s->dram_clk_chanage * frac) / ref_clk_mhz / frac, (s->dram_clk_chanage * frac) / ref_clk_mhz % frac);
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++ }
++
++ return bufSize - remaining_buffer;
++}
++
++static unsigned int dcn10_get_hubp_states(struct dc *dc, char *pBuf, unsigned int bufSize)
++{
++ struct dc_context *dc_ctx = dc->ctx;
++ struct resource_pool *pool = dc->res_pool;
++ int i;
++
++ unsigned int chars_printed = 0;
++ unsigned int remaining_buffer = bufSize;
++
++ const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clock_inKhz / 1000;
++ static const unsigned int frac = 1000;
++
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,format,addr_hi,width,height,rotation,mirror,sw_mode,dcc_en,blank_en,ttu_dis,underflow,"
++ "min_ttu_vblank,qos_low_wm,qos_high_wm"
++ "\n");
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++
++ for (i = 0; i < pool->pipe_count; i++) {
++ struct hubp *hubp = pool->hubps[i];
++ struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
++
++ hubp->funcs->hubp_read_state(hubp);
++
++ if (!s->blank_en) {
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%d,%d,%x,%x,%x,%x,%x,%x,%x,"
++ "%d.%03d,%d.%03d,%d.%03d"
++ "\n",
++ hubp->inst,
++ s->pixel_format,
++ s->inuse_addr_hi,
++ s->viewport_width,
++ s->viewport_height,
++ s->rotation_angle,
++ s->h_mirror_en,
++ s->sw_mode,
++ s->dcc_en,
++ s->blank_en,
++ s->ttu_disable,
++ s->underflow_status,
++ (s->min_ttu_vblank * frac) / ref_clk_mhz / frac, (s->min_ttu_vblank * frac) / ref_clk_mhz % frac,
++ (s->qos_level_low_wm * frac) / ref_clk_mhz / frac, (s->qos_level_low_wm * frac) / ref_clk_mhz % frac,
++ (s->qos_level_high_wm * frac) / ref_clk_mhz / frac, (s->qos_level_high_wm * frac) / ref_clk_mhz % frac);
++
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++ }
++ }
++
++ return bufSize - remaining_buffer;
++}
++
++static unsigned int dcn10_get_rq_states(struct dc *dc, char *pBuf, unsigned int bufSize)
++{
++ struct resource_pool *pool = dc->res_pool;
++ int i;
++
++ unsigned int chars_printed = 0;
++ unsigned int remaining_buffer = bufSize;
++
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,drq_exp_m,prq_exp_m,mrq_exp_m,crq_exp_m,plane1_ba,"
++ "luma_chunk_s,luma_min_chu_s,luma_meta_ch_s,luma_min_m_c_s,luma_dpte_gr_s,luma_mpte_gr_s,luma_swath_hei,luma_pte_row_h,"
++ "chroma_chunk_s,chroma_min_chu_s,chroma_meta_ch_s,chroma_min_m_c_s,chroma_dpte_gr_s,chroma_mpte_gr_s,chroma_swath_hei,chroma_pte_row_h"
++ "\n");
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++
++ for (i = 0; i < pool->pipe_count; i++) {
++ struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
++ struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs;
++
++ if (!s->blank_en) {
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%x,%x,%x,"
++ "%x,%x,%x,%x,%x,%x,%x,%x,"
++ "%x,%x,%x,%x,%x,%x,%x,%x"
++ "\n",
++ pool->hubps[i]->inst, rq_regs->drq_expansion_mode, rq_regs->prq_expansion_mode, rq_regs->mrq_expansion_mode,
++ rq_regs->crq_expansion_mode, rq_regs->plane1_base_address, rq_regs->rq_regs_l.chunk_size,
++ rq_regs->rq_regs_l.min_chunk_size, rq_regs->rq_regs_l.meta_chunk_size,
++ rq_regs->rq_regs_l.min_meta_chunk_size, rq_regs->rq_regs_l.dpte_group_size,
++ rq_regs->rq_regs_l.mpte_group_size, rq_regs->rq_regs_l.swath_height,
++ rq_regs->rq_regs_l.pte_row_height_linear, rq_regs->rq_regs_c.chunk_size, rq_regs->rq_regs_c.min_chunk_size,
++ rq_regs->rq_regs_c.meta_chunk_size, rq_regs->rq_regs_c.min_meta_chunk_size,
++ rq_regs->rq_regs_c.dpte_group_size, rq_regs->rq_regs_c.mpte_group_size,
++ rq_regs->rq_regs_c.swath_height, rq_regs->rq_regs_c.pte_row_height_linear);
++
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++ }
++ }
++
++ return bufSize - remaining_buffer;
++}
++
++static unsigned int dcn10_get_dlg_states(struct dc *dc, char *pBuf, unsigned int bufSize)
++{
++ struct resource_pool *pool = dc->res_pool;
++ int i;
++
++ unsigned int chars_printed = 0;
++ unsigned int remaining_buffer = bufSize;
++
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,rc_hbe,dlg_vbe,min_d_y_n,rc_per_ht,rc_x_a_s,"
++ "dst_y_a_s,dst_y_pf,dst_y_vvb,dst_y_rvb,dst_y_vfl,dst_y_rfl,rf_pix_fq,"
++ "vratio_pf,vrat_pf_c,rc_pg_vbl,rc_pg_vbc,rc_mc_vbl,rc_mc_vbc,rc_pg_fll,"
++ "rc_pg_flc,rc_mc_fll,rc_mc_flc,pr_nom_l,pr_nom_c,rc_pg_nl,rc_pg_nc,"
++ "mr_nom_l,mr_nom_c,rc_mc_nl,rc_mc_nc,rc_ld_pl,rc_ld_pc,rc_ld_l,"
++ "rc_ld_c,cha_cur0,ofst_cur1,cha_cur1,vr_af_vc0,ddrq_limt,x_rt_dlay,x_rp_dlay,x_rr_sfl"
++ "\n");
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++
++ for (i = 0; i < pool->pipe_count; i++) {
++ struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
++ struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &s->dlg_attr;
++
++ if (!s->blank_en) {
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%x,%x,"
++ "%x,%x,%x,%x,%x,%x,%x,"
++ "%x,%x,%x,%x,%x,%x,%x,"
++ "%x,%x,%x,%x,%x,%x,%x,"
++ "%x,%x,%x,%x,%x,%x,%x,"
++ "%x,%x,%x,%x,%x,%x,%x,%x,%x,%x"
++ "\n",
++ pool->hubps[i]->inst, dlg_regs->refcyc_h_blank_end, dlg_regs->dlg_vblank_end, dlg_regs->min_dst_y_next_start,
++ dlg_regs->refcyc_per_htotal, dlg_regs->refcyc_x_after_scaler, dlg_regs->dst_y_after_scaler,
++ dlg_regs->dst_y_prefetch, dlg_regs->dst_y_per_vm_vblank, dlg_regs->dst_y_per_row_vblank,
++ dlg_regs->dst_y_per_vm_flip, dlg_regs->dst_y_per_row_flip, dlg_regs->ref_freq_to_pix_freq,
++ dlg_regs->vratio_prefetch, dlg_regs->vratio_prefetch_c, dlg_regs->refcyc_per_pte_group_vblank_l,
++ dlg_regs->refcyc_per_pte_group_vblank_c, dlg_regs->refcyc_per_meta_chunk_vblank_l,
++ dlg_regs->refcyc_per_meta_chunk_vblank_c, dlg_regs->refcyc_per_pte_group_flip_l,
++ dlg_regs->refcyc_per_pte_group_flip_c, dlg_regs->refcyc_per_meta_chunk_flip_l,
++ dlg_regs->refcyc_per_meta_chunk_flip_c, dlg_regs->dst_y_per_pte_row_nom_l,
++ dlg_regs->dst_y_per_pte_row_nom_c, dlg_regs->refcyc_per_pte_group_nom_l,
++ dlg_regs->refcyc_per_pte_group_nom_c, dlg_regs->dst_y_per_meta_row_nom_l,
++ dlg_regs->dst_y_per_meta_row_nom_c, dlg_regs->refcyc_per_meta_chunk_nom_l,
++ dlg_regs->refcyc_per_meta_chunk_nom_c, dlg_regs->refcyc_per_line_delivery_pre_l,
++ dlg_regs->refcyc_per_line_delivery_pre_c, dlg_regs->refcyc_per_line_delivery_l,
++ dlg_regs->refcyc_per_line_delivery_c, dlg_regs->chunk_hdl_adjust_cur0, dlg_regs->dst_y_offset_cur1,
++ dlg_regs->chunk_hdl_adjust_cur1, dlg_regs->vready_after_vcount0, dlg_regs->dst_y_delta_drq_limit,
++ dlg_regs->xfc_reg_transfer_delay, dlg_regs->xfc_reg_precharge_delay,
++ dlg_regs->xfc_reg_remote_surface_flip_latency);
++
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++ }
++ }
++
++ return bufSize - remaining_buffer;
++}
++
++static unsigned int dcn10_get_ttu_states(struct dc *dc, char *pBuf, unsigned int bufSize)
++{
++ struct resource_pool *pool = dc->res_pool;
++ int i;
++
++ unsigned int chars_printed = 0;
++ unsigned int remaining_buffer = bufSize;
++
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,qos_ll_wm,qos_lh_wm,mn_ttu_vb,qos_l_flp,rc_rd_p_l,rc_rd_l,rc_rd_p_c,"
++ "rc_rd_c,rc_rd_c0,rc_rd_pc0,rc_rd_c1,rc_rd_pc1,qos_lf_l,qos_rds_l,"
++ "qos_lf_c,qos_rds_c,qos_lf_c0,qos_rds_c0,qos_lf_c1,qos_rds_c1"
++ "\n");
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++
++ for (i = 0; i < pool->pipe_count; i++) {
++ struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
++ struct _vcs_dpi_display_ttu_regs_st *ttu_regs = &s->ttu_attr;
++
++ if (!s->blank_en) {
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%x,%x,%x,%x,%x,"
++ "%x,%x,%x,%x,%x,%x,%x,"
++ "%x,%x,%x,%x,%x,%x"
++ "\n",
++ pool->hubps[i]->inst, ttu_regs->qos_level_low_wm, ttu_regs->qos_level_high_wm, ttu_regs->min_ttu_vblank,
++ ttu_regs->qos_level_flip, ttu_regs->refcyc_per_req_delivery_pre_l, ttu_regs->refcyc_per_req_delivery_l,
++ ttu_regs->refcyc_per_req_delivery_pre_c, ttu_regs->refcyc_per_req_delivery_c, ttu_regs->refcyc_per_req_delivery_cur0,
++ ttu_regs->refcyc_per_req_delivery_pre_cur0, ttu_regs->refcyc_per_req_delivery_cur1,
++ ttu_regs->refcyc_per_req_delivery_pre_cur1, ttu_regs->qos_level_fixed_l, ttu_regs->qos_ramp_disable_l,
++ ttu_regs->qos_level_fixed_c, ttu_regs->qos_ramp_disable_c, ttu_regs->qos_level_fixed_cur0,
++ ttu_regs->qos_ramp_disable_cur0, ttu_regs->qos_level_fixed_cur1, ttu_regs->qos_ramp_disable_cur1);
++
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++ }
++ }
++
++ return bufSize - remaining_buffer;
++}
++
++static unsigned int dcn10_get_cm_states(struct dc *dc, char *pBuf, unsigned int bufSize)
++{
++ struct resource_pool *pool = dc->res_pool;
++ int i;
++
++ unsigned int chars_printed = 0;
++ unsigned int remaining_buffer = bufSize;
++
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,igam_format,igam_mode,dgam_mode,rgam_mode,gamut_mode,"
++ "c11_c12,c13_c14,c21_c22,c23_c24,c31_c32,c33_c34"
++ "\n");
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++
++ for (i = 0; i < pool->pipe_count; i++) {
++ struct dpp *dpp = pool->dpps[i];
++ struct dcn_dpp_state s = {0};
++
++ dpp->funcs->dpp_read_state(dpp, &s);
++
++ if (s.is_enabled) {
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%x,%x,%x,"
++ "%08x,%08x,%08x,%08x,%08x,%08x"
++ "\n",
++ dpp->inst, s.igam_input_format, s.igam_lut_mode, s.dgam_lut_mode,
++ s.rgam_lut_mode, s.gamut_remap_mode, s.gamut_remap_c11_c12,
++ s.gamut_remap_c13_c14, s.gamut_remap_c21_c22, s.gamut_remap_c23_c24,
++ s.gamut_remap_c31_c32, s.gamut_remap_c33_c34);
++
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++ }
++ }
++
++ return bufSize - remaining_buffer;
++}
++
++static unsigned int dcn10_get_mpcc_states(struct dc *dc, char *pBuf, unsigned int bufSize)
++{
++ struct resource_pool *pool = dc->res_pool;
++ int i;
++
++ unsigned int chars_printed = 0;
++ unsigned int remaining_buffer = bufSize;
++
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,opp,dpp,mpccbot,mode,alpha_mode,premult,overlap_only,idle\n");
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++
++ for (i = 0; i < pool->pipe_count; i++) {
++ struct mpcc_state s = {0};
++
++ pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s);
++
++ if (s.opp_id != 0xf) {
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%x,%x,%x,%x,%x,%x,%x,%x\n",
++ i, s.opp_id, s.dpp_id, s.bot_mpcc_id,
++ s.mode, s.alpha_mode, s.pre_multiplied_alpha, s.overlap_only,
++ s.idle);
++
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++ }
++ }
++
++ return bufSize - remaining_buffer;
++}
++
++static unsigned int dcn10_get_otg_states(struct dc *dc, char *pBuf, unsigned int bufSize)
++{
++ struct resource_pool *pool = dc->res_pool;
++ int i;
++
++ unsigned int chars_printed = 0;
++ unsigned int remaining_buffer = bufSize;
++
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "instance,v_bs,v_be,v_ss,v_se,vpol,vmax,vmin,vmax_sel,vmin_sel,"
++ "h_bs,h_be,h_ss,h_se,hpol,htot,vtot,underflow\n");
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++
++ for (i = 0; i < pool->timing_generator_count; i++) {
++ struct timing_generator *tg = pool->timing_generators[i];
++ struct dcn_otg_state s = {0};
++
++ optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
++
++ //only print if OTG master is enabled
++ if (s.otg_enabled & 1) {
++ chars_printed = snprintf_count(pBuf, remaining_buffer, "%x,%d,%d,%d,%d,%d,%d,%d,%d,%d,"
++ "%d,%d,%d,%d,%d,%d,%d,%d"
++ "\n",
++ tg->inst,
++ s.v_blank_start,
++ s.v_blank_end,
++ s.v_sync_a_start,
++ s.v_sync_a_end,
++ s.v_sync_a_pol,
++ s.v_total_max,
++ s.v_total_min,
++ s.v_total_max_sel,
++ s.v_total_min_sel,
++ s.h_blank_start,
++ s.h_blank_end,
++ s.h_sync_a_start,
++ s.h_sync_a_end,
++ s.h_sync_a_pol,
++ s.h_total,
++ s.v_total,
++ s.underflow_occurred_status);
++
++ remaining_buffer -= chars_printed;
++ pBuf += chars_printed;
++
++ // Clear underflow for debug purposes
++ // We want to keep underflow sticky bit on for the longevity tests outside of test environment.
++ // This function is called only from Windows or Diags test environment, hence it's safe to clear
++ // it from here without affecting the original intent.
++ tg->funcs->clear_optc_underflow(tg);
++ }
++ }
++
++ return bufSize - remaining_buffer;
++}
++
++static unsigned int dcn10_get_clock_states(struct dc *dc, char *pBuf, unsigned int bufSize)
++{
++ unsigned int chars_printed = 0;
++
++ chars_printed = snprintf_count(pBuf, bufSize, "dcfclk_khz,dcfclk_deep_sleep_khz,dispclk_khz,"
++ "dppclk_khz,max_supported_dppclk_khz,fclk_khz,socclk_khz\n"
++ "%d,%d,%d,%d,%d,%d,%d\n",
++ dc->current_state->bw.dcn.clk.dcfclk_khz,
++ dc->current_state->bw.dcn.clk.dcfclk_deep_sleep_khz,
++ dc->current_state->bw.dcn.clk.dispclk_khz,
++ dc->current_state->bw.dcn.clk.dppclk_khz,
++ dc->current_state->bw.dcn.clk.max_supported_dppclk_khz,
++ dc->current_state->bw.dcn.clk.fclk_khz,
++ dc->current_state->bw.dcn.clk.socclk_khz);
++
++ return chars_printed;
++}
++
++void dcn10_get_hw_state(struct dc *dc, char *pBuf, unsigned int bufSize, unsigned int mask)
++{
++ const unsigned int DC_HW_STATE_MASK_HUBBUB = 0x1;
++ const unsigned int DC_HW_STATE_MASK_HUBP = 0x2;
++ const unsigned int DC_HW_STATE_MASK_RQ = 0x4;
++ const unsigned int DC_HW_STATE_MASK_DLG = 0x8;
++ const unsigned int DC_HW_STATE_MASK_TTU = 0x10;
++ const unsigned int DC_HW_STATE_MASK_CM = 0x20;
++ const unsigned int DC_HW_STATE_MASK_MPCC = 0x40;
++ const unsigned int DC_HW_STATE_MASK_OTG = 0x80;
++ const unsigned int DC_HW_STATE_MASK_CLOCKS = 0x100;
++
++ unsigned int chars_printed = 0;
++ unsigned int remaining_buf_size = bufSize;
++
++ if (mask == 0x0)
++ mask = 0xFFFF;
++
++ if ((mask & DC_HW_STATE_MASK_HUBBUB) && remaining_buf_size > 0) {
++ chars_printed = dcn10_get_hubbub_state(dc, pBuf, remaining_buf_size);
++ pBuf += chars_printed;
++ remaining_buf_size -= chars_printed;
++ }
++
++ if ((mask & DC_HW_STATE_MASK_HUBP) && remaining_buf_size > 0) {
++ chars_printed = dcn10_get_hubp_states(dc, pBuf, remaining_buf_size);
++ pBuf += chars_printed;
++ remaining_buf_size -= chars_printed;
++ }
++
++ if ((mask & DC_HW_STATE_MASK_RQ) && remaining_buf_size > 0) {
++ chars_printed = dcn10_get_rq_states(dc, pBuf, remaining_buf_size);
++ pBuf += chars_printed;
++ remaining_buf_size -= chars_printed;
++ }
++
++ if ((mask & DC_HW_STATE_MASK_DLG) && remaining_buf_size > 0) {
++ chars_printed = dcn10_get_dlg_states(dc, pBuf, remaining_buf_size);
++ pBuf += chars_printed;
++ remaining_buf_size -= chars_printed;
++ }
++
++ if ((mask & DC_HW_STATE_MASK_TTU) && remaining_buf_size > 0) {
++ chars_printed = dcn10_get_ttu_states(dc, pBuf, remaining_buf_size);
++ pBuf += chars_printed;
++ remaining_buf_size -= chars_printed;
++ }
++
++ if ((mask & DC_HW_STATE_MASK_CM) && remaining_buf_size > 0) {
++ chars_printed = dcn10_get_cm_states(dc, pBuf, remaining_buf_size);
++ pBuf += chars_printed;
++ remaining_buf_size -= chars_printed;
++ }
++
++ if ((mask & DC_HW_STATE_MASK_MPCC) && remaining_buf_size > 0) {
++ chars_printed = dcn10_get_mpcc_states(dc, pBuf, remaining_buf_size);
++ pBuf += chars_printed;
++ remaining_buf_size -= chars_printed;
++ }
++
++ if ((mask & DC_HW_STATE_MASK_OTG) && remaining_buf_size > 0) {
++ chars_printed = dcn10_get_otg_states(dc, pBuf, remaining_buf_size);
++ pBuf += chars_printed;
++ remaining_buf_size -= chars_printed;
++ }
++
++ if ((mask & DC_HW_STATE_MASK_CLOCKS) && remaining_buf_size > 0)
++ chars_printed = dcn10_get_clock_states(dc, pBuf, remaining_buf_size);
++}
+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 a14ce4de80b2..9a97356923e2 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+@@ -203,6 +203,7 @@ struct hw_sequencer_funcs {
+ void (*set_avmute)(struct pipe_ctx *pipe_ctx, bool enable);
+
+ void (*log_hw_state)(struct dc *dc);
++ void (*get_hw_state)(struct dc *dc, char *pBuf, unsigned int bufSize, unsigned int mask);
+
+ void (*wait_for_mpcc_disconnect)(struct dc *dc,
+ struct resource_pool *res_pool,
+--
+2.17.1
+