[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