[RFC][PATCH 3/2] drm/radeon: use masks when doing DCE4+ HDMI R/W ops

Rafał Miłecki zajec5 at gmail.com
Sun Oct 6 23:41:52 CEST 2013


Recent RE with faking reading values allowed us to figure out correct
masks for all R/W ops. Use them following fglrx logic.

See https://bugzilla.kernel.org/show_bug.cgi?id=62591 for details.
---
That patches weren't tested with the HW, please don't apply them yet.
---
 drivers/gpu/drm/radeon/evergreen_hdmi.c |   78 +++++++++++++++++++------------
 drivers/gpu/drm/radeon/evergreend.h     |   12 +++++
 2 files changed, 59 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c
index 51b643d..1f6e332 100644
--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c
+++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c
@@ -48,14 +48,20 @@ static void evergreen_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t cloc
 	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 	uint32_t offset = dig->afmt->offset;
 
-	WREG32(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr.cts_32khz));
-	WREG32(HDMI_ACR_32_1 + offset, acr.n_32khz);
-
-	WREG32(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr.cts_44_1khz));
-	WREG32(HDMI_ACR_44_1 + offset, acr.n_44_1khz);
-
-	WREG32(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr.cts_48khz));
-	WREG32(HDMI_ACR_48_1 + offset, acr.n_48khz);
+	WREG32_P(HDMI_ACR_32_0 + offset, HDMI_ACR_CTS_32(acr.cts_32khz),
+		 ~HDMI_ACR_CTS_32_MASK);
+	WREG32_P(HDMI_ACR_32_1 + offset, HDMI_ACR_N_32(acr.n_32khz),
+		 ~HDMI_ACR_N_32_MASK);
+
+	WREG32_P(HDMI_ACR_44_0 + offset, HDMI_ACR_CTS_44(acr.cts_44_1khz),
+		 ~HDMI_ACR_CTS_44_MASK);
+	WREG32_P(HDMI_ACR_44_1 + offset, HDMI_ACR_N_44(acr.n_44_1khz),
+		 ~HDMI_ACR_N_44_MASK);
+
+	WREG32_P(HDMI_ACR_48_0 + offset, HDMI_ACR_CTS_48(acr.cts_48khz),
+		 ~HDMI_ACR_CTS_48_MASK);
+	WREG32_P(HDMI_ACR_48_1 + offset, HDMI_ACR_N_48(acr.n_48khz),
+		 ~HDMI_ACR_N_48_MASK);
 }
 
 static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
@@ -258,10 +264,11 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
 
 	evergreen_audio_set_dto(encoder, mode->clock);
 
-	WREG32(HDMI_VBI_PACKET_CONTROL + offset,
-	       HDMI_NULL_SEND | /* send null packets when required */
-	       HDMI_GC_SEND | /* send general control packets */
-	       HDMI_GC_CONT); /* send general control packets every frame */
+	WREG32_P(HDMI_VBI_PACKET_CONTROL + offset,
+		 HDMI_NULL_SEND | /* send null packets when required */
+		 HDMI_GC_SEND | /* send general control packets */
+		 HDMI_GC_CONT, /* send general control packets every frame */
+		 ~(HDMI_NULL_SEND | HDMI_GC_SEND | HDMI_GC_CONT | BIT(12)));
 
 	WREG32(HDMI_INFOFRAME_CONTROL0 + offset,
 	       HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
@@ -270,14 +277,17 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
 	WREG32(AFMT_INFOFRAME_CONTROL0 + offset,
 	       AFMT_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */
 
-	WREG32(HDMI_INFOFRAME_CONTROL1 + offset,
-	       HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */
+	WREG32_P(HDMI_INFOFRAME_CONTROL1 + offset,
+		 HDMI_AUDIO_INFO_LINE(2), /* anything other than 0 */
+		 ~HDMI_AUDIO_INFO_LINE_MASK);
 
-	WREG32(HDMI_GC + offset, 0); /* unset HDMI_GC_AVMUTE */
+	WREG32_AND(HDMI_GC + offset, ~HDMI_GC_AVMUTE); /* unset HDMI_GC_AVMUTE */
 
-	WREG32(HDMI_AUDIO_PACKET_CONTROL + offset,
-	       HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */
-	       HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
+	WREG32_P(HDMI_AUDIO_PACKET_CONTROL + offset,
+		 HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */
+		 HDMI_AUDIO_PACKETS_PER_LINE(3), /* should be suffient for all audio modes and small enough for all hblanks */
+		 ~(HDMI_AUDIO_DELAY_EN_MASK |
+		   HDMI_AUDIO_PACKETS_PER_LINE_MASK));
 
 	WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
 	       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
@@ -285,25 +295,31 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
 	WREG32_AND(AFMT_AUDIO_PACKET_CONTROL2,
 		   ~(AFMT_AUDIO_LAYOUT_OVRD | AFMT_60958_CS_SOURCE));
 
+	/* TODO: do we need HDMI_ACR_SOURCE? */
 	WREG32(HDMI_ACR_PACKET_CONTROL + offset,
 	       HDMI_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */
 	       HDMI_ACR_SOURCE); /* select SW CTS value */
 
 	evergreen_hdmi_update_ACR(encoder, mode->clock);
 
-	WREG32(AFMT_60958_0 + offset,
-	       AFMT_60958_CS_CHANNEL_NUMBER_L(1));
-
-	WREG32(AFMT_60958_1 + offset,
-	       AFMT_60958_CS_CHANNEL_NUMBER_R(2));
-
-	WREG32(AFMT_60958_2 + offset,
-	       AFMT_60958_CS_CHANNEL_NUMBER_2(3) |
-	       AFMT_60958_CS_CHANNEL_NUMBER_3(4) |
-	       AFMT_60958_CS_CHANNEL_NUMBER_4(5) |
-	       AFMT_60958_CS_CHANNEL_NUMBER_5(6) |
-	       AFMT_60958_CS_CHANNEL_NUMBER_6(7) |
-	       AFMT_60958_CS_CHANNEL_NUMBER_7(8));
+	WREG32_P(AFMT_60958_0 + offset,
+		 AFMT_60958_CS_CHANNEL_NUMBER_L(1),
+		 ~(AFMT_60958_CS_CHANNEL_NUMBER_L_MASK |
+		   BIT(30) |
+		   BIT(31)));
+
+	WREG32_P(AFMT_60958_1 + offset,
+		 AFMT_60958_CS_CHANNEL_NUMBER_R(2),
+		 ~AFMT_60958_CS_CHANNEL_NUMBER_R_MASK);
+
+	WREG32_P(AFMT_60958_2 + offset,
+		 AFMT_60958_CS_CHANNEL_NUMBER_2(3) |
+		 AFMT_60958_CS_CHANNEL_NUMBER_3(4) |
+		 AFMT_60958_CS_CHANNEL_NUMBER_4(5) |
+		 AFMT_60958_CS_CHANNEL_NUMBER_5(6) |
+		 AFMT_60958_CS_CHANNEL_NUMBER_6(7) |
+		 AFMT_60958_CS_CHANNEL_NUMBER_7(8),
+		 ~AFMT_60958_CS_CHANNEL_NUMBERS_MASK);
 
 	if (ASIC_IS_DCE6(rdev))
 		WREG32(0x7138 + offset, 0);
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index cf75975..585ad90 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -523,7 +523,9 @@
 #       define HDMI_VBI_PACKET_ERROR         (1 << 20)
 #define HDMI_AUDIO_PACKET_CONTROL            0x7038
 #       define HDMI_AUDIO_DELAY_EN(x)        (((x) & 3) << 4)
+#       define HDMI_AUDIO_DELAY_EN_MASK      (3 << 4)
 #       define HDMI_AUDIO_PACKETS_PER_LINE(x)  (((x) & 0x1f) << 16)
+#       define HDMI_AUDIO_PACKETS_PER_LINE_MASK (0x1f << 16)
 #define HDMI_ACR_PACKET_CONTROL              0x703c
 #       define HDMI_ACR_SEND                 (1 << 0)
 #       define HDMI_ACR_CONT                 (1 << 1)
@@ -554,6 +556,7 @@
 #       define HDMI_AVI_INFO_LINE(x)         (((x) & 0x3f) << 0)
 #       define HDMI_AVI_INFO_LINE_MASK       (0x3f << 0)
 #       define HDMI_AUDIO_INFO_LINE(x)       (((x) & 0x3f) << 8)
+#       define HDMI_AUDIO_INFO_LINE_MASK     (0x3f << 8)
 #       define HDMI_MPEG_INFO_LINE(x)        (((x) & 0x3f) << 16)
 #define HDMI_GENERIC_PACKET_CONTROL          0x704c
 #       define HDMI_GENERIC0_SEND            (1 << 0)
@@ -632,16 +635,22 @@
 #define AFMT_GENERIC1_6                      0x70d8
 #define HDMI_ACR_32_0                        0x70dc
 #       define HDMI_ACR_CTS_32(x)            (((x) & 0xfffff) << 12)
+#       define HDMI_ACR_CTS_32_MASK          (0xfffff << 12)
 #define HDMI_ACR_32_1                        0x70e0
 #       define HDMI_ACR_N_32(x)              (((x) & 0xfffff) << 0)
+#       define HDMI_ACR_N_32_MASK            (0xfffff << 0)
 #define HDMI_ACR_44_0                        0x70e4
 #       define HDMI_ACR_CTS_44(x)            (((x) & 0xfffff) << 12)
+#       define HDMI_ACR_CTS_44_MASK          (0xfffff << 12)
 #define HDMI_ACR_44_1                        0x70e8
 #       define HDMI_ACR_N_44(x)              (((x) & 0xfffff) << 0)
+#       define HDMI_ACR_N_44_MASK            (0xfffff << 0)
 #define HDMI_ACR_48_0                        0x70ec
 #       define HDMI_ACR_CTS_48(x)            (((x) & 0xfffff) << 12)
+#       define HDMI_ACR_CTS_48_MASK          (0xfffff << 12)
 #define HDMI_ACR_48_1                        0x70f0
 #       define HDMI_ACR_N_48(x)              (((x) & 0xfffff) << 0)
+#       define HDMI_ACR_N_48_MASK            (0xfffff << 0)
 #define HDMI_ACR_STATUS_0                    0x70f4
 #define HDMI_ACR_STATUS_1                    0x70f8
 #define AFMT_AUDIO_INFO0                     0x70fc
@@ -665,6 +674,7 @@
 #       define AFMT_60958_CS_CATEGORY_CODE(x)      (((x) & 0xff) << 8)
 #       define AFMT_60958_CS_SOURCE_NUMBER(x)      (((x) & 0xf) << 16)
 #       define AFMT_60958_CS_CHANNEL_NUMBER_L(x)   (((x) & 0xf) << 20)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_L_MASK (0xf << 20)
 #       define AFMT_60958_CS_SAMPLING_FREQUENCY(x) (((x) & 0xf) << 24)
 #       define AFMT_60958_CS_CLOCK_ACCURACY(x)     (((x) & 3) << 28)
 #define AFMT_60958_1                         0x7108
@@ -673,6 +683,7 @@
 #       define AFMT_60958_CS_VALID_L(x)      (((x) & 1) << 16)
 #       define AFMT_60958_CS_VALID_R(x)      (((x) & 1) << 18)
 #       define AFMT_60958_CS_CHANNEL_NUMBER_R(x)   (((x) & 0xf) << 20)
+#       define AFMT_60958_CS_CHANNEL_NUMBER_R_MASK (0xf << 20)
 #define AFMT_AUDIO_CRC_CONTROL               0x710c
 #       define AFMT_AUDIO_CRC_EN             (1 << 0)
 #define AFMT_RAMP_CONTROL0                   0x7110
@@ -692,6 +703,7 @@
 #       define AFMT_60958_CS_CHANNEL_NUMBER_5(x)   (((x) & 0xf) << 12)
 #       define AFMT_60958_CS_CHANNEL_NUMBER_6(x)   (((x) & 0xf) << 16)
 #       define AFMT_60958_CS_CHANNEL_NUMBER_7(x)   (((x) & 0xf) << 20)
+#       define AFMT_60958_CS_CHANNEL_NUMBERS_MASK  0x00ffffff
 #define AFMT_STATUS                          0x7128
 #       define AFMT_AUDIO_ENABLE             (1 << 4)
 #       define AFMT_AUDIO_HBR_ENABLE         (1 << 8)
-- 
1.7.10.4



More information about the dri-devel mailing list