All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] DC Patches FEB 22, 2021
@ 2021-02-19 22:15 Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 01/13] drm/amd/display: Remove Assert from dcn10_get_dig_frontend Bindu Ramamurthy
                   ` (13 more replies)
  0 siblings, 14 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:15 UTC (permalink / raw)
  To: amd-gfx
  Cc: Eryk.Brol, Sunpeng.Li, Harry.Wentland, Qingqing.Zhuo,
	Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai,
	Bhawanpreet.Lakha, bindu.r


This DC patchset brings improvements in multiple areas. In summary, we highlight:
* Firmware release 0.0.53.
* Addition of interrupts for DCN2.1
* Refractor debugfs entries for connectors.
* Enable display audio when seamless booting with an external monitor over DP.
* Fixes for System hang after multiple hotplug, timing synchronization for displays, disable seamless boot for DP.


Anthony Koo (1):
  drm/amd/display: [FW Promotion] Release 0.0.53

Anthony Wang (2):
  drm/amd/display: disable seamless boot for DP MST
  drm/amd/display: enable audio on DP seamless boot

Aric Cyr (3):
  drm/amd/display: Don't optimize bandwidth before disabling planes
  drm/amd/display: reduce scope for local var

  drm/amd/display: 3.2.124
       This version brings along following fixes:
       - Fix system hang after multiple hotplug.
       - Don't optimize bandwidth before disabling planes.
       - Report timing synchronizable when DP streams time frame difference is less than 0.05 percent.
       - move trace buffer to uncached memory.
       - enable audio on DP seamless boot. 
       - Disable seamless boot for DP MST.


Eric Bernstein (1):
  drm/amd/display: Remove Assert from dcn10_get_dig_frontend

Eryk Brol (1):
  drm/amd/display: Check for DSC support instead of ASIC revision

Qingqing Zhuo (1):
  drm/amd/display: Fix system hang after multiple hotplugs

Rodrigo Siqueira (1):
  drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1

Stylon Wang (1):
  drm/amd/display: Refactor debugfs entries for all connectors

Vladimir Stempen (1):
  drm/amd/display: Synchronize displays with different timings

Yongqiang Sun (1):
  drm/amd/display: move trace buffer to uncached memory.

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  82 +++++--
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  27 +++
 .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c |  22 +-
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  39 ++-
 drivers/gpu/drm/amd/display/dc/core/dc_link.c |  10 +
 .../gpu/drm/amd/display/dc/core/dc_resource.c |  43 ++++
 drivers/gpu/drm/amd/display/dc/dc.h           |   5 +-
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |   1 +
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |   3 +
 .../drm/amd/display/dc/dce/dce_clock_source.c |  52 +++-
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 225 ++++++++++++++++++
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.h |   5 +
 .../amd/display/dc/dcn10/dcn10_link_encoder.c |   1 -
 .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h |   2 +
 .../display/dc/dcn10/dcn10_stream_encoder.c   |   1 -
 .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c |   1 +
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 123 ++++++++++
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   8 +-
 .../dc/dcn30/dcn30_dio_stream_encoder.c       |   1 -
 .../drm/amd/display/dc/dcn30/dcn30_hwseq.c    |   2 +
 .../gpu/drm/amd/display/dc/inc/clock_source.h |   5 +
 .../amd/display/dc/inc/hw/timing_generator.h  |  12 +
 .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |   3 +
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   4 +
 .../display/dc/irq/dcn21/irq_service_dcn21.c  |  22 ++
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   |   4 +-
 .../gpu/drm/amd/display/dmub/src/dmub_dcn20.c |   7 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn20.h |   7 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn30.c |   7 +
 29 files changed, 676 insertions(+), 48 deletions(-)

-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 01/13] drm/amd/display: Remove Assert from dcn10_get_dig_frontend
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 02/13] drm/amd/display: Refactor debugfs entries for all connectors Bindu Ramamurthy
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Eryk.Brol, Sunpeng.Li, Harry.Wentland, Qingqing.Zhuo,
	Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai, Eric Bernstein,
	Bhawanpreet.Lakha, bindu.r

From: Eric Bernstein <eric.bernstein@amd.com>

[Why]
In some cases, this function is called when DIG BE is not
connected to DIG FE, in which case a value of zero isn't
invalid and assert should not be hit.

[How]
Remove assert and handle ENGINE_ID_UNKNOWN result in calling
function.

Signed-off-by: Eric Bernstein <eric.bernstein@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c | 1 -
 drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c        | 2 ++
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c
index 59024653430c..e4701825b5a0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c
@@ -480,7 +480,6 @@ unsigned int dcn10_get_dig_frontend(struct link_encoder *enc)
 		break;
 	default:
 		// invalid source select DIG
-		ASSERT(false);
 		result = ENGINE_ID_UNKNOWN;
 	}
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
index ab93da667d51..aaeefe7eca3e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
@@ -539,6 +539,8 @@ void dcn30_init_hw(struct dc *dc)
 
 					fe = dc->links[i]->link_enc->funcs->get_dig_frontend(
 										dc->links[i]->link_enc);
+					if (fe == ENGINE_ID_UNKNOWN)
+						continue;
 
 					for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
 						if (fe == dc->res_pool->stream_enc[j]->id) {
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 02/13] drm/amd/display: Refactor debugfs entries for all connectors
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 01/13] drm/amd/display: Remove Assert from dcn10_get_dig_frontend Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-19 22:16   ` Bindu Ramamurthy
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Stylon Wang, Eryk.Brol, Sunpeng.Li, Harry.Wentland,
	Qingqing.Zhuo, Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai,
	Bhawanpreet.Lakha, bindu.r

From: Stylon Wang <stylon.wang@amd.com>

[Why]
Debugfs entries being moved from DP/eDP only to be available
on all connectors are cluttering the code.

[How]
Refactor the registration of these debugfs entries.

Signed-off-by: Stylon Wang <stylon.wang@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 22 ++++++++++++-------
 1 file changed, 14 insertions(+), 8 deletions(-)

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 704aa8cb668e..f7408d09ded9 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
@@ -2342,6 +2342,15 @@ static int psr_get(void *data, u64 *val)
 
 DEFINE_DEBUGFS_ATTRIBUTE(psr_fops, psr_get, NULL, "%llu\n");
 
+static const struct {
+	char *name;
+	const struct file_operations *fops;
+} connector_debugfs_entries[] = {
+		{"force_yuv420_output", &force_yuv420_output_fops},
+		{"output_bpc", &output_bpc_fops},
+		{"trigger_hotplug", &trigger_hotplug_debugfs_fops}
+};
+
 void connector_debugfs_init(struct amdgpu_dm_connector *connector)
 {
 	int i;
@@ -2358,14 +2367,11 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
 	if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)
 		debugfs_create_file_unsafe("psr_state", 0444, dir, connector, &psr_fops);
 
-	debugfs_create_file_unsafe("force_yuv420_output", 0644, dir, connector,
-				   &force_yuv420_output_fops);
-
-	debugfs_create_file("output_bpc", 0644, dir, connector,
-			    &output_bpc_fops);
-
-	debugfs_create_file("trigger_hotplug", 0644, dir, connector,
-			    &trigger_hotplug_debugfs_fops);
+	for (i = 0; i < ARRAY_SIZE(connector_debugfs_entries); i++) {
+		debugfs_create_file(connector_debugfs_entries[i].name,
+				    0644, dir, connector,
+				    connector_debugfs_entries[i].fops);
+	}
 
 	connector->debugfs_dpcd_address = 0;
 	connector->debugfs_dpcd_size = 0;
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 03/13] drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
@ 2021-02-19 22:16   ` Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 02/13] drm/amd/display: Refactor debugfs entries for all connectors Bindu Ramamurthy
                     ` (12 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry.Wentland, Sunpeng.Li, Bhawanpreet.Lakha, Rodrigo.Siqueira,
	Aurabindo.Pillai, Qingqing.Zhuo, Eryk.Brol, bindu.r, Anson.Jacob,
	stable

From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>

When run igt@kms_vrr in a device that uses DCN2.1 architecture, we
noticed multiple failures. Furthermore, when we tested a VRR demo, we
noticed a system hang where the mouse pointer still works, but the
entire system freezes; in this case, we don't see any dmesg warning or
failure messages kernel. This happens due to a lack of vupdate_no_lock
interrupt, making the userspace wait eternally to get the event back.
For fixing this issue, we need to add the vupdate_no_lock interrupt in
the interrupt list.

Cc: stable@vger.kernel.org
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 .../display/dc/irq/dcn21/irq_service_dcn21.c  | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
index 1b971265418b..0e0f494fbb5e 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
@@ -168,6 +168,11 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = {
 	.ack = NULL
 };
 
+static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = {
+	.set = NULL,
+	.ack = NULL
+};
+
 #undef BASE_INNER
 #define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg
 
@@ -230,6 +235,17 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = {
 		.funcs = &vblank_irq_info_funcs\
 	}
 
+/* vupdate_no_lock_int_entry maps to DC_IRQ_SOURCE_VUPDATEx, to match semantic
+ * of DCE's DC_IRQ_SOURCE_VUPDATEx.
+ */
+#define vupdate_no_lock_int_entry(reg_num)\
+	[DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\
+		IRQ_REG_ENTRY(OTG, reg_num,\
+			OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\
+			OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\
+		.funcs = &vupdate_no_lock_irq_info_funcs\
+	}
+
 #define vblank_int_entry(reg_num)\
 	[DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\
 		IRQ_REG_ENTRY(OTG, reg_num,\
@@ -338,6 +354,12 @@ irq_source_info_dcn21[DAL_IRQ_SOURCES_NUMBER] = {
 	vupdate_int_entry(3),
 	vupdate_int_entry(4),
 	vupdate_int_entry(5),
+	vupdate_no_lock_int_entry(0),
+	vupdate_no_lock_int_entry(1),
+	vupdate_no_lock_int_entry(2),
+	vupdate_no_lock_int_entry(3),
+	vupdate_no_lock_int_entry(4),
+	vupdate_no_lock_int_entry(5),
 	vblank_int_entry(0),
 	vblank_int_entry(1),
 	vblank_int_entry(2),
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 03/13] drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
@ 2021-02-19 22:16   ` Bindu Ramamurthy
  0 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Eryk.Brol, Sunpeng.Li, Harry.Wentland, Qingqing.Zhuo,
	Rodrigo.Siqueira, stable, Anson.Jacob, Aurabindo.Pillai,
	Bhawanpreet.Lakha, bindu.r

From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>

When run igt@kms_vrr in a device that uses DCN2.1 architecture, we
noticed multiple failures. Furthermore, when we tested a VRR demo, we
noticed a system hang where the mouse pointer still works, but the
entire system freezes; in this case, we don't see any dmesg warning or
failure messages kernel. This happens due to a lack of vupdate_no_lock
interrupt, making the userspace wait eternally to get the event back.
For fixing this issue, we need to add the vupdate_no_lock interrupt in
the interrupt list.

Cc: stable@vger.kernel.org
Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 .../display/dc/irq/dcn21/irq_service_dcn21.c  | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
index 1b971265418b..0e0f494fbb5e 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
@@ -168,6 +168,11 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = {
 	.ack = NULL
 };
 
+static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = {
+	.set = NULL,
+	.ack = NULL
+};
+
 #undef BASE_INNER
 #define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg
 
@@ -230,6 +235,17 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = {
 		.funcs = &vblank_irq_info_funcs\
 	}
 
+/* vupdate_no_lock_int_entry maps to DC_IRQ_SOURCE_VUPDATEx, to match semantic
+ * of DCE's DC_IRQ_SOURCE_VUPDATEx.
+ */
+#define vupdate_no_lock_int_entry(reg_num)\
+	[DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\
+		IRQ_REG_ENTRY(OTG, reg_num,\
+			OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\
+			OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\
+		.funcs = &vupdate_no_lock_irq_info_funcs\
+	}
+
 #define vblank_int_entry(reg_num)\
 	[DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\
 		IRQ_REG_ENTRY(OTG, reg_num,\
@@ -338,6 +354,12 @@ irq_source_info_dcn21[DAL_IRQ_SOURCES_NUMBER] = {
 	vupdate_int_entry(3),
 	vupdate_int_entry(4),
 	vupdate_int_entry(5),
+	vupdate_no_lock_int_entry(0),
+	vupdate_no_lock_int_entry(1),
+	vupdate_no_lock_int_entry(2),
+	vupdate_no_lock_int_entry(3),
+	vupdate_no_lock_int_entry(4),
+	vupdate_no_lock_int_entry(5),
 	vblank_int_entry(0),
 	vblank_int_entry(1),
 	vblank_int_entry(2),
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 04/13] drm/amd/display: disable seamless boot for DP MST
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
                   ` (2 preceding siblings ...)
  2021-02-19 22:16   ` Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 05/13] drm/amd/display: enable audio on DP seamless boot Bindu Ramamurthy
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Eryk.Brol, Sunpeng.Li, Harry.Wentland, Qingqing.Zhuo,
	Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai, Anthony Wang,
	Bhawanpreet.Lakha, bindu.r

From: Anthony Wang <anthony1.wang@amd.com>

[Why]
Seamless boot over DP MST is not POR, but is not explicitly disabled.

[How]
Add check for DP MST and return false in
dc_validate_seamless_boot_timing.

Signed-off-by: Anthony Wang <anthony1.wang@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index e2cc1a141131..2f56fa2c0bf4 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1213,8 +1213,9 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
 	unsigned int i, enc_inst, tg_inst = 0;
 
 	// Seamless port only support single DP and EDP so far
-	if (sink->sink_signal != SIGNAL_TYPE_DISPLAY_PORT &&
-		sink->sink_signal != SIGNAL_TYPE_EDP)
+	if ((sink->sink_signal != SIGNAL_TYPE_DISPLAY_PORT &&
+		sink->sink_signal != SIGNAL_TYPE_EDP) ||
+		sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
 		return false;
 
 	/* Check for enabled DIG to identify enabled display */
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 05/13] drm/amd/display: enable audio on DP seamless boot
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
                   ` (3 preceding siblings ...)
  2021-02-19 22:16 ` [PATCH 04/13] drm/amd/display: disable seamless boot for DP MST Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 06/13] drm/amd/display: Check for DSC support instead of ASIC revision Bindu Ramamurthy
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Eryk.Brol, Sunpeng.Li, Harry.Wentland, Qingqing.Zhuo,
	Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai, Anthony Wang,
	Bhawanpreet.Lakha, bindu.r

From: Anthony Wang <anthony1.wang@amd.com>

[Why]
Some external displays with DP can use seamless boot, but their audio endpoints are
only enabled after hotplug.
On boot, these displays inherit UEFI timings without properly initializing audio.

[How]
Enable display audio when seamless booting with an external monitor over DP.

Signed-off-by: Anthony Wang <anthony1.wang@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc_link.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

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 fa5059f71727..81ad546b2098 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -3258,6 +3258,16 @@ void core_link_enable_stream(
 		/* Do not touch link on seamless boot optimization. */
 		if (pipe_ctx->stream->apply_seamless_boot_optimization) {
 			pipe_ctx->stream->dpms_off = false;
+
+			/* Still enable stream features & audio on seamless boot for DP external displays */
+			if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) {
+				enable_stream_features(pipe_ctx);
+				if (pipe_ctx->stream_res.audio != NULL) {
+					pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
+					dc->hwss.enable_audio_stream(pipe_ctx);
+				}
+			}
+
 #if defined(CONFIG_DRM_AMD_DC_HDCP)
 			update_psp_stream_config(pipe_ctx, false);
 #endif
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 06/13] drm/amd/display: Check for DSC support instead of ASIC revision
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
                   ` (4 preceding siblings ...)
  2021-02-19 22:16 ` [PATCH 05/13] drm/amd/display: enable audio on DP seamless boot Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 07/13] drm/amd/display: move trace buffer to uncached memory Bindu Ramamurthy
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Eryk Brol, Sunpeng.Li, Harry.Wentland, Qingqing.Zhuo,
	Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai,
	Bhawanpreet.Lakha, bindu.r

From: Eryk Brol <eryk.brol@amd.com>

[why]
This check for ASIC revision is no longer useful and causes
lightup issues after a topology change in MST DSC scenario.
In this case, DSC configs should be recalculated for the new
topology. This check prevented that from happening on certain
ASICs that do, in fact, support DSC.

[how]
Change the ASIC revision to instead check if DSC is supported.

Signed-off-by: Eryk Brol <eryk.brol@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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 cf3ee268ea4f..0970d9c14889 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -9419,7 +9419,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 	}
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-	if (adev->asic_type >= CHIP_NAVI10) {
+	if (dc_resource_is_dsc_encoding_supported(dc)) {
 		for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
 			if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
 				ret = add_affected_mst_dsc_crtcs(state, crtc);
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 07/13] drm/amd/display: move trace buffer to uncached memory.
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
                   ` (5 preceding siblings ...)
  2021-02-19 22:16 ` [PATCH 06/13] drm/amd/display: Check for DSC support instead of ASIC revision Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 08/13] drm/amd/display: Synchronize displays with different timings Bindu Ramamurthy
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Eryk.Brol, Sunpeng.Li, Harry.Wentland, Qingqing.Zhuo,
	Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai, Yongqiang Sun,
	Bhawanpreet.Lakha, bindu.r

From: Yongqiang Sun <yongqiang.sun@amd.com>

[Why & How]
Move dmub trace buffer to uncached memory.

Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c | 7 +++++++
 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h | 7 +++++++
 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c | 7 +++++++
 3 files changed, 21 insertions(+)

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 8e8e65fa83c0..ea30da4f794f 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
@@ -248,6 +248,13 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
 		  DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top,
 		  DMCUB_REGION3_CW5_ENABLE, 1);
 
+	REG_WRITE(DMCUB_REGION5_OFFSET, offset.u.low_part);
+	REG_WRITE(DMCUB_REGION5_OFFSET_HIGH, offset.u.high_part);
+	REG_SET_2(DMCUB_REGION5_TOP_ADDRESS, 0,
+		  DMCUB_REGION5_TOP_ADDRESS,
+		  cw5->region.top - cw5->region.base - 1,
+		  DMCUB_REGION5_ENABLE, 1);
+
 	dmub_dcn20_translate_addr(&cw6->offset, fb_base, fb_offset, &offset);
 
 	REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part);
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
index a62be9c0652e..30c6d631a431 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.h
@@ -75,6 +75,9 @@ struct dmub_srv;
 	DMUB_SR(DMCUB_REGION4_OFFSET) \
 	DMUB_SR(DMCUB_REGION4_OFFSET_HIGH) \
 	DMUB_SR(DMCUB_REGION4_TOP_ADDRESS) \
+	DMUB_SR(DMCUB_REGION5_OFFSET) \
+	DMUB_SR(DMCUB_REGION5_OFFSET_HIGH) \
+	DMUB_SR(DMCUB_REGION5_TOP_ADDRESS) \
 	DMUB_SR(DMCUB_SCRATCH0) \
 	DMUB_SR(DMCUB_SCRATCH1) \
 	DMUB_SR(DMCUB_SCRATCH2) \
@@ -123,6 +126,8 @@ struct dmub_srv;
 	DMUB_SF(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_ENABLE) \
 	DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_TOP_ADDRESS) \
 	DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_ENABLE) \
+	DMUB_SF(DMCUB_REGION5_TOP_ADDRESS, DMCUB_REGION5_TOP_ADDRESS) \
+	DMUB_SF(DMCUB_REGION5_TOP_ADDRESS, DMCUB_REGION5_ENABLE) \
 	DMUB_SF(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE) \
 	DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \
 	DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \
@@ -200,4 +205,6 @@ union dmub_fw_boot_status dmub_dcn20_get_fw_boot_status(struct dmub_srv *dmub);
 
 bool dmub_dcn20_use_cached_inbox(struct dmub_srv *dmub);
 
+bool dmub_dcn20_use_cached_trace_buffer(struct dmub_srv *dmub);
+
 #endif /* _DMUB_DCN20_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
index b4bc0df2f14a..fb11c8d39208 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
@@ -180,6 +180,13 @@ void dmub_dcn30_setup_windows(struct dmub_srv *dmub,
 		  DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top,
 		  DMCUB_REGION3_CW5_ENABLE, 1);
 
+	REG_WRITE(DMCUB_REGION5_OFFSET, offset.u.low_part);
+	REG_WRITE(DMCUB_REGION5_OFFSET_HIGH, offset.u.high_part);
+	REG_SET_2(DMCUB_REGION5_TOP_ADDRESS, 0,
+		  DMCUB_REGION5_TOP_ADDRESS,
+		  cw5->region.top - cw5->region.base - 1,
+		  DMCUB_REGION5_ENABLE, 1);
+
 	offset = cw6->offset;
 
 	REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part);
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 08/13] drm/amd/display: Synchronize displays with different timings
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
                   ` (6 preceding siblings ...)
  2021-02-19 22:16 ` [PATCH 07/13] drm/amd/display: move trace buffer to uncached memory Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-21  6:21   ` Nils Wallménius
  2021-02-19 22:16 ` [PATCH 09/13] drm/amd/display: Don't optimize bandwidth before disabling planes Bindu Ramamurthy
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Vladimir Stempen, Eryk.Brol, Sunpeng.Li, Harry.Wentland,
	Qingqing.Zhuo, Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai,
	Bhawanpreet.Lakha, bindu.r

From: Vladimir Stempen <vladimir.stempen@amd.com>

[why]
 Vendor based fan noise improvement

[how]
Report timing synchronizable when DP streams time frame
difference is less than 0.05 percent. Adjust DP  DTOs and
sync displays using  MASTER_UPDATE_LOCK_DB_X_Y

Signed-off-by: Vladimir Stempen <vladimir.stempen@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  28 ++-
 .../gpu/drm/amd/display/dc/core/dc_resource.c |  43 ++++
 drivers/gpu/drm/amd/display/dc/dc.h           |   3 +
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |   1 +
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |   3 +
 .../drm/amd/display/dc/dce/dce_clock_source.c |  52 +++-
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 225 ++++++++++++++++++
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.h |   5 +
 .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h |   2 +
 .../display/dc/dcn10/dcn10_stream_encoder.c   |   1 -
 .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c |   1 +
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 123 ++++++++++
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   8 +-
 .../dc/dcn30/dcn30_dio_stream_encoder.c       |   1 -
 .../gpu/drm/amd/display/dc/inc/clock_source.h |   5 +
 .../amd/display/dc/inc/hw/timing_generator.h  |  12 +
 .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |   3 +
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   4 +
 18 files changed, 505 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 2f56fa2c0bf4..39df5d2c0108 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1102,6 +1102,7 @@ static void program_timing_sync(
 
 	for (i = 0; i < pipe_count; i++) {
 		int group_size = 1;
+		enum timing_synchronization_type sync_type = NOT_SYNCHRONIZABLE;
 		struct pipe_ctx *pipe_set[MAX_PIPES];
 
 		if (!unsynced_pipes[i])
@@ -1116,10 +1117,22 @@ static void program_timing_sync(
 		for (j = i + 1; j < pipe_count; j++) {
 			if (!unsynced_pipes[j])
 				continue;
-
-			if (resource_are_streams_timing_synchronizable(
+			if (sync_type != TIMING_SYNCHRONIZABLE &&
+				dc->hwss.enable_vblanks_synchronization &&
+				unsynced_pipes[j]->stream_res.tg->funcs->align_vblanks &&
+				resource_are_vblanks_synchronizable(
+					unsynced_pipes[j]->stream,
+					pipe_set[0]->stream)) {
+				sync_type = VBLANK_SYNCHRONIZABLE;
+				pipe_set[group_size] = unsynced_pipes[j];
+				unsynced_pipes[j] = NULL;
+				group_size++;
+			} else
+			if (sync_type != VBLANK_SYNCHRONIZABLE &&
+				resource_are_streams_timing_synchronizable(
 					unsynced_pipes[j]->stream,
 					pipe_set[0]->stream)) {
+				sync_type = TIMING_SYNCHRONIZABLE;
 				pipe_set[group_size] = unsynced_pipes[j];
 				unsynced_pipes[j] = NULL;
 				group_size++;
@@ -1145,7 +1158,6 @@ static void program_timing_sync(
 			}
 		}
 
-
 		for (k = 0; k < group_size; k++) {
 			struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream);
 
@@ -1175,8 +1187,14 @@ static void program_timing_sync(
 		}
 
 		if (group_size > 1) {
-			dc->hwss.enable_timing_synchronization(
-				dc, group_index, group_size, pipe_set);
+			if (sync_type == TIMING_SYNCHRONIZABLE) {
+				dc->hwss.enable_timing_synchronization(
+					dc, group_index, group_size, pipe_set);
+			} else
+				if (sync_type == VBLANK_SYNCHRONIZABLE) {
+				dc->hwss.enable_vblanks_synchronization(
+					dc, group_index, group_size, pipe_set);
+				}
 			group_index++;
 		}
 		num_group++;
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 0c26c2ade782..0241c9d96d7a 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -417,6 +417,49 @@ int resource_get_clock_source_reference(
 	return -1;
 }
 
+bool resource_are_vblanks_synchronizable(
+	struct dc_stream_state *stream1,
+	struct dc_stream_state *stream2)
+{
+	uint32_t base60_refresh_rates[] = {10, 20, 5};
+	uint8_t i;
+	uint8_t rr_count = sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]);
+	int64_t frame_time_diff;
+
+	if (stream1->ctx->dc->config.vblank_alignment_dto_params &&
+		stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 &&
+		dc_is_dp_signal(stream1->signal) &&
+		dc_is_dp_signal(stream2->signal) &&
+		false == stream1->has_non_synchronizable_pclk &&
+		false == stream2->has_non_synchronizable_pclk &&
+		stream1->timing.flags.VBLANK_SYNCHRONIZABLE &&
+		stream2->timing.flags.VBLANK_SYNCHRONIZABLE) {
+		/* disable refresh rates higher than 60Hz for now */
+		if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/
+				stream1->timing.v_total > 60)
+			return false;
+		if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/
+				stream2->timing.v_total > 60)
+			return false;
+		frame_time_diff = (int64_t)10000 *
+			stream1->timing.h_total *
+			stream1->timing.v_total *
+			stream2->timing.pix_clk_100hz /
+			stream1->timing.pix_clk_100hz /
+			stream2->timing.h_total /
+			stream2->timing.v_total;
+		for (i = 0; i < rr_count; i++) {
+			int64_t diff = (frame_time_diff * base60_refresh_rates[i]) / 10 - 10000;
+
+			if (diff < 0)
+				diff = -diff;
+			if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff)
+				return true;
+		}
+	}
+	return false;
+}
+
 bool resource_are_streams_timing_synchronizable(
 	struct dc_stream_state *stream1,
 	struct dc_stream_state *stream2)
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index a10daf6655f9..9e631980fa1b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -301,6 +301,8 @@ struct dc_config {
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 	bool clamp_min_dcfclk;
 #endif
+	uint64_t vblank_alignment_dto_params;
+	uint8_t  vblank_alignment_max_frame_time_diff;
 };
 
 enum visual_confirm {
@@ -528,6 +530,7 @@ struct dc_debug_options {
 	bool disable_dsc;
 	bool enable_dram_clock_change_one_display_vactive;
 	union mem_low_power_enable_options enable_mem_low_power;
+	bool force_vblank_alignment;
 };
 
 struct dc_debug_data {
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index b41e6367b15e..48d3ed97ead9 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -705,6 +705,7 @@ struct dc_crtc_timing_flags {
 #ifndef TRIM_FSFT
 	uint32_t FAST_TRANSPORT: 1;
 #endif
+	uint32_t VBLANK_SYNCHRONIZABLE: 1;
 };
 
 enum dc_timing_3d_format {
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index e243c01b9672..7fa998f97e7a 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -228,6 +228,9 @@ struct dc_stream_state {
 	uint32_t stream_id;
 	bool is_dsc_enabled;
 	union stream_update_flags update_flags;
+
+	bool has_non_synchronizable_pclk;
+	bool vblank_synchronized;
 };
 
 #define ABM_LEVEL_IMMEDIATE_DISABLE 255
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
index dec58b3c42e4..6f47f9bab5ee 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -1002,15 +1002,27 @@ static bool get_pixel_clk_frequency_100hz(
 {
 	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
 	unsigned int clock_hz = 0;
+	unsigned int modulo_hz = 0;
 
 	if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) {
 		clock_hz = REG_READ(PHASE[inst]);
 
-		/* NOTE: There is agreement with VBIOS here that MODULO is
-		 * programmed equal to DPREFCLK, in which case PHASE will be
-		 * equivalent to pixel clock.
-		 */
-		*pixel_clk_khz = clock_hz / 100;
+		if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&
+			clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {
+			/* NOTE: In case VBLANK syncronization is enabled, MODULO may
+			 * not be programmed equal to DPREFCLK
+			 */
+			modulo_hz = REG_READ(MODULO[inst]);
+			*pixel_clk_khz = ((uint64_t)clock_hz*
+				clock_source->ctx->dc->clk_mgr->dprefclk_khz*10)/
+				modulo_hz;
+		} else {
+			/* NOTE: There is agreement with VBIOS here that MODULO is
+			 * programmed equal to DPREFCLK, in which case PHASE will be
+			 * equivalent to pixel clock.
+			 */
+			*pixel_clk_khz = clock_hz / 100;
+		}
 		return true;
 	}
 
@@ -1074,8 +1086,35 @@ static bool dcn20_program_pix_clk(
 		struct pixel_clk_params *pix_clk_params,
 		struct pll_settings *pll_settings)
 {
+	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
+	unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
+
 	dce112_program_pix_clk(clock_source, pix_clk_params, pll_settings);
 
+	if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&
+			clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {
+		/* NOTE: In case VBLANK syncronization is enabled,
+		 * we need to set modulo to default DPREFCLK first
+		 * dce112_program_pix_clk does not set default DPREFCLK
+		 */
+		REG_WRITE(MODULO[inst],
+			clock_source->ctx->dc->clk_mgr->dprefclk_khz*1000);
+	}
+	return true;
+}
+
+static bool dcn20_override_dp_pix_clk(
+		struct clock_source *clock_source,
+		unsigned int inst,
+		unsigned int pixel_clk,
+		unsigned int ref_clk)
+{
+	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
+
+	REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 0);
+	REG_WRITE(PHASE[inst], pixel_clk);
+	REG_WRITE(MODULO[inst], ref_clk);
+	REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1);
 	return true;
 }
 
@@ -1083,7 +1122,8 @@ static const struct clock_source_funcs dcn20_clk_src_funcs = {
 	.cs_power_down = dce110_clock_source_power_down,
 	.program_pix_clk = dcn20_program_pix_clk,
 	.get_pix_clk_dividers = dce112_get_pix_clk_dividers,
-	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
+	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz,
+	.override_dp_pix_clk = dcn20_override_dp_pix_clk
 };
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
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 89912bb5014f..669cee48b0b5 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
@@ -1851,6 +1851,225 @@ static bool wait_for_reset_trigger_to_occur(
 	return rc;
 }
 
+uint64_t reduceSizeAndFraction(
+	uint64_t *numerator,
+	uint64_t *denominator,
+	bool checkUint32Bounary)
+{
+	int i;
+	bool ret = checkUint32Bounary == false;
+	uint64_t max_int32 = 0xffffffff;
+	uint64_t num, denom;
+	uint16_t prime_numbers[] = {
+		2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
+		47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
+		107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
+		167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
+		229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
+		283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353,
+		359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421,
+		431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487,
+		491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,
+		571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631,
+		641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
+		709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773,
+		787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857,
+		859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
+		941, 947, 953, 967, 971, 977, 983, 991, 997};
+	int count = ARRAY_SIZE(prime_numbers)/sizeof(prime_numbers[0]);
+
+	num = *numerator;
+	denom = *denominator;
+	for (i = 0; i < count; i++) {
+		if (checkUint32Bounary &&
+			num <= max_int32 && denom <= max_int32) {
+			ret = true;
+			break;
+		}
+		while (num % prime_numbers[i] == 0 &&
+			   denom % prime_numbers[i] == 0) {
+			num /= prime_numbers[i];
+			denom /= prime_numbers[i];
+		}
+	}
+	*numerator = num;
+	*denominator = denom;
+	return ret;
+}
+
+bool is_low_refresh_rate(struct pipe_ctx *pipe)
+{
+	uint32_t master_pipe_refresh_rate =
+		pipe->stream->timing.pix_clk_100hz * 100 /
+		pipe->stream->timing.h_total /
+		pipe->stream->timing.v_total;
+	return master_pipe_refresh_rate <= 30;
+}
+
+uint8_t get_clock_divider(struct pipe_ctx *pipe, bool account_low_refresh_rate)
+{
+	uint32_t clock_divider = 1;
+	uint32_t numpipes = 1;
+
+	if (account_low_refresh_rate && is_low_refresh_rate(pipe))
+		clock_divider *= 2;
+
+	if (pipe->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420)
+		clock_divider *= 2;
+
+	while (pipe->next_odm_pipe) {
+		pipe = pipe->next_odm_pipe;
+		numpipes++;
+	}
+	clock_divider *= numpipes;
+
+	return clock_divider;
+}
+
+int dcn10_align_pixel_clocks(
+	struct dc *dc,
+	int group_size,
+	struct pipe_ctx *grouped_pipes[])
+{
+	struct dc_context *dc_ctx = dc->ctx;
+	int i, master = -1, embedded = -1;
+	struct dc_crtc_timing hw_crtc_timing[MAX_PIPES] = {0};
+	uint64_t phase[MAX_PIPES];
+	uint64_t modulo[MAX_PIPES];
+	unsigned int pclk;
+
+	uint32_t embedded_pix_clk_100hz;
+	uint16_t embedded_h_total;
+	uint16_t embedded_v_total;
+	bool clamshell_closed = false;
+	uint32_t dp_ref_clk_100hz =
+		dc->res_pool->dp_clock_source->ctx->dc->clk_mgr->dprefclk_khz*10;
+
+	if (dc->config.vblank_alignment_dto_params &&
+		dc->res_pool->dp_clock_source->funcs->override_dp_pix_clk) {
+		clamshell_closed =
+			(dc->config.vblank_alignment_dto_params >> 63);
+		embedded_h_total =
+			(dc->config.vblank_alignment_dto_params >> 32) & 0x7FFF;
+		embedded_v_total =
+			(dc->config.vblank_alignment_dto_params >> 48) & 0x7FFF;
+		embedded_pix_clk_100hz =
+			dc->config.vblank_alignment_dto_params & 0xFFFFFFFF;
+
+		for (i = 0; i < group_size; i++) {
+			grouped_pipes[i]->stream_res.tg->funcs->get_hw_timing(
+					grouped_pipes[i]->stream_res.tg,
+					&hw_crtc_timing[i]);
+			dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
+				dc->res_pool->dp_clock_source,
+				grouped_pipes[i]->stream_res.tg->inst,
+				&pclk);
+			hw_crtc_timing[i].pix_clk_100hz = pclk;
+			if (dc_is_embedded_signal(
+					grouped_pipes[i]->stream->signal)) {
+				embedded = i;
+				master = i;
+				phase[i] = embedded_pix_clk_100hz*100;
+				modulo[i] = dp_ref_clk_100hz*100;
+			} else {
+
+				phase[i] = (uint64_t)embedded_pix_clk_100hz*
+					hw_crtc_timing[i].h_total*
+					hw_crtc_timing[i].v_total/
+					get_clock_divider(grouped_pipes[i], true);
+				modulo[i] = (uint64_t)dp_ref_clk_100hz*
+					embedded_h_total*
+					embedded_v_total;
+
+				if (reduceSizeAndFraction(&phase[i],
+						&modulo[i], true) == false) {
+					/*
+					 * this will help to stop reporting
+					 * this timing synchronizable
+					 */
+					DC_SYNC_INFO("Failed to reduce DTO parameters\n");
+					grouped_pipes[i]->stream->has_non_synchronizable_pclk = true;
+				}
+			}
+		}
+
+		for (i = 0; i < group_size; i++) {
+			if (i != embedded && !grouped_pipes[i]->stream->has_non_synchronizable_pclk) {
+				dc->res_pool->dp_clock_source->funcs->override_dp_pix_clk(
+					dc->res_pool->dp_clock_source,
+					grouped_pipes[i]->stream_res.tg->inst,
+					phase[i], modulo[i]);
+				dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
+					dc->res_pool->dp_clock_source,
+					grouped_pipes[i]->stream_res.tg->inst, &pclk);
+					grouped_pipes[i]->stream->timing.pix_clk_100hz =
+						pclk*get_clock_divider(grouped_pipes[i], false);
+				if (master == -1)
+					master = i;
+			}
+		}
+
+	}
+	return master;
+}
+
+void dcn10_enable_vblanks_synchronization(
+	struct dc *dc,
+	int group_index,
+	int group_size,
+	struct pipe_ctx *grouped_pipes[])
+{
+	struct dc_context *dc_ctx = dc->ctx;
+	struct output_pixel_processor *opp;
+	struct timing_generator *tg;
+	int i, width, height, master;
+
+	for (i = 1; i < group_size; i++) {
+		opp = grouped_pipes[i]->stream_res.opp;
+		tg = grouped_pipes[i]->stream_res.tg;
+		tg->funcs->get_otg_active_size(tg, &width, &height);
+		if (opp->funcs->opp_program_dpg_dimensions)
+			opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1);
+	}
+
+	for (i = 0; i < group_size; i++) {
+		if (grouped_pipes[i]->stream == NULL)
+			continue;
+		grouped_pipes[i]->stream->vblank_synchronized = false;
+		grouped_pipes[i]->stream->has_non_synchronizable_pclk = false;
+	}
+
+	DC_SYNC_INFO("Aligning DP DTOs\n");
+
+	master = dcn10_align_pixel_clocks(dc, group_size, grouped_pipes);
+
+	DC_SYNC_INFO("Synchronizing VBlanks\n");
+
+	if (master >= 0) {
+		for (i = 0; i < group_size; i++) {
+			if (i != master && !grouped_pipes[i]->stream->has_non_synchronizable_pclk)
+			grouped_pipes[i]->stream_res.tg->funcs->align_vblanks(
+				grouped_pipes[master]->stream_res.tg,
+				grouped_pipes[i]->stream_res.tg,
+				grouped_pipes[master]->stream->timing.pix_clk_100hz,
+				grouped_pipes[i]->stream->timing.pix_clk_100hz,
+				get_clock_divider(grouped_pipes[master], false),
+				get_clock_divider(grouped_pipes[i], false));
+				grouped_pipes[i]->stream->vblank_synchronized = true;
+		}
+		grouped_pipes[master]->stream->vblank_synchronized = true;
+		DC_SYNC_INFO("Sync complete\n");
+	}
+
+	for (i = 1; i < group_size; i++) {
+		opp = grouped_pipes[i]->stream_res.opp;
+		tg = grouped_pipes[i]->stream_res.tg;
+		tg->funcs->get_otg_active_size(tg, &width, &height);
+		if (opp->funcs->opp_program_dpg_dimensions)
+			opp->funcs->opp_program_dpg_dimensions(opp, width, height);
+	}
+}
+
 void dcn10_enable_timing_synchronization(
 	struct dc *dc,
 	int group_index,
@@ -1872,6 +2091,12 @@ void dcn10_enable_timing_synchronization(
 			opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1);
 	}
 
+	for (i = 0; i < group_size; i++) {
+		if (grouped_pipes[i]->stream == NULL)
+			continue;
+		grouped_pipes[i]->stream->vblank_synchronized = false;
+	}
+
 	for (i = 1; i < group_size; i++)
 		grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
 				grouped_pipes[i]->stream_res.tg,
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 89e6dfb63da0..a30f74cfd11a 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
@@ -123,6 +123,11 @@ void dcn10_enable_timing_synchronization(
 		int group_index,
 		int group_size,
 		struct pipe_ctx *grouped_pipes[]);
+void dcn10_enable_vblanks_synchronization(
+		struct dc *dc,
+		int group_index,
+		int group_size,
+		struct pipe_ctx *grouped_pipes[]);
 void dcn10_enable_per_frame_crtc_position_reset(
 		struct dc *dc,
 		int group_size,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
index b222c67973d4..2529723beeb1 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
@@ -212,6 +212,7 @@ struct dcn_optc_registers {
 	SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\
 	SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\
 	SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\
+	SF(OTG0_OTG_CONTROL, OTG_CURRENT_MASTER_EN_STATE, mask_sh),\
 	SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\
 	SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\
 	SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\
@@ -352,6 +353,7 @@ struct dcn_optc_registers {
 	type OTG_START_POINT_CNTL;\
 	type OTG_DISABLE_POINT_CNTL;\
 	type OTG_FIELD_NUMBER_CNTL;\
+	type OTG_CURRENT_MASTER_EN_STATE;\
 	type OTG_STEREO_EN;\
 	type OTG_STEREO_SYNC_OUTPUT_LINE_NUM;\
 	type OTG_STEREO_SYNC_OUTPUT_POLARITY;\
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 73ac78b16bd4..f1a08a7736ac 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
@@ -738,7 +738,6 @@ void enc1_stream_encoder_update_dp_info_packets(
 	REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid);
 	REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid);
 
-
 	/* This bit is the master enable bit.
 	 * When enabling secondary stream engine,
 	 * this master bit must also be set.
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 51a4166e9750..5b74605d0abe 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c
@@ -42,6 +42,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = {
 	.program_output_csc = dcn20_program_output_csc,
 	.enable_accelerated_mode = dce110_enable_accelerated_mode,
 	.enable_timing_synchronization = dcn10_enable_timing_synchronization,
+	.enable_vblanks_synchronization = dcn10_enable_vblanks_synchronization,
 	.enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset,
 	.update_info_frame = dce110_update_info_frame,
 	.send_immediate_sdp_message = dcn10_send_immediate_sdp_message,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
index d8b18c515d06..ef6ee03175e0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -309,6 +309,128 @@ void optc2_set_dwb_source(struct timing_generator *optc,
 				OPTC_DWB1_SOURCE_SELECT, optc->inst);
 }
 
+void optc2_align_vblanks(
+	struct timing_generator *optc_master,
+	struct timing_generator *optc_slave,
+	uint32_t master_pixel_clock_100Hz,
+	uint32_t slave_pixel_clock_100Hz,
+	uint8_t master_clock_divider,
+	uint8_t slave_clock_divider)
+{
+	/* accessing slave OTG registers */
+	struct optc *optc1 = DCN10TG_FROM_TG(optc_slave);
+
+	uint32_t master_v_active = 0;
+	uint32_t master_h_total = 0;
+	uint32_t slave_h_total = 0;
+	uint64_t L, XY, p = 10000;
+	uint32_t X, Y;
+	uint32_t master_update_lock;
+
+	/* disable slave OTG */
+	REG_UPDATE(OTG_CONTROL, OTG_MASTER_EN, 0);
+	/* wait until disabled */
+	REG_WAIT(OTG_CONTROL,
+			 OTG_CURRENT_MASTER_EN_STATE,
+			 0, 10, 5000);
+
+	REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, &slave_h_total);
+
+	/* assign slave OTG to be controlled by master update lock */
+	REG_SET(OTG_GLOBAL_CONTROL0, 0,
+			OTG_MASTER_UPDATE_LOCK_SEL, optc_master->inst);
+
+	/* accessing master OTG registers */
+	optc1 = DCN10TG_FROM_TG(optc_master);
+
+	/* saving update lock state, not sure if it's needed */
+	REG_GET(OTG_MASTER_UPDATE_LOCK,
+			OTG_MASTER_UPDATE_LOCK, &master_update_lock);
+	/* unlocking master OTG */
+	REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
+			OTG_MASTER_UPDATE_LOCK, 0);
+
+	REG_GET(OTG_V_BLANK_START_END,
+			OTG_V_BLANK_START, &master_v_active);
+	REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, &master_h_total);
+
+	/* calculate when to enable slave OTG */
+	L = p * slave_h_total * master_pixel_clock_100Hz /
+		master_h_total / slave_pixel_clock_100Hz;
+	XY = L / p;
+	Y = master_v_active - XY - 1;
+	X = ((XY + 1) * p - L) * master_h_total / master_clock_divider / p;
+
+	/*
+	 * set master OTG to unlock when V/H
+	 * counters reach calculated values
+	 */
+	REG_UPDATE(OTG_GLOBAL_CONTROL1,
+			   MASTER_UPDATE_LOCK_DB_EN, 1);
+	REG_UPDATE_2(OTG_GLOBAL_CONTROL1,
+				 MASTER_UPDATE_LOCK_DB_X,
+				 X,
+				 MASTER_UPDATE_LOCK_DB_Y,
+				 Y);
+
+	/* lock master OTG */
+	REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
+			OTG_MASTER_UPDATE_LOCK, 1);
+	REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+			 UPDATE_LOCK_STATUS, 1, 1, 10);
+
+	/* accessing slave OTG registers */
+	optc1 = DCN10TG_FROM_TG(optc_slave);
+
+	/*
+	 * enable slave OTG, the OTG is locked with
+	 * master's update lock, so it will not run
+	 */
+	REG_UPDATE(OTG_CONTROL,
+			   OTG_MASTER_EN, 1);
+
+	/* accessing master OTG registers */
+	optc1 = DCN10TG_FROM_TG(optc_master);
+
+	/*
+	 * unlock master OTG. When master H/V counters reach
+	 * DB_XY point, slave OTG will start
+	 */
+	REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
+			OTG_MASTER_UPDATE_LOCK, 0);
+
+	/* accessing slave OTG registers */
+	optc1 = DCN10TG_FROM_TG(optc_slave);
+
+	/* wait for slave OTG to start running*/
+	REG_WAIT(OTG_CONTROL,
+			 OTG_CURRENT_MASTER_EN_STATE,
+			 1, 10, 5000);
+
+	/* accessing master OTG registers */
+	optc1 = DCN10TG_FROM_TG(optc_master);
+
+	/* disable the XY point*/
+	REG_UPDATE(OTG_GLOBAL_CONTROL1,
+			   MASTER_UPDATE_LOCK_DB_EN, 0);
+	REG_UPDATE_2(OTG_GLOBAL_CONTROL1,
+				 MASTER_UPDATE_LOCK_DB_X,
+				 0,
+				 MASTER_UPDATE_LOCK_DB_Y,
+				 0);
+
+	/*restore master update lock*/
+	REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
+			OTG_MASTER_UPDATE_LOCK, master_update_lock);
+
+	/* accessing slave OTG registers */
+	optc1 = DCN10TG_FROM_TG(optc_slave);
+	/* restore slave to be controlled by it's own */
+	REG_SET(OTG_GLOBAL_CONTROL0, 0,
+			OTG_MASTER_UPDATE_LOCK_SEL, optc_slave->inst);
+
+}
+
 void optc2_triplebuffer_lock(struct timing_generator *optc)
 {
 	struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -468,6 +590,7 @@ static struct timing_generator_funcs dcn20_tg_funcs = {
 		.program_manual_trigger = optc2_program_manual_trigger,
 		.setup_manual_trigger = optc2_setup_manual_trigger,
 		.get_hw_timing = optc1_get_hw_timing,
+		.align_vblanks = optc2_align_vblanks,
 };
 
 void dcn20_timing_generator_init(struct optc *optc1)
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 2c2dbfcd8957..a65efed63fbf 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -2033,9 +2033,13 @@ int dcn20_populate_dml_pipes_from_context(
 		if (res_ctx->pipe_ctx[pipe_cnt].stream == res_ctx->pipe_ctx[i].stream)
 			continue;
 
-		if (dc->debug.disable_timing_sync || !resource_are_streams_timing_synchronizable(
+		if (dc->debug.disable_timing_sync ||
+			(!resource_are_streams_timing_synchronizable(
 				res_ctx->pipe_ctx[pipe_cnt].stream,
-				res_ctx->pipe_ctx[i].stream)) {
+				res_ctx->pipe_ctx[i].stream) &&
+			!resource_are_vblanks_synchronizable(
+				res_ctx->pipe_ctx[pipe_cnt].stream,
+				res_ctx->pipe_ctx[i].stream))) {
 			synchronized_vblank = false;
 			break;
 		}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
index 6c0f7ef0a3df..72bee637c1e4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
@@ -454,7 +454,6 @@ static void enc3_stream_encoder_update_dp_info_packets(
 	REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid);
 	REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid);
 
-
 	/* This bit is the master enable bit.
 	 * When enabling secondary stream engine,
 	 * this master bit must also be set.
diff --git a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h
index 1b01a9a58d14..e2b3a2c7a927 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h
@@ -170,6 +170,11 @@ struct clock_source_funcs {
 			const struct clock_source *clock_source,
 			unsigned int inst,
 			unsigned int *pixel_clk_khz);
+	bool (*override_dp_pix_clk)(
+			struct clock_source *clock_source,
+			unsigned int inst,
+			unsigned int pixel_clk,
+			unsigned int ref_clk);
 };
 
 struct clock_source {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
index 754832d216fd..9ff68b67780c 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
@@ -109,6 +109,12 @@ enum h_timing_div_mode {
 	H_TIMING_DIV_BY4,
 };
 
+enum timing_synchronization_type {
+	NOT_SYNCHRONIZABLE,
+	TIMING_SYNCHRONIZABLE,
+	VBLANK_SYNCHRONIZABLE
+};
+
 struct crc_params {
 	/* Regions used to calculate CRC*/
 	uint16_t windowa_x_start;
@@ -292,6 +298,12 @@ struct timing_generator_funcs {
 			uint32_t window_start, uint32_t window_end);
 	void (*set_vtotal_change_limit)(struct timing_generator *optc,
 			uint32_t limit);
+	void (*align_vblanks)(struct timing_generator *master_optc,
+			struct timing_generator *slave_optc,
+			uint32_t master_pixel_clock_100Hz,
+			uint32_t slave_pixel_clock_100Hz,
+			uint8_t master_clock_divider,
+			uint8_t slave_clock_divider);
 };
 
 #endif
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 0586ab2ffd6a..714a5ace2298 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -111,6 +111,9 @@ struct hw_sequencer_funcs {
 	void (*enable_timing_synchronization)(struct dc *dc,
 			int group_index, int group_size,
 			struct pipe_ctx *grouped_pipes[]);
+	void (*enable_vblanks_synchronization)(struct dc *dc,
+			int group_index, int group_size,
+			struct pipe_ctx *grouped_pipes[]);
 	void (*setup_periodic_interrupt)(struct dc *dc,
 			struct pipe_ctx *pipe_ctx,
 			enum vline_select vline);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index d89815a46190..3d97078d52a9 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -115,6 +115,10 @@ bool resource_are_streams_timing_synchronizable(
 		struct dc_stream_state *stream1,
 		struct dc_stream_state *stream2);
 
+bool resource_are_vblanks_synchronizable(
+		struct dc_stream_state *stream1,
+		struct dc_stream_state *stream2);
+
 struct clock_source *resource_find_used_clk_src_for_sharing(
 		struct resource_context *res_ctx,
 		struct pipe_ctx *pipe_ctx);
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 09/13] drm/amd/display: Don't optimize bandwidth before disabling planes
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
                   ` (7 preceding siblings ...)
  2021-02-19 22:16 ` [PATCH 08/13] drm/amd/display: Synchronize displays with different timings Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 10/13] drm/amd/display: reduce scope for local var Bindu Ramamurthy
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Aric Cyr, Eryk.Brol, Sunpeng.Li, Harry.Wentland, Qingqing.Zhuo,
	Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai,
	Bhawanpreet.Lakha, bindu.r

From: Aric Cyr <aric.cyr@amd.com>

[Why]
There is a window of time where we optimize bandwidth due to no streams
enabled will enable PSTATE changing but HUBPs are not disabled yet.
This results in underflow counter increasing in some hotplug scenarios.

[How]
Set the optimize-bandwidth flag for later processing once all the HUBPs
are properly disabled.

Signed-off-by: Aric Cyr <aric.cyr@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 39df5d2c0108..4df26a67e570 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2413,7 +2413,8 @@ static void commit_planes_do_stream_update(struct dc *dc,
 					if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only)
 						pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
 
-					dc->hwss.optimize_bandwidth(dc, dc->current_state);
+					dc->optimized_required = true;
+
 				} else {
 					if (get_seamless_boot_stream_count(context) == 0)
 						dc->hwss.prepare_bandwidth(dc, dc->current_state);
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 10/13] drm/amd/display: reduce scope for local var
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
                   ` (8 preceding siblings ...)
  2021-02-19 22:16 ` [PATCH 09/13] drm/amd/display: Don't optimize bandwidth before disabling planes Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 11/13] drm/amd/display: [FW Promotion] Release 0.0.53 Bindu Ramamurthy
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Aric Cyr, Eryk.Brol, Sunpeng.Li, Harry.Wentland, Qingqing.Zhuo,
	Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai,
	Bhawanpreet.Lakha, bindu.r

From: Aric Cyr <aric.cyr@amd.com>

[Why]
No reason to have uninitialized var at top of function

[How]
Move it to minimum scope where it's actuallty used

Signed-off-by: Aric Cyr <aric.cyr@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 4df26a67e570..6a1e758eaa77 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -2348,7 +2348,6 @@ static void commit_planes_do_stream_update(struct dc *dc,
 		struct dc_state *context)
 {
 	int j;
-	bool should_program_abm;
 
 	// Stream updates
 	for (j = 0; j < dc->res_pool->pipe_count; j++) {
@@ -2424,7 +2423,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
 			}
 
 			if (stream_update->abm_level && pipe_ctx->stream_res.abm) {
-				should_program_abm = true;
+				bool should_program_abm = true;
 
 				// if otg funcs defined check if blanked before programming
 				if (pipe_ctx->stream_res.tg->funcs->is_blanked)
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 11/13] drm/amd/display: [FW Promotion] Release 0.0.53
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
                   ` (9 preceding siblings ...)
  2021-02-19 22:16 ` [PATCH 10/13] drm/amd/display: reduce scope for local var Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 12/13] drm/amd/display: 3.2.124 Bindu Ramamurthy
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Anthony Koo, Eryk.Brol, Sunpeng.Li, Harry.Wentland,
	Qingqing.Zhuo, Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai,
	Bhawanpreet.Lakha, bindu.r

From: Anthony Koo <Anthony.Koo@amd.com>

Signed-off-by: Anthony Koo <Anthony.Koo@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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 85d6a4849d3a..63111351d1e3 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -47,10 +47,10 @@
 
 /* Firmware versioning. */
 #ifdef DMUB_EXPOSE_VERSION
-#define DMUB_FW_VERSION_GIT_HASH 0xb959929e3
+#define DMUB_FW_VERSION_GIT_HASH 0x3ac600697
 #define DMUB_FW_VERSION_MAJOR 0
 #define DMUB_FW_VERSION_MINOR 0
-#define DMUB_FW_VERSION_REVISION 52
+#define DMUB_FW_VERSION_REVISION 53
 #define DMUB_FW_VERSION_TEST 0
 #define DMUB_FW_VERSION_VBIOS 0
 #define DMUB_FW_VERSION_HOTFIX 0
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 12/13] drm/amd/display: 3.2.124
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
                   ` (10 preceding siblings ...)
  2021-02-19 22:16 ` [PATCH 11/13] drm/amd/display: [FW Promotion] Release 0.0.53 Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-19 22:16 ` [PATCH 13/13] drm/amd/display: Fix system hang after multiple hotplugs Bindu Ramamurthy
  2021-02-19 22:29 ` [PATCH 00/13] DC Patches FEB 22, 2021 Wheeler, Daniel
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Aric Cyr, Eryk.Brol, Sunpeng.Li, Harry.Wentland, Qingqing.Zhuo,
	Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai,
	Bhawanpreet.Lakha, bindu.r

From: Aric Cyr <aric.cyr@amd.com>

Signed-off-by: Aric Cyr <aric.cyr@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 drivers/gpu/drm/amd/display/dc/dc.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 9e631980fa1b..bd1cb665a585 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.123"
+#define DC_VER "3.2.124"
 
 #define MAX_SURFACES 3
 #define MAX_PLANES 6
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 13/13] drm/amd/display: Fix system hang after multiple hotplugs
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
                   ` (11 preceding siblings ...)
  2021-02-19 22:16 ` [PATCH 12/13] drm/amd/display: 3.2.124 Bindu Ramamurthy
@ 2021-02-19 22:16 ` Bindu Ramamurthy
  2021-02-19 22:29 ` [PATCH 00/13] DC Patches FEB 22, 2021 Wheeler, Daniel
  13 siblings, 0 replies; 19+ messages in thread
From: Bindu Ramamurthy @ 2021-02-19 22:16 UTC (permalink / raw)
  To: amd-gfx
  Cc: Eryk.Brol, Sunpeng.Li, Harry.Wentland, Qingqing Zhuo,
	Rodrigo.Siqueira, Anson.Jacob, Aurabindo.Pillai,
	Bhawanpreet.Lakha, bindu.r

From: Qingqing Zhuo <qingqing.zhuo@amd.com>

[Why]
mutex_lock() was introduced in dm_disable_vblank(), which could
be called in an IRQ context. Waiting in IRQ would cause issues
like kernel lockup, etc.

[How]
Handle code that requires mutex lock on a different thread.

Signed-off-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 80 +++++++++++++++----
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 27 +++++++
 2 files changed, 92 insertions(+), 15 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 0970d9c14889..223bbb34f1a0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -938,7 +938,49 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
 
 }
 #endif
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+static void event_mall_stutter(struct work_struct *work)
+{
+
+	struct vblank_workqueue *vblank_work = container_of(work, struct vblank_workqueue, mall_work);
+	struct amdgpu_display_manager *dm = vblank_work->dm;
+
+	mutex_lock(&dm->dc_lock);
+
+	if (vblank_work->enable)
+		dm->active_vblank_irq_count++;
+	else
+		dm->active_vblank_irq_count--;
+
+
+	dc_allow_idle_optimizations(
+		dm->dc, dm->active_vblank_irq_count == 0 ? true : false);
+
+	DRM_DEBUG_DRIVER("Allow idle optimizations (MALL): %d\n", dm->active_vblank_irq_count == 0);
+
+
+	mutex_unlock(&dm->dc_lock);
+}
+
+static struct vblank_workqueue *vblank_create_workqueue(struct amdgpu_device *adev, struct dc *dc)
+{
+
+	int max_caps = dc->caps.max_links;
+	struct vblank_workqueue *vblank_work;
+	int i = 0;
+
+	vblank_work = kcalloc(max_caps, sizeof(*vblank_work), GFP_KERNEL);
+	if (ZERO_OR_NULL_PTR(vblank_work)) {
+		kfree(vblank_work);
+		return NULL;
+	}
+
+	for (i = 0; i < max_caps; i++)
+		INIT_WORK(&vblank_work[i].mall_work, event_mall_stutter);
 
+	return vblank_work;
+}
+#endif
 static int amdgpu_dm_init(struct amdgpu_device *adev)
 {
 	struct dc_init_data init_data;
@@ -958,6 +1000,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
 
 	mutex_init(&adev->dm.dc_lock);
 	mutex_init(&adev->dm.audio_lock);
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+	spin_lock_init(&adev->dm.vblank_lock);
+#endif
 
 	if(amdgpu_dm_irq_init(adev)) {
 		DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
@@ -1072,6 +1117,17 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
 
 	amdgpu_dm_init_color_mod();
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+	if (adev->dm.dc->caps.max_links > 0) {
+		adev->dm.vblank_workqueue = vblank_create_workqueue(adev, adev->dm.dc);
+
+		if (!adev->dm.vblank_workqueue)
+			DRM_ERROR("amdgpu: failed to initialize vblank_workqueue.\n");
+		else
+			DRM_DEBUG_DRIVER("amdgpu: vblank_workqueue init done %p.\n", adev->dm.vblank_workqueue);
+	}
+#endif
+
 #ifdef CONFIG_DRM_AMD_DC_HDCP
 	if (adev->dm.dc->caps.max_links > 0 && adev->asic_type >= CHIP_RAVEN) {
 		adev->dm.hdcp_workqueue = hdcp_create_workqueue(adev, &init_params.cp_psp, adev->dm.dc);
@@ -5449,6 +5505,9 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
 	struct amdgpu_device *adev = drm_to_adev(crtc->dev);
 	struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
 	struct amdgpu_display_manager *dm = &adev->dm;
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+	unsigned long flags;
+#endif
 	int rc = 0;
 
 	if (enable) {
@@ -5472,21 +5531,12 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
 	if (amdgpu_in_reset(adev))
 		return 0;
 
-	mutex_lock(&dm->dc_lock);
-
-	if (enable)
-		dm->active_vblank_irq_count++;
-	else
-		dm->active_vblank_irq_count--;
-
-#if defined(CONFIG_DRM_AMD_DC_DCN)
-	dc_allow_idle_optimizations(
-		adev->dm.dc, dm->active_vblank_irq_count == 0 ? true : false);
-
-	DRM_DEBUG_DRIVER("Allow idle optimizations (MALL): %d\n", dm->active_vblank_irq_count == 0);
-#endif
-
-	mutex_unlock(&dm->dc_lock);
+	spin_lock_irqsave(&dm->vblank_lock, flags);
+	dm->vblank_workqueue->dm = dm;
+	dm->vblank_workqueue->otg_inst = acrtc->otg_inst;
+	dm->vblank_workqueue->enable = enable;
+	spin_unlock_irqrestore(&dm->vblank_lock, flags);
+	schedule_work(&dm->vblank_workqueue->mall_work);
 
 #endif
 	return 0;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 5f9950fd216c..b0d137998169 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -92,6 +92,20 @@ struct dm_compressor_info {
 	uint64_t gpu_addr;
 };
 
+/**
+ * struct vblank_workqueue - Works to be executed in a separate thread during vblank
+ * @mall_work: work for mall stutter
+ * @dm: amdgpu display manager device
+ * @otg_inst: otg instance of which vblank is being set
+ * @enable: true if enable vblank
+ */
+struct vblank_workqueue {
+	struct work_struct mall_work;
+	struct amdgpu_display_manager *dm;
+	int otg_inst;
+	bool enable;
+};
+
 /**
  * struct amdgpu_dm_backlight_caps - Information about backlight
  *
@@ -243,6 +257,15 @@ struct amdgpu_display_manager {
 	 */
 	struct mutex audio_lock;
 
+	/**
+	 * @vblank_work_lock:
+	 *
+	 * Guards access to deferred vblank work state.
+	 */
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+	spinlock_t vblank_lock;
+#endif
+
 	/**
 	 * @audio_component:
 	 *
@@ -321,6 +344,10 @@ struct amdgpu_display_manager {
 	struct hdcp_workqueue *hdcp_workqueue;
 #endif
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+	struct vblank_workqueue *vblank_workqueue;
+#endif
+
 	struct drm_atomic_state *cached_state;
 	struct dc_state *cached_dc_state;
 
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* RE: [PATCH 00/13] DC Patches FEB 22, 2021
  2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
                   ` (12 preceding siblings ...)
  2021-02-19 22:16 ` [PATCH 13/13] drm/amd/display: Fix system hang after multiple hotplugs Bindu Ramamurthy
@ 2021-02-19 22:29 ` Wheeler, Daniel
  13 siblings, 0 replies; 19+ messages in thread
From: Wheeler, Daniel @ 2021-02-19 22:29 UTC (permalink / raw)
  To: R, Bindu, amd-gfx
  Cc: Brol, Eryk, Li, Sun peng (Leo),
	Lakha, Bhawanpreet, Zhuo,  Qingqing, Siqueira, Rodrigo, Jacob,
	Anson, Pillai, Aurabindo, Wentland, Harry, R, Bindu

[AMD Public Use]

Hi all,

This week this patchset was tested on a HP Envy 360, with Ryzen 5 4500U, on the following display types (via usb-c to dp/dvi/hdmi/vga):
4k 60z, 1440p 144hz, 1680*1050 60hz, internal eDP 1080p 60hz

Tested on a Reference AMD RX6800 on the following display types (via DP):
4k60 60hz, 1440p 144hz, 1680x1050 60hz.

Also using a MST hub at 2x 4k 30hz on both systems.


Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>

Thank you,

Dan Wheeler
Technologist  |  AMD
SW Display
O +(1) 905-882-2600 ext. 74665
------------------------------------------------------------------------------------------------------------------
1 Commerce Valley Dr E, Thornhill, ON L3T 7X6
Facebook |  Twitter |  amd.com  


-----Original Message-----
From: amd-gfx <amd-gfx-bounces@lists.freedesktop.org> On Behalf Of Bindu Ramamurthy
Sent: February 19, 2021 5:16 PM
To: amd-gfx@lists.freedesktop.org
Cc: 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>; R, Bindu <Bindu.R@amd.com>
Subject: [PATCH 00/13] DC Patches FEB 22, 2021


This DC patchset brings improvements in multiple areas. In summary, we highlight:
* Firmware release 0.0.53.
* Addition of interrupts for DCN2.1
* Refractor debugfs entries for connectors.
* Enable display audio when seamless booting with an external monitor over DP.
* Fixes for System hang after multiple hotplug, timing synchronization for displays, disable seamless boot for DP.


Anthony Koo (1):
  drm/amd/display: [FW Promotion] Release 0.0.53

Anthony Wang (2):
  drm/amd/display: disable seamless boot for DP MST
  drm/amd/display: enable audio on DP seamless boot

Aric Cyr (3):
  drm/amd/display: Don't optimize bandwidth before disabling planes
  drm/amd/display: reduce scope for local var

  drm/amd/display: 3.2.124
       This version brings along following fixes:
       - Fix system hang after multiple hotplug.
       - Don't optimize bandwidth before disabling planes.
       - Report timing synchronizable when DP streams time frame difference is less than 0.05 percent.
       - move trace buffer to uncached memory.
       - enable audio on DP seamless boot. 
       - Disable seamless boot for DP MST.


Eric Bernstein (1):
  drm/amd/display: Remove Assert from dcn10_get_dig_frontend

Eryk Brol (1):
  drm/amd/display: Check for DSC support instead of ASIC revision

Qingqing Zhuo (1):
  drm/amd/display: Fix system hang after multiple hotplugs

Rodrigo Siqueira (1):
  drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1

Stylon Wang (1):
  drm/amd/display: Refactor debugfs entries for all connectors

Vladimir Stempen (1):
  drm/amd/display: Synchronize displays with different timings

Yongqiang Sun (1):
  drm/amd/display: move trace buffer to uncached memory.

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  82 +++++--  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  27 +++  .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c |  22 +-
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  39 ++-
 drivers/gpu/drm/amd/display/dc/core/dc_link.c |  10 +  .../gpu/drm/amd/display/dc/core/dc_resource.c |  43 ++++
 drivers/gpu/drm/amd/display/dc/dc.h           |   5 +-
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |   1 +
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |   3 +
 .../drm/amd/display/dc/dce/dce_clock_source.c |  52 +++-  .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 225 ++++++++++++++++++
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.h |   5 +
 .../amd/display/dc/dcn10/dcn10_link_encoder.c |   1 -
 .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h |   2 +
 .../display/dc/dcn10/dcn10_stream_encoder.c   |   1 -
 .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c |   1 +
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 123 ++++++++++
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   8 +-
 .../dc/dcn30/dcn30_dio_stream_encoder.c       |   1 -
 .../drm/amd/display/dc/dcn30/dcn30_hwseq.c    |   2 +
 .../gpu/drm/amd/display/dc/inc/clock_source.h |   5 +
 .../amd/display/dc/inc/hw/timing_generator.h  |  12 +
 .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |   3 +
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   4 +
 .../display/dc/irq/dcn21/irq_service_dcn21.c  |  22 ++
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   |   4 +-
 .../gpu/drm/amd/display/dmub/src/dmub_dcn20.c |   7 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn20.h |   7 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn30.c |   7 +
 29 files changed, 676 insertions(+), 48 deletions(-)

--
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfx&amp;data=04%7C01%7Cdaniel.wheeler%40amd.com%7Cc87256f9100c4509f11508d8d5240403%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637493697957037816%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=ITJMWXnsrp%2FG8PAsy%2FxjOftNx6IXuHDhVvnGuwC6dJk%3D&amp;reserved=0
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 08/13] drm/amd/display: Synchronize displays with different timings
  2021-02-19 22:16 ` [PATCH 08/13] drm/amd/display: Synchronize displays with different timings Bindu Ramamurthy
@ 2021-02-21  6:21   ` Nils Wallménius
  2021-02-22 13:43     ` R, Bindu
  0 siblings, 1 reply; 19+ messages in thread
From: Nils Wallménius @ 2021-02-21  6:21 UTC (permalink / raw)
  To: Bindu Ramamurthy
  Cc: Eryk.Brol, Sunpeng.Li, Bhawanpreet.Lakha, Qingqing.Zhuo,
	Rodrigo.Siqueira, amd-gfx, Anson.Jacob, Vladimir Stempen,
	Aurabindo.Pillai, Harry.Wentland


[-- Attachment #1.1: Type: text/plain, Size: 15279 bytes --]

Hi Bindu, an inline comment below.

Den fre 19 feb. 2021 23:16Bindu Ramamurthy <bindu.r@amd.com> skrev:

> From: Vladimir Stempen <vladimir.stempen@amd.com>
>
> [why]
>  Vendor based fan noise improvement
>
> [how]
> Report timing synchronizable when DP streams time frame
> difference is less than 0.05 percent. Adjust DP  DTOs and
> sync displays using  MASTER_UPDATE_LOCK_DB_X_Y
>
> Signed-off-by: Vladimir Stempen <vladimir.stempen@amd.com>
> Acked-by: Bindu Ramamurthy <bindu.r@amd.com>
> ---
>  drivers/gpu/drm/amd/display/dc/core/dc.c      |  28 ++-
>  .../gpu/drm/amd/display/dc/core/dc_resource.c |  43 ++++
>  drivers/gpu/drm/amd/display/dc/dc.h           |   3 +
>  drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |   1 +
>  drivers/gpu/drm/amd/display/dc/dc_stream.h    |   3 +
>  .../drm/amd/display/dc/dce/dce_clock_source.c |  52 +++-
>  .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 225 ++++++++++++++++++
>  .../amd/display/dc/dcn10/dcn10_hw_sequencer.h |   5 +
>  .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h |   2 +
>  .../display/dc/dcn10/dcn10_stream_encoder.c   |   1 -
>  .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c |   1 +
>  .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 123 ++++++++++
>  .../drm/amd/display/dc/dcn20/dcn20_resource.c |   8 +-
>  .../dc/dcn30/dcn30_dio_stream_encoder.c       |   1 -
>  .../gpu/drm/amd/display/dc/inc/clock_source.h |   5 +
>  .../amd/display/dc/inc/hw/timing_generator.h  |  12 +
>  .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |   3 +
>  drivers/gpu/drm/amd/display/dc/inc/resource.h |   4 +
>  18 files changed, 505 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c
> b/drivers/gpu/drm/amd/display/dc/core/dc.c
> index 2f56fa2c0bf4..39df5d2c0108 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
> @@ -1102,6 +1102,7 @@ static void program_timing_sync(
>
>         for (i = 0; i < pipe_count; i++) {
>                 int group_size = 1;
> +               enum timing_synchronization_type sync_type =
> NOT_SYNCHRONIZABLE;
>                 struct pipe_ctx *pipe_set[MAX_PIPES];
>
>                 if (!unsynced_pipes[i])
> @@ -1116,10 +1117,22 @@ static void program_timing_sync(
>                 for (j = i + 1; j < pipe_count; j++) {
>                         if (!unsynced_pipes[j])
>                                 continue;
> -
> -                       if (resource_are_streams_timing_synchronizable(
> +                       if (sync_type != TIMING_SYNCHRONIZABLE &&
> +                               dc->hwss.enable_vblanks_synchronization &&
> +
>  unsynced_pipes[j]->stream_res.tg->funcs->align_vblanks &&
> +                               resource_are_vblanks_synchronizable(
> +                                       unsynced_pipes[j]->stream,
> +                                       pipe_set[0]->stream)) {
> +                               sync_type = VBLANK_SYNCHRONIZABLE;
> +                               pipe_set[group_size] = unsynced_pipes[j];
> +                               unsynced_pipes[j] = NULL;
> +                               group_size++;
> +                       } else
> +                       if (sync_type != VBLANK_SYNCHRONIZABLE &&
> +                               resource_are_streams_timing_synchronizable(
>                                         unsynced_pipes[j]->stream,
>                                         pipe_set[0]->stream)) {
> +                               sync_type = TIMING_SYNCHRONIZABLE;
>                                 pipe_set[group_size] = unsynced_pipes[j];
>                                 unsynced_pipes[j] = NULL;
>                                 group_size++;
> @@ -1145,7 +1158,6 @@ static void program_timing_sync(
>                         }
>                 }
>
> -
>                 for (k = 0; k < group_size; k++) {
>                         struct dc_stream_status *status =
> dc_stream_get_status_from_state(ctx, pipe_set[k]->stream);
>
> @@ -1175,8 +1187,14 @@ static void program_timing_sync(
>                 }
>
>                 if (group_size > 1) {
> -                       dc->hwss.enable_timing_synchronization(
> -                               dc, group_index, group_size, pipe_set);
> +                       if (sync_type == TIMING_SYNCHRONIZABLE) {
> +                               dc->hwss.enable_timing_synchronization(
> +                                       dc, group_index, group_size,
> pipe_set);
> +                       } else
> +                               if (sync_type == VBLANK_SYNCHRONIZABLE) {
> +                               dc->hwss.enable_vblanks_synchronization(
> +                                       dc, group_index, group_size,
> pipe_set);
> +                               }
>                         group_index++;
>                 }
>                 num_group++;
> 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 0c26c2ade782..0241c9d96d7a 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
> @@ -417,6 +417,49 @@ int resource_get_clock_source_reference(
>         return -1;
>  }
>
> +bool resource_are_vblanks_synchronizable(
> +       struct dc_stream_state *stream1,
> +       struct dc_stream_state *stream2)
> +{
> +       uint32_t base60_refresh_rates[] = {10, 20, 5};
> +       uint8_t i;
> +       uint8_t rr_count =
> sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]);
> +       int64_t frame_time_diff;
> +
> +       if (stream1->ctx->dc->config.vblank_alignment_dto_params &&
> +
>  stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 &&
> +               dc_is_dp_signal(stream1->signal) &&
> +               dc_is_dp_signal(stream2->signal) &&
> +               false == stream1->has_non_synchronizable_pclk &&
> +               false == stream2->has_non_synchronizable_pclk &&
> +               stream1->timing.flags.VBLANK_SYNCHRONIZABLE &&
> +               stream2->timing.flags.VBLANK_SYNCHRONIZABLE) {
> +               /* disable refresh rates higher than 60Hz for now */
> +               if
> (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/
> +                               stream1->timing.v_total > 60)
> +                       return false;
> +               if
> (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/
> +                               stream2->timing.v_total > 60)
> +                       return false;
> +               frame_time_diff = (int64_t)10000 *
> +                       stream1->timing.h_total *
> +                       stream1->timing.v_total *
> +                       stream2->timing.pix_clk_100hz /
> +                       stream1->timing.pix_clk_100hz /
> +                       stream2->timing.h_total /
> +                       stream2->timing.v_total;
> +               for (i = 0; i < rr_count; i++) {
> +                       int64_t diff = (frame_time_diff *
> base60_refresh_rates[i]) / 10 - 10000;
> +
> +                       if (diff < 0)
> +                               diff = -diff;
> +                       if (diff <
> stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff)
> +                               return true;
> +               }
> +       }
> +       return false;
> +}
> +
>  bool resource_are_streams_timing_synchronizable(
>         struct dc_stream_state *stream1,
>         struct dc_stream_state *stream2)
> diff --git a/drivers/gpu/drm/amd/display/dc/dc.h
> b/drivers/gpu/drm/amd/display/dc/dc.h
> index a10daf6655f9..9e631980fa1b 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc.h
> @@ -301,6 +301,8 @@ struct dc_config {
>  #if defined(CONFIG_DRM_AMD_DC_DCN)
>         bool clamp_min_dcfclk;
>  #endif
> +       uint64_t vblank_alignment_dto_params;
> +       uint8_t  vblank_alignment_max_frame_time_diff;
>  };
>
>  enum visual_confirm {
> @@ -528,6 +530,7 @@ struct dc_debug_options {
>         bool disable_dsc;
>         bool enable_dram_clock_change_one_display_vactive;
>         union mem_low_power_enable_options enable_mem_low_power;
> +       bool force_vblank_alignment;
>  };
>
>  struct dc_debug_data {
> diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
> b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
> index b41e6367b15e..48d3ed97ead9 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
> @@ -705,6 +705,7 @@ struct dc_crtc_timing_flags {
>  #ifndef TRIM_FSFT
>         uint32_t FAST_TRANSPORT: 1;
>  #endif
> +       uint32_t VBLANK_SYNCHRONIZABLE: 1;
>  };
>
>  enum dc_timing_3d_format {
> diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h
> b/drivers/gpu/drm/amd/display/dc/dc_stream.h
> index e243c01b9672..7fa998f97e7a 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
> @@ -228,6 +228,9 @@ struct dc_stream_state {
>         uint32_t stream_id;
>         bool is_dsc_enabled;
>         union stream_update_flags update_flags;
> +
> +       bool has_non_synchronizable_pclk;
> +       bool vblank_synchronized;
>  };
>
>  #define ABM_LEVEL_IMMEDIATE_DISABLE 255
> 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
> index dec58b3c42e4..6f47f9bab5ee 100644
> --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
> +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
> @@ -1002,15 +1002,27 @@ static bool get_pixel_clk_frequency_100hz(
>  {
>         struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
>         unsigned int clock_hz = 0;
> +       unsigned int modulo_hz = 0;
>
>         if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) {
>                 clock_hz = REG_READ(PHASE[inst]);
>
> -               /* NOTE: There is agreement with VBIOS here that MODULO is
> -                * programmed equal to DPREFCLK, in which case PHASE will
> be
> -                * equivalent to pixel clock.
> -                */
> -               *pixel_clk_khz = clock_hz / 100;
> +               if
> (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&
> +
>  clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {
> +                       /* NOTE: In case VBLANK syncronization is enabled,
> MODULO may
> +                        * not be programmed equal to DPREFCLK
> +                        */
> +                       modulo_hz = REG_READ(MODULO[inst]);
> +                       *pixel_clk_khz = ((uint64_t)clock_hz*
> +
>  clock_source->ctx->dc->clk_mgr->dprefclk_khz*10)/
> +                               modulo_hz;
> +               } else {
> +                       /* NOTE: There is agreement with VBIOS here that
> MODULO is
> +                        * programmed equal to DPREFCLK, in which case
> PHASE will be
> +                        * equivalent to pixel clock.
> +                        */
> +                       *pixel_clk_khz = clock_hz / 100;
> +               }
>                 return true;
>         }
>
> @@ -1074,8 +1086,35 @@ static bool dcn20_program_pix_clk(
>                 struct pixel_clk_params *pix_clk_params,
>                 struct pll_settings *pll_settings)
>  {
> +       struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
> +       unsigned int inst = pix_clk_params->controller_id -
> CONTROLLER_ID_D0;
> +
>         dce112_program_pix_clk(clock_source, pix_clk_params, pll_settings);
>
> +       if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&
> +
>  clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {
> +               /* NOTE: In case VBLANK syncronization is enabled,
> +                * we need to set modulo to default DPREFCLK first
> +                * dce112_program_pix_clk does not set default DPREFCLK
> +                */
> +               REG_WRITE(MODULO[inst],
> +                       clock_source->ctx->dc->clk_mgr->dprefclk_khz*1000);
> +       }
> +       return true;
> +}
> +
> +static bool dcn20_override_dp_pix_clk(
> +               struct clock_source *clock_source,
> +               unsigned int inst,
> +               unsigned int pixel_clk,
> +               unsigned int ref_clk)
> +{
> +       struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
> +
> +       REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 0);
> +       REG_WRITE(PHASE[inst], pixel_clk);
> +       REG_WRITE(MODULO[inst], ref_clk);
> +       REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1);
>         return true;
>  }
>
> @@ -1083,7 +1122,8 @@ static const struct clock_source_funcs
> dcn20_clk_src_funcs = {
>         .cs_power_down = dce110_clock_source_power_down,
>         .program_pix_clk = dcn20_program_pix_clk,
>         .get_pix_clk_dividers = dce112_get_pix_clk_dividers,
> -       .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
> +       .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz,
> +       .override_dp_pix_clk = dcn20_override_dp_pix_clk
>  };
>
>  #if defined(CONFIG_DRM_AMD_DC_DCN)
> 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 89912bb5014f..669cee48b0b5 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
> @@ -1851,6 +1851,225 @@ static bool wait_for_reset_trigger_to_occur(
>         return rc;
>  }
>
> +uint64_t reduceSizeAndFraction(
> +       uint64_t *numerator,
> +       uint64_t *denominator,
> +       bool checkUint32Bounary)
> +{
> +       int i;
> +       bool ret = checkUint32Bounary == false;
> +       uint64_t max_int32 = 0xffffffff;
> +       uint64_t num, denom;
> +       uint16_t prime_numbers[] = {
> +               2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
> +               47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
> +               107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
> +               167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
> +               229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
> +               283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353,
> +               359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421,
> +               431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487,
> +               491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,
> +               571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631,
> +               641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
> +               709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773,
> +               787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857,
> +               859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
> +               941, 947, 953, 967, 971, 977, 983, 991, 997};
> +       int count = ARRAY_SIZE(prime_numbers)/sizeof(prime_numbers[0]);
>

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".

BR
Nils

[-- Attachment #1.2: Type: text/html, Size: 18990 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 08/13] drm/amd/display: Synchronize displays with different timings
  2021-02-21  6:21   ` Nils Wallménius
@ 2021-02-22 13:43     ` R, Bindu
  2021-02-22 18:04       ` R, Bindu
  0 siblings, 1 reply; 19+ messages in thread
From: R, Bindu @ 2021-02-22 13:43 UTC (permalink / raw)
  To: Nils Wallménius
  Cc: Brol, Eryk, Li, Sun peng (Leo),
	Lakha, Bhawanpreet, Zhuo, Qingqing, Siqueira, Rodrigo, amd-gfx,
	Jacob, Anson, Stempen,  Vladimir, Pillai, Aurabindo, Wentland,
	Harry


[-- Attachment #1.1: Type: text/plain, Size: 16283 bytes --]

[AMD Official Use Only - Internal Distribution Only]

Hi Nils,?
   ?Thanks for the inputs.

@ Stempen, Vladimir<mailto:Vladimir.Stempen@amd.com>,
      ? As the array 'prime_numbers' has constant values defined, we can mark this as static const. Would you like to change the count calculation -or- retain the same limit iteration ? All the patches would be merged to upstream by today. please suggest.

Thanks,
Bindu
________________________________
From: Nils Wallménius <nils.wallmenius@gmail.com>
Sent: Sunday, February 21, 2021 1:21 AM
To: R, Bindu <Bindu.R@amd.com>
Cc: 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>
Subject: Re: [PATCH 08/13] drm/amd/display: Synchronize displays with different timings

Hi Bindu, an inline comment below.

Den fre 19 feb. 2021 23:16Bindu Ramamurthy <bindu.r@amd.com<mailto:bindu.r@amd.com>> skrev:
From: Vladimir Stempen <vladimir.stempen@amd.com<mailto:vladimir.stempen@amd.com>>

[why]
 Vendor based fan noise improvement

[how]
Report timing synchronizable when DP streams time frame
difference is less than 0.05 percent. Adjust DP  DTOs and
sync displays using  MASTER_UPDATE_LOCK_DB_X_Y

Signed-off-by: Vladimir Stempen <vladimir.stempen@amd.com<mailto:vladimir.stempen@amd.com>>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com<mailto:bindu.r@amd.com>>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  28 ++-
 .../gpu/drm/amd/display/dc/core/dc_resource.c |  43 ++++
 drivers/gpu/drm/amd/display/dc/dc.h           |   3 +
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |   1 +
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |   3 +
 .../drm/amd/display/dc/dce/dce_clock_source.c |  52 +++-
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 225 ++++++++++++++++++
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.h |   5 +
 .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h |   2 +
 .../display/dc/dcn10/dcn10_stream_encoder.c   |   1 -
 .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c |   1 +
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 123 ++++++++++
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   8 +-
 .../dc/dcn30/dcn30_dio_stream_encoder.c       |   1 -
 .../gpu/drm/amd/display/dc/inc/clock_source.h |   5 +
 .../amd/display/dc/inc/hw/timing_generator.h  |  12 +
 .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |   3 +
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   4 +
 18 files changed, 505 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 2f56fa2c0bf4..39df5d2c0108 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1102,6 +1102,7 @@ static void program_timing_sync(

        for (i = 0; i < pipe_count; i++) {
                int group_size = 1;
+               enum timing_synchronization_type sync_type = NOT_SYNCHRONIZABLE;
                struct pipe_ctx *pipe_set[MAX_PIPES];

                if (!unsynced_pipes[i])
@@ -1116,10 +1117,22 @@ static void program_timing_sync(
                for (j = i + 1; j < pipe_count; j++) {
                        if (!unsynced_pipes[j])
                                continue;
-
-                       if (resource_are_streams_timing_synchronizable(
+                       if (sync_type != TIMING_SYNCHRONIZABLE &&
+                               dc->hwss.enable_vblanks_synchronization &&
+                               unsynced_pipes[j]->stream_res.tg->funcs->align_vblanks &&
+                               resource_are_vblanks_synchronizable(
+                                       unsynced_pipes[j]->stream,
+                                       pipe_set[0]->stream)) {
+                               sync_type = VBLANK_SYNCHRONIZABLE;
+                               pipe_set[group_size] = unsynced_pipes[j];
+                               unsynced_pipes[j] = NULL;
+                               group_size++;
+                       } else
+                       if (sync_type != VBLANK_SYNCHRONIZABLE &&
+                               resource_are_streams_timing_synchronizable(
                                        unsynced_pipes[j]->stream,
                                        pipe_set[0]->stream)) {
+                               sync_type = TIMING_SYNCHRONIZABLE;
                                pipe_set[group_size] = unsynced_pipes[j];
                                unsynced_pipes[j] = NULL;
                                group_size++;
@@ -1145,7 +1158,6 @@ static void program_timing_sync(
                        }
                }

-
                for (k = 0; k < group_size; k++) {
                        struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream);

@@ -1175,8 +1187,14 @@ static void program_timing_sync(
                }

                if (group_size > 1) {
-                       dc->hwss.enable_timing_synchronization(
-                               dc, group_index, group_size, pipe_set);
+                       if (sync_type == TIMING_SYNCHRONIZABLE) {
+                               dc->hwss.enable_timing_synchronization(
+                                       dc, group_index, group_size, pipe_set);
+                       } else
+                               if (sync_type == VBLANK_SYNCHRONIZABLE) {
+                               dc->hwss.enable_vblanks_synchronization(
+                                       dc, group_index, group_size, pipe_set);
+                               }
                        group_index++;
                }
                num_group++;
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 0c26c2ade782..0241c9d96d7a 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -417,6 +417,49 @@ int resource_get_clock_source_reference(
        return -1;
 }

+bool resource_are_vblanks_synchronizable(
+       struct dc_stream_state *stream1,
+       struct dc_stream_state *stream2)
+{
+       uint32_t base60_refresh_rates[] = {10, 20, 5};
+       uint8_t i;
+       uint8_t rr_count = sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]);
+       int64_t frame_time_diff;
+
+       if (stream1->ctx->dc->config.vblank_alignment_dto_params &&
+               stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 &&
+               dc_is_dp_signal(stream1->signal) &&
+               dc_is_dp_signal(stream2->signal) &&
+               false == stream1->has_non_synchronizable_pclk &&
+               false == stream2->has_non_synchronizable_pclk &&
+               stream1->timing.flags.VBLANK_SYNCHRONIZABLE &&
+               stream2->timing.flags.VBLANK_SYNCHRONIZABLE) {
+               /* disable refresh rates higher than 60Hz for now */
+               if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/
+                               stream1->timing.v_total > 60)
+                       return false;
+               if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/
+                               stream2->timing.v_total > 60)
+                       return false;
+               frame_time_diff = (int64_t)10000 *
+                       stream1->timing.h_total *
+                       stream1->timing.v_total *
+                       stream2->timing.pix_clk_100hz /
+                       stream1->timing.pix_clk_100hz /
+                       stream2->timing.h_total /
+                       stream2->timing.v_total;
+               for (i = 0; i < rr_count; i++) {
+                       int64_t diff = (frame_time_diff * base60_refresh_rates[i]) / 10 - 10000;
+
+                       if (diff < 0)
+                               diff = -diff;
+                       if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff)
+                               return true;
+               }
+       }
+       return false;
+}
+
 bool resource_are_streams_timing_synchronizable(
        struct dc_stream_state *stream1,
        struct dc_stream_state *stream2)
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index a10daf6655f9..9e631980fa1b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -301,6 +301,8 @@ struct dc_config {
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        bool clamp_min_dcfclk;
 #endif
+       uint64_t vblank_alignment_dto_params;
+       uint8_t  vblank_alignment_max_frame_time_diff;
 };

 enum visual_confirm {
@@ -528,6 +530,7 @@ struct dc_debug_options {
        bool disable_dsc;
        bool enable_dram_clock_change_one_display_vactive;
        union mem_low_power_enable_options enable_mem_low_power;
+       bool force_vblank_alignment;
 };

 struct dc_debug_data {
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index b41e6367b15e..48d3ed97ead9 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -705,6 +705,7 @@ struct dc_crtc_timing_flags {
 #ifndef TRIM_FSFT
        uint32_t FAST_TRANSPORT: 1;
 #endif
+       uint32_t VBLANK_SYNCHRONIZABLE: 1;
 };

 enum dc_timing_3d_format {
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index e243c01b9672..7fa998f97e7a 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -228,6 +228,9 @@ struct dc_stream_state {
        uint32_t stream_id;
        bool is_dsc_enabled;
        union stream_update_flags update_flags;
+
+       bool has_non_synchronizable_pclk;
+       bool vblank_synchronized;
 };

 #define ABM_LEVEL_IMMEDIATE_DISABLE 255
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
index dec58b3c42e4..6f47f9bab5ee 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -1002,15 +1002,27 @@ static bool get_pixel_clk_frequency_100hz(
 {
        struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
        unsigned int clock_hz = 0;
+       unsigned int modulo_hz = 0;

        if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) {
                clock_hz = REG_READ(PHASE[inst]);

-               /* NOTE: There is agreement with VBIOS here that MODULO is
-                * programmed equal to DPREFCLK, in which case PHASE will be
-                * equivalent to pixel clock.
-                */
-               *pixel_clk_khz = clock_hz / 100;
+               if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&
+                       clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {
+                       /* NOTE: In case VBLANK syncronization is enabled, MODULO may
+                        * not be programmed equal to DPREFCLK
+                        */
+                       modulo_hz = REG_READ(MODULO[inst]);
+                       *pixel_clk_khz = ((uint64_t)clock_hz*
+                               clock_source->ctx->dc->clk_mgr->dprefclk_khz*10)/
+                               modulo_hz;
+               } else {
+                       /* NOTE: There is agreement with VBIOS here that MODULO is
+                        * programmed equal to DPREFCLK, in which case PHASE will be
+                        * equivalent to pixel clock.
+                        */
+                       *pixel_clk_khz = clock_hz / 100;
+               }
                return true;
        }

@@ -1074,8 +1086,35 @@ static bool dcn20_program_pix_clk(
                struct pixel_clk_params *pix_clk_params,
                struct pll_settings *pll_settings)
 {
+       struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
+       unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
+
        dce112_program_pix_clk(clock_source, pix_clk_params, pll_settings);

+       if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&
+                       clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {
+               /* NOTE: In case VBLANK syncronization is enabled,
+                * we need to set modulo to default DPREFCLK first
+                * dce112_program_pix_clk does not set default DPREFCLK
+                */
+               REG_WRITE(MODULO[inst],
+                       clock_source->ctx->dc->clk_mgr->dprefclk_khz*1000);
+       }
+       return true;
+}
+
+static bool dcn20_override_dp_pix_clk(
+               struct clock_source *clock_source,
+               unsigned int inst,
+               unsigned int pixel_clk,
+               unsigned int ref_clk)
+{
+       struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
+
+       REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 0);
+       REG_WRITE(PHASE[inst], pixel_clk);
+       REG_WRITE(MODULO[inst], ref_clk);
+       REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1);
        return true;
 }

@@ -1083,7 +1122,8 @@ static const struct clock_source_funcs dcn20_clk_src_funcs = {
        .cs_power_down = dce110_clock_source_power_down,
        .program_pix_clk = dcn20_program_pix_clk,
        .get_pix_clk_dividers = dce112_get_pix_clk_dividers,
-       .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
+       .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz,
+       .override_dp_pix_clk = dcn20_override_dp_pix_clk
 };

 #if defined(CONFIG_DRM_AMD_DC_DCN)
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 89912bb5014f..669cee48b0b5 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
@@ -1851,6 +1851,225 @@ static bool wait_for_reset_trigger_to_occur(
        return rc;
 }

+uint64_t reduceSizeAndFraction(
+       uint64_t *numerator,
+       uint64_t *denominator,
+       bool checkUint32Bounary)
+{
+       int i;
+       bool ret = checkUint32Bounary == false;
+       uint64_t max_int32 = 0xffffffff;
+       uint64_t num, denom;
+       uint16_t prime_numbers[] = {
+               2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
+               47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
+               107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
+               167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
+               229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
+               283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353,
+               359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421,
+               431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487,
+               491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,
+               571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631,
+               641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
+               709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773,
+               787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857,
+               859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
+               941, 947, 953, 967, 971, 977, 983, 991, 997};
+       int count = ARRAY_SIZE(prime_numbers)/sizeof(prime_numbers[0]);

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".

BR
Nils

[-- Attachment #1.2: Type: text/html, Size: 29527 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 08/13] drm/amd/display: Synchronize displays with different timings
  2021-02-22 13:43     ` R, Bindu
@ 2021-02-22 18:04       ` R, Bindu
  0 siblings, 0 replies; 19+ messages in thread
From: R, Bindu @ 2021-02-22 18:04 UTC (permalink / raw)
  To: Nils Wallménius
  Cc: Brol, Eryk, Li, Sun peng (Leo),
	Lakha, Bhawanpreet, Zhuo, Qingqing, Siqueira, Rodrigo, amd-gfx,
	Jacob, Anson, Stempen,  Vladimir, Pillai, Aurabindo, Wentland,
	Harry


[-- Attachment #1.1: Type: text/plain, Size: 17177 bytes --]

[AMD Official Use Only - Internal Distribution Only]

​Hi Nils,
   We have incorporated the review comments and the updated patch would be applied with this promotion.

 @ Stempen, Vladimir,
     Thanks for your support.

Regards,
Bindu
________________________________
From: R, Bindu <Bindu.R@amd.com>
Sent: Monday, February 22, 2021 8:43 AM
To: Nils Wallménius <nils.wallmenius@gmail.com>
Cc: 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>
Subject: Re: [PATCH 08/13] drm/amd/display: Synchronize displays with different timings

Hi Nils,​
   ​Thanks for the inputs.

@ Stempen, Vladimir<mailto:Vladimir.Stempen@amd.com>,
      ​ As the array 'prime_numbers' has constant values defined, we can mark this as static const. Would you like to change the count calculation -or- retain the same limit iteration ? All the patches would be merged to upstream by today. please suggest.

Thanks,
Bindu
________________________________
From: Nils Wallménius <nils.wallmenius@gmail.com>
Sent: Sunday, February 21, 2021 1:21 AM
To: R, Bindu <Bindu.R@amd.com>
Cc: 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>
Subject: Re: [PATCH 08/13] drm/amd/display: Synchronize displays with different timings

Hi Bindu, an inline comment below.

Den fre 19 feb. 2021 23:16Bindu Ramamurthy <bindu.r@amd.com<mailto:bindu.r@amd.com>> skrev:
From: Vladimir Stempen <vladimir.stempen@amd.com<mailto:vladimir.stempen@amd.com>>

[why]
 Vendor based fan noise improvement

[how]
Report timing synchronizable when DP streams time frame
difference is less than 0.05 percent. Adjust DP  DTOs and
sync displays using  MASTER_UPDATE_LOCK_DB_X_Y

Signed-off-by: Vladimir Stempen <vladimir.stempen@amd.com<mailto:vladimir.stempen@amd.com>>
Acked-by: Bindu Ramamurthy <bindu.r@amd.com<mailto:bindu.r@amd.com>>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  28 ++-
 .../gpu/drm/amd/display/dc/core/dc_resource.c |  43 ++++
 drivers/gpu/drm/amd/display/dc/dc.h           |   3 +
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |   1 +
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |   3 +
 .../drm/amd/display/dc/dce/dce_clock_source.c |  52 +++-
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 225 ++++++++++++++++++
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.h |   5 +
 .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h |   2 +
 .../display/dc/dcn10/dcn10_stream_encoder.c   |   1 -
 .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c |   1 +
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 123 ++++++++++
 .../drm/amd/display/dc/dcn20/dcn20_resource.c |   8 +-
 .../dc/dcn30/dcn30_dio_stream_encoder.c       |   1 -
 .../gpu/drm/amd/display/dc/inc/clock_source.h |   5 +
 .../amd/display/dc/inc/hw/timing_generator.h  |  12 +
 .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |   3 +
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   4 +
 18 files changed, 505 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 2f56fa2c0bf4..39df5d2c0108 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1102,6 +1102,7 @@ static void program_timing_sync(

        for (i = 0; i < pipe_count; i++) {
                int group_size = 1;
+               enum timing_synchronization_type sync_type = NOT_SYNCHRONIZABLE;
                struct pipe_ctx *pipe_set[MAX_PIPES];

                if (!unsynced_pipes[i])
@@ -1116,10 +1117,22 @@ static void program_timing_sync(
                for (j = i + 1; j < pipe_count; j++) {
                        if (!unsynced_pipes[j])
                                continue;
-
-                       if (resource_are_streams_timing_synchronizable(
+                       if (sync_type != TIMING_SYNCHRONIZABLE &&
+                               dc->hwss.enable_vblanks_synchronization &&
+                               unsynced_pipes[j]->stream_res.tg->funcs->align_vblanks &&
+                               resource_are_vblanks_synchronizable(
+                                       unsynced_pipes[j]->stream,
+                                       pipe_set[0]->stream)) {
+                               sync_type = VBLANK_SYNCHRONIZABLE;
+                               pipe_set[group_size] = unsynced_pipes[j];
+                               unsynced_pipes[j] = NULL;
+                               group_size++;
+                       } else
+                       if (sync_type != VBLANK_SYNCHRONIZABLE &&
+                               resource_are_streams_timing_synchronizable(
                                        unsynced_pipes[j]->stream,
                                        pipe_set[0]->stream)) {
+                               sync_type = TIMING_SYNCHRONIZABLE;
                                pipe_set[group_size] = unsynced_pipes[j];
                                unsynced_pipes[j] = NULL;
                                group_size++;
@@ -1145,7 +1158,6 @@ static void program_timing_sync(
                        }
                }

-
                for (k = 0; k < group_size; k++) {
                        struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream);

@@ -1175,8 +1187,14 @@ static void program_timing_sync(
                }

                if (group_size > 1) {
-                       dc->hwss.enable_timing_synchronization(
-                               dc, group_index, group_size, pipe_set);
+                       if (sync_type == TIMING_SYNCHRONIZABLE) {
+                               dc->hwss.enable_timing_synchronization(
+                                       dc, group_index, group_size, pipe_set);
+                       } else
+                               if (sync_type == VBLANK_SYNCHRONIZABLE) {
+                               dc->hwss.enable_vblanks_synchronization(
+                                       dc, group_index, group_size, pipe_set);
+                               }
                        group_index++;
                }
                num_group++;
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 0c26c2ade782..0241c9d96d7a 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -417,6 +417,49 @@ int resource_get_clock_source_reference(
        return -1;
 }

+bool resource_are_vblanks_synchronizable(
+       struct dc_stream_state *stream1,
+       struct dc_stream_state *stream2)
+{
+       uint32_t base60_refresh_rates[] = {10, 20, 5};
+       uint8_t i;
+       uint8_t rr_count = sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]);
+       int64_t frame_time_diff;
+
+       if (stream1->ctx->dc->config.vblank_alignment_dto_params &&
+               stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 &&
+               dc_is_dp_signal(stream1->signal) &&
+               dc_is_dp_signal(stream2->signal) &&
+               false == stream1->has_non_synchronizable_pclk &&
+               false == stream2->has_non_synchronizable_pclk &&
+               stream1->timing.flags.VBLANK_SYNCHRONIZABLE &&
+               stream2->timing.flags.VBLANK_SYNCHRONIZABLE) {
+               /* disable refresh rates higher than 60Hz for now */
+               if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/
+                               stream1->timing.v_total > 60)
+                       return false;
+               if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/
+                               stream2->timing.v_total > 60)
+                       return false;
+               frame_time_diff = (int64_t)10000 *
+                       stream1->timing.h_total *
+                       stream1->timing.v_total *
+                       stream2->timing.pix_clk_100hz /
+                       stream1->timing.pix_clk_100hz /
+                       stream2->timing.h_total /
+                       stream2->timing.v_total;
+               for (i = 0; i < rr_count; i++) {
+                       int64_t diff = (frame_time_diff * base60_refresh_rates[i]) / 10 - 10000;
+
+                       if (diff < 0)
+                               diff = -diff;
+                       if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff)
+                               return true;
+               }
+       }
+       return false;
+}
+
 bool resource_are_streams_timing_synchronizable(
        struct dc_stream_state *stream1,
        struct dc_stream_state *stream2)
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index a10daf6655f9..9e631980fa1b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -301,6 +301,8 @@ struct dc_config {
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        bool clamp_min_dcfclk;
 #endif
+       uint64_t vblank_alignment_dto_params;
+       uint8_t  vblank_alignment_max_frame_time_diff;
 };

 enum visual_confirm {
@@ -528,6 +530,7 @@ struct dc_debug_options {
        bool disable_dsc;
        bool enable_dram_clock_change_one_display_vactive;
        union mem_low_power_enable_options enable_mem_low_power;
+       bool force_vblank_alignment;
 };

 struct dc_debug_data {
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index b41e6367b15e..48d3ed97ead9 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -705,6 +705,7 @@ struct dc_crtc_timing_flags {
 #ifndef TRIM_FSFT
        uint32_t FAST_TRANSPORT: 1;
 #endif
+       uint32_t VBLANK_SYNCHRONIZABLE: 1;
 };

 enum dc_timing_3d_format {
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index e243c01b9672..7fa998f97e7a 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -228,6 +228,9 @@ struct dc_stream_state {
        uint32_t stream_id;
        bool is_dsc_enabled;
        union stream_update_flags update_flags;
+
+       bool has_non_synchronizable_pclk;
+       bool vblank_synchronized;
 };

 #define ABM_LEVEL_IMMEDIATE_DISABLE 255
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
index dec58b3c42e4..6f47f9bab5ee 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -1002,15 +1002,27 @@ static bool get_pixel_clk_frequency_100hz(
 {
        struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
        unsigned int clock_hz = 0;
+       unsigned int modulo_hz = 0;

        if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) {
                clock_hz = REG_READ(PHASE[inst]);

-               /* NOTE: There is agreement with VBIOS here that MODULO is
-                * programmed equal to DPREFCLK, in which case PHASE will be
-                * equivalent to pixel clock.
-                */
-               *pixel_clk_khz = clock_hz / 100;
+               if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&
+                       clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {
+                       /* NOTE: In case VBLANK syncronization is enabled, MODULO may
+                        * not be programmed equal to DPREFCLK
+                        */
+                       modulo_hz = REG_READ(MODULO[inst]);
+                       *pixel_clk_khz = ((uint64_t)clock_hz*
+                               clock_source->ctx->dc->clk_mgr->dprefclk_khz*10)/
+                               modulo_hz;
+               } else {
+                       /* NOTE: There is agreement with VBIOS here that MODULO is
+                        * programmed equal to DPREFCLK, in which case PHASE will be
+                        * equivalent to pixel clock.
+                        */
+                       *pixel_clk_khz = clock_hz / 100;
+               }
                return true;
        }

@@ -1074,8 +1086,35 @@ static bool dcn20_program_pix_clk(
                struct pixel_clk_params *pix_clk_params,
                struct pll_settings *pll_settings)
 {
+       struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
+       unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
+
        dce112_program_pix_clk(clock_source, pix_clk_params, pll_settings);

+       if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&
+                       clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {
+               /* NOTE: In case VBLANK syncronization is enabled,
+                * we need to set modulo to default DPREFCLK first
+                * dce112_program_pix_clk does not set default DPREFCLK
+                */
+               REG_WRITE(MODULO[inst],
+                       clock_source->ctx->dc->clk_mgr->dprefclk_khz*1000);
+       }
+       return true;
+}
+
+static bool dcn20_override_dp_pix_clk(
+               struct clock_source *clock_source,
+               unsigned int inst,
+               unsigned int pixel_clk,
+               unsigned int ref_clk)
+{
+       struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
+
+       REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 0);
+       REG_WRITE(PHASE[inst], pixel_clk);
+       REG_WRITE(MODULO[inst], ref_clk);
+       REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1);
        return true;
 }

@@ -1083,7 +1122,8 @@ static const struct clock_source_funcs dcn20_clk_src_funcs = {
        .cs_power_down = dce110_clock_source_power_down,
        .program_pix_clk = dcn20_program_pix_clk,
        .get_pix_clk_dividers = dce112_get_pix_clk_dividers,
-       .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
+       .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz,
+       .override_dp_pix_clk = dcn20_override_dp_pix_clk
 };

 #if defined(CONFIG_DRM_AMD_DC_DCN)
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 89912bb5014f..669cee48b0b5 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
@@ -1851,6 +1851,225 @@ static bool wait_for_reset_trigger_to_occur(
        return rc;
 }

+uint64_t reduceSizeAndFraction(
+       uint64_t *numerator,
+       uint64_t *denominator,
+       bool checkUint32Bounary)
+{
+       int i;
+       bool ret = checkUint32Bounary == false;
+       uint64_t max_int32 = 0xffffffff;
+       uint64_t num, denom;
+       uint16_t prime_numbers[] = {
+               2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
+               47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
+               107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
+               167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
+               229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
+               283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353,
+               359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421,
+               431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487,
+               491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,
+               571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631,
+               641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
+               709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773,
+               787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857,
+               859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
+               941, 947, 953, 967, 971, 977, 983, 991, 997};
+       int count = ARRAY_SIZE(prime_numbers)/sizeof(prime_numbers[0]);

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".

BR
Nils

[-- Attachment #1.2: Type: text/html, Size: 32256 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2021-02-22 18:05 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-19 22:15 [PATCH 00/13] DC Patches FEB 22, 2021 Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 01/13] drm/amd/display: Remove Assert from dcn10_get_dig_frontend Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 02/13] drm/amd/display: Refactor debugfs entries for all connectors Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 03/13] drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1 Bindu Ramamurthy
2021-02-19 22:16   ` Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 04/13] drm/amd/display: disable seamless boot for DP MST Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 05/13] drm/amd/display: enable audio on DP seamless boot Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 06/13] drm/amd/display: Check for DSC support instead of ASIC revision Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 07/13] drm/amd/display: move trace buffer to uncached memory Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 08/13] drm/amd/display: Synchronize displays with different timings Bindu Ramamurthy
2021-02-21  6:21   ` Nils Wallménius
2021-02-22 13:43     ` R, Bindu
2021-02-22 18:04       ` R, Bindu
2021-02-19 22:16 ` [PATCH 09/13] drm/amd/display: Don't optimize bandwidth before disabling planes Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 10/13] drm/amd/display: reduce scope for local var Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 11/13] drm/amd/display: [FW Promotion] Release 0.0.53 Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 12/13] drm/amd/display: 3.2.124 Bindu Ramamurthy
2021-02-19 22:16 ` [PATCH 13/13] drm/amd/display: Fix system hang after multiple hotplugs Bindu Ramamurthy
2021-02-19 22:29 ` [PATCH 00/13] DC Patches FEB 22, 2021 Wheeler, Daniel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.