<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<p style="font-family:Arial;font-size:11pt;color:#0078D7;margin:5pt;" align="Left">
[AMD Official Use Only - Internal Distribution Only]<br>
</p>
<br>
<div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="font-size: 11pt;">Hi </span><span style="font-size: 11pt;">Nils,</span><span style="font-size: 11pt;">​</span></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
   <span style="font-size: 11pt;">​Thanks for the inputs. <br>
</span></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="font-size: 11pt;"><br>
</span></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="font-size: 11pt;"><a id="OWAAM727992" class="_1OtrSZdhKXVv3UhaivrdJ4 mention ms-bgc-nlr ms-fcl-b" href="mailto:Vladimir.Stempen@amd.com">@ Stempen, Vladimir</a>,</span></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="font-size: 11pt;">      <font size="2"><span style="font-size: 11pt;">​ As the a</span><span style="font-size: 11pt;">rray</span><span style="font-size: 11pt;">
</span><font size="2"><span style="font-size:11pt">'prime_numbers</span></font><span style="font-size: 11pt;">' has constant values defined, we can mark this as static const. Would you like to change the count calculation -or- retain
</span><span style="font-size:11pt"></span></font></span><span style="font-size: 11pt;"></span>the same limit iteration ?
<span style="font-size: 11pt;">All the patches would be merged to upstream by today. please suggest.
</span><br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="font-size: 11pt;">Thanks,</span></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<span style="font-size: 11pt;">Bindu </span><br>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Nils Wallménius <nils.wallmenius@gmail.com><br>
<b>Sent:</b> Sunday, February 21, 2021 1:21 AM<br>
<b>To:</b> R, Bindu <Bindu.R@amd.com><br>
<b>Cc:</b> amd-gfx@lists.freedesktop.org <amd-gfx@lists.freedesktop.org>; Stempen, Vladimir <Vladimir.Stempen@amd.com>; Brol, Eryk <Eryk.Brol@amd.com>; Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Wentland, Harry <Harry.Wentland@amd.com>; Zhuo, Qingqing <Qingqing.Zhuo@amd.com>;
 Siqueira, Rodrigo <Rodrigo.Siqueira@amd.com>; Jacob, Anson <Anson.Jacob@amd.com>; Pillai, Aurabindo <Aurabindo.Pillai@amd.com>; Lakha, Bhawanpreet <Bhawanpreet.Lakha@amd.com><br>
<b>Subject:</b> Re: [PATCH 08/13] drm/amd/display: Synchronize displays with different timings</font>
<div> </div>
</div>
<div>
<div dir="auto">
<div>Hi Bindu, an inline comment below.<br>
<br>
<div class="x_gmail_quote">
<div dir="ltr" class="x_gmail_attr">Den fre 19 feb. 2021 23:16Bindu Ramamurthy <<a href="mailto:bindu.r@amd.com">bindu.r@amd.com</a>> skrev:<br>
</div>
<blockquote class="x_gmail_quote" style="margin:0 0 0 .8ex; border-left:1px #ccc solid; padding-left:1ex">
From: Vladimir Stempen <<a href="mailto:vladimir.stempen@amd.com" target="_blank" rel="noreferrer">vladimir.stempen@amd.com</a>><br>
<br>
[why]<br>
 Vendor based fan noise improvement<br>
<br>
[how]<br>
Report timing synchronizable when DP streams time frame<br>
difference is less than 0.05 percent. Adjust DP  DTOs and<br>
sync displays using  MASTER_UPDATE_LOCK_DB_X_Y<br>
<br>
Signed-off-by: Vladimir Stempen <<a href="mailto:vladimir.stempen@amd.com" target="_blank" rel="noreferrer">vladimir.stempen@amd.com</a>><br>
Acked-by: Bindu Ramamurthy <<a href="mailto:bindu.r@amd.com" target="_blank" rel="noreferrer">bindu.r@amd.com</a>><br>
---<br>
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  28 ++-<br>
 .../gpu/drm/amd/display/dc/core/dc_resource.c |  43 ++++<br>
 drivers/gpu/drm/amd/display/dc/dc.h           |   3 +<br>
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |   1 +<br>
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |   3 +<br>
 .../drm/amd/display/dc/dce/dce_clock_source.c |  52 +++-<br>
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 225 ++++++++++++++++++<br>
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.h |   5 +<br>
 .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h |   2 +<br>
 .../display/dc/dcn10/dcn10_stream_encoder.c   |   1 -<br>
 .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c |   1 +<br>
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 123 ++++++++++<br>
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   8 +-<br>
 .../dc/dcn30/dcn30_dio_stream_encoder.c       |   1 -<br>
 .../gpu/drm/amd/display/dc/inc/clock_source.h |   5 +<br>
 .../amd/display/dc/inc/hw/timing_generator.h  |  12 +<br>
 .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |   3 +<br>
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   4 +<br>
 18 files changed, 505 insertions(+), 15 deletions(-)<br>
<br>
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c<br>
index 2f56fa2c0bf4..39df5d2c0108 100644<br>
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c<br>
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c<br>
@@ -1102,6 +1102,7 @@ static void program_timing_sync(<br>
<br>
        for (i = 0; i < pipe_count; i++) {<br>
                int group_size = 1;<br>
+               enum timing_synchronization_type sync_type = NOT_SYNCHRONIZABLE;<br>
                struct pipe_ctx *pipe_set[MAX_PIPES];<br>
<br>
                if (!unsynced_pipes[i])<br>
@@ -1116,10 +1117,22 @@ static void program_timing_sync(<br>
                for (j = i + 1; j < pipe_count; j++) {<br>
                        if (!unsynced_pipes[j])<br>
                                continue;<br>
-<br>
-                       if (resource_are_streams_timing_synchronizable(<br>
+                       if (sync_type != TIMING_SYNCHRONIZABLE &&<br>
+                               dc->hwss.enable_vblanks_synchronization &&<br>
+                               unsynced_pipes[j]->stream_res.tg->funcs->align_vblanks &&<br>
+                               resource_are_vblanks_synchronizable(<br>
+                                       unsynced_pipes[j]->stream,<br>
+                                       pipe_set[0]->stream)) {<br>
+                               sync_type = VBLANK_SYNCHRONIZABLE;<br>
+                               pipe_set[group_size] = unsynced_pipes[j];<br>
+                               unsynced_pipes[j] = NULL;<br>
+                               group_size++;<br>
+                       } else<br>
+                       if (sync_type != VBLANK_SYNCHRONIZABLE &&<br>
+                               resource_are_streams_timing_synchronizable(<br>
                                        unsynced_pipes[j]->stream,<br>
                                        pipe_set[0]->stream)) {<br>
+                               sync_type = TIMING_SYNCHRONIZABLE;<br>
                                pipe_set[group_size] = unsynced_pipes[j];<br>
                                unsynced_pipes[j] = NULL;<br>
                                group_size++;<br>
@@ -1145,7 +1158,6 @@ static void program_timing_sync(<br>
                        }<br>
                }<br>
<br>
-<br>
                for (k = 0; k < group_size; k++) {<br>
                        struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream);<br>
<br>
@@ -1175,8 +1187,14 @@ static void program_timing_sync(<br>
                }<br>
<br>
                if (group_size > 1) {<br>
-                       dc->hwss.enable_timing_synchronization(<br>
-                               dc, group_index, group_size, pipe_set);<br>
+                       if (sync_type == TIMING_SYNCHRONIZABLE) {<br>
+                               dc->hwss.enable_timing_synchronization(<br>
+                                       dc, group_index, group_size, pipe_set);<br>
+                       } else<br>
+                               if (sync_type == VBLANK_SYNCHRONIZABLE) {<br>
+                               dc->hwss.enable_vblanks_synchronization(<br>
+                                       dc, group_index, group_size, pipe_set);<br>
+                               }<br>
                        group_index++;<br>
                }<br>
                num_group++;<br>
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c<br>
index 0c26c2ade782..0241c9d96d7a 100644<br>
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c<br>
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c<br>
@@ -417,6 +417,49 @@ int resource_get_clock_source_reference(<br>
        return -1;<br>
 }<br>
<br>
+bool resource_are_vblanks_synchronizable(<br>
+       struct dc_stream_state *stream1,<br>
+       struct dc_stream_state *stream2)<br>
+{<br>
+       uint32_t base60_refresh_rates[] = {10, 20, 5};<br>
+       uint8_t i;<br>
+       uint8_t rr_count = sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]);<br>
+       int64_t frame_time_diff;<br>
+<br>
+       if (stream1->ctx->dc->config.vblank_alignment_dto_params &&<br>
+               stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 &&<br>
+               dc_is_dp_signal(stream1->signal) &&<br>
+               dc_is_dp_signal(stream2->signal) &&<br>
+               false == stream1->has_non_synchronizable_pclk &&<br>
+               false == stream2->has_non_synchronizable_pclk &&<br>
+               stream1->timing.flags.VBLANK_SYNCHRONIZABLE &&<br>
+               stream2->timing.flags.VBLANK_SYNCHRONIZABLE) {<br>
+               /* disable refresh rates higher than 60Hz for now */<br>
+               if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/<br>
+                               stream1->timing.v_total > 60)<br>
+                       return false;<br>
+               if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/<br>
+                               stream2->timing.v_total > 60)<br>
+                       return false;<br>
+               frame_time_diff = (int64_t)10000 *<br>
+                       stream1->timing.h_total *<br>
+                       stream1->timing.v_total *<br>
+                       stream2->timing.pix_clk_100hz /<br>
+                       stream1->timing.pix_clk_100hz /<br>
+                       stream2->timing.h_total /<br>
+                       stream2->timing.v_total;<br>
+               for (i = 0; i < rr_count; i++) {<br>
+                       int64_t diff = (frame_time_diff * base60_refresh_rates[i]) / 10 - 10000;<br>
+<br>
+                       if (diff < 0)<br>
+                               diff = -diff;<br>
+                       if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff)<br>
+                               return true;<br>
+               }<br>
+       }<br>
+       return false;<br>
+}<br>
+<br>
 bool resource_are_streams_timing_synchronizable(<br>
        struct dc_stream_state *stream1,<br>
        struct dc_stream_state *stream2)<br>
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h<br>
index a10daf6655f9..9e631980fa1b 100644<br>
--- a/drivers/gpu/drm/amd/display/dc/dc.h<br>
+++ b/drivers/gpu/drm/amd/display/dc/dc.h<br>
@@ -301,6 +301,8 @@ struct dc_config {<br>
 #if defined(CONFIG_DRM_AMD_DC_DCN)<br>
        bool clamp_min_dcfclk;<br>
 #endif<br>
+       uint64_t vblank_alignment_dto_params;<br>
+       uint8_t  vblank_alignment_max_frame_time_diff;<br>
 };<br>
<br>
 enum visual_confirm {<br>
@@ -528,6 +530,7 @@ struct dc_debug_options {<br>
        bool disable_dsc;<br>
        bool enable_dram_clock_change_one_display_vactive;<br>
        union mem_low_power_enable_options enable_mem_low_power;<br>
+       bool force_vblank_alignment;<br>
 };<br>
<br>
 struct dc_debug_data {<br>
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h<br>
index b41e6367b15e..48d3ed97ead9 100644<br>
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h<br>
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h<br>
@@ -705,6 +705,7 @@ struct dc_crtc_timing_flags {<br>
 #ifndef TRIM_FSFT<br>
        uint32_t FAST_TRANSPORT: 1;<br>
 #endif<br>
+       uint32_t VBLANK_SYNCHRONIZABLE: 1;<br>
 };<br>
<br>
 enum dc_timing_3d_format {<br>
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h<br>
index e243c01b9672..7fa998f97e7a 100644<br>
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h<br>
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h<br>
@@ -228,6 +228,9 @@ struct dc_stream_state {<br>
        uint32_t stream_id;<br>
        bool is_dsc_enabled;<br>
        union stream_update_flags update_flags;<br>
+<br>
+       bool has_non_synchronizable_pclk;<br>
+       bool vblank_synchronized;<br>
 };<br>
<br>
 #define ABM_LEVEL_IMMEDIATE_DISABLE 255<br>
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c<br>
index dec58b3c42e4..6f47f9bab5ee 100644<br>
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c<br>
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c<br>
@@ -1002,15 +1002,27 @@ static bool get_pixel_clk_frequency_100hz(<br>
 {<br>
        struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);<br>
        unsigned int clock_hz = 0;<br>
+       unsigned int modulo_hz = 0;<br>
<br>
        if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) {<br>
                clock_hz = REG_READ(PHASE[inst]);<br>
<br>
-               /* NOTE: There is agreement with VBIOS here that MODULO is<br>
-                * programmed equal to DPREFCLK, in which case PHASE will be<br>
-                * equivalent to pixel clock.<br>
-                */<br>
-               *pixel_clk_khz = clock_hz / 100;<br>
+               if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&<br>
+                       clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {<br>
+                       /* NOTE: In case VBLANK syncronization is enabled, MODULO may<br>
+                        * not be programmed equal to DPREFCLK<br>
+                        */<br>
+                       modulo_hz = REG_READ(MODULO[inst]);<br>
+                       *pixel_clk_khz = ((uint64_t)clock_hz*<br>
+                               clock_source->ctx->dc->clk_mgr->dprefclk_khz*10)/<br>
+                               modulo_hz;<br>
+               } else {<br>
+                       /* NOTE: There is agreement with VBIOS here that MODULO is<br>
+                        * programmed equal to DPREFCLK, in which case PHASE will be<br>
+                        * equivalent to pixel clock.<br>
+                        */<br>
+                       *pixel_clk_khz = clock_hz / 100;<br>
+               }<br>
                return true;<br>
        }<br>
<br>
@@ -1074,8 +1086,35 @@ static bool dcn20_program_pix_clk(<br>
                struct pixel_clk_params *pix_clk_params,<br>
                struct pll_settings *pll_settings)<br>
 {<br>
+       struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);<br>
+       unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;<br>
+<br>
        dce112_program_pix_clk(clock_source, pix_clk_params, pll_settings);<br>
<br>
+       if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&<br>
+                       clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {<br>
+               /* NOTE: In case VBLANK syncronization is enabled,<br>
+                * we need to set modulo to default DPREFCLK first<br>
+                * dce112_program_pix_clk does not set default DPREFCLK<br>
+                */<br>
+               REG_WRITE(MODULO[inst],<br>
+                       clock_source->ctx->dc->clk_mgr->dprefclk_khz*1000);<br>
+       }<br>
+       return true;<br>
+}<br>
+<br>
+static bool dcn20_override_dp_pix_clk(<br>
+               struct clock_source *clock_source,<br>
+               unsigned int inst,<br>
+               unsigned int pixel_clk,<br>
+               unsigned int ref_clk)<br>
+{<br>
+       struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);<br>
+<br>
+       REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 0);<br>
+       REG_WRITE(PHASE[inst], pixel_clk);<br>
+       REG_WRITE(MODULO[inst], ref_clk);<br>
+       REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1);<br>
        return true;<br>
 }<br>
<br>
@@ -1083,7 +1122,8 @@ static const struct clock_source_funcs dcn20_clk_src_funcs = {<br>
        .cs_power_down = dce110_clock_source_power_down,<br>
        .program_pix_clk = dcn20_program_pix_clk,<br>
        .get_pix_clk_dividers = dce112_get_pix_clk_dividers,<br>
-       .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz<br>
+       .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz,<br>
+       .override_dp_pix_clk = dcn20_override_dp_pix_clk<br>
 };<br>
<br>
 #if defined(CONFIG_DRM_AMD_DC_DCN)<br>
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<br>
index 89912bb5014f..669cee48b0b5 100644<br>
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c<br>
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c<br>
@@ -1851,6 +1851,225 @@ static bool wait_for_reset_trigger_to_occur(<br>
        return rc;<br>
 }<br>
<br>
+uint64_t reduceSizeAndFraction(<br>
+       uint64_t *numerator,<br>
+       uint64_t *denominator,<br>
+       bool checkUint32Bounary)<br>
+{<br>
+       int i;<br>
+       bool ret = checkUint32Bounary == false;<br>
+       uint64_t max_int32 = 0xffffffff;<br>
+       uint64_t num, denom;<br>
+       uint16_t prime_numbers[] = {<br>
+               2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,<br>
+               47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,<br>
+               107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,<br>
+               167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,<br>
+               229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,<br>
+               283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353,<br>
+               359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421,<br>
+               431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487,<br>
+               491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,<br>
+               571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631,<br>
+               641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,<br>
+               709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773,<br>
+               787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857,<br>
+               859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,<br>
+               941, 947, 953, 967, 971, 977, 983, 991, 997};<br>
+       int count = ARRAY_SIZE(prime_numbers)/sizeof(prime_numbers[0]);<br>
</blockquote>
</div>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">ARRAY_SIZE gives the number of elements, so this will limit iteration to the first half of the prime_numbers array. Btw, the array can be "static const".</div>
<div dir="auto"><br>
</div>
<div dir="auto">BR</div>
<div dir="auto">Nils</div>
</div>
</div>
</div>
</body>
</html>