[PATCH 10/24] radeon/audio: consolidate audio_set_dto() functions

Alex Deucher alexdeucher at gmail.com
Tue Jan 13 09:46:39 PST 2015


From: Slava Grigorev <slava.grigorev at amd.com>

Signed-off-by: Slava Grigorev <slava.grigorev at amd.com>
Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
---
 drivers/gpu/drm/radeon/dce3_1_afmt.c    | 56 +++++++++++++++++++-
 drivers/gpu/drm/radeon/dce6_afmt.c      | 39 ++++++++++++++
 drivers/gpu/drm/radeon/evergreen_hdmi.c | 92 ++++++++++++++++++++-------------
 drivers/gpu/drm/radeon/evergreend.h     |  1 +
 drivers/gpu/drm/radeon/r600_hdmi.c      | 80 +++++++---------------------
 drivers/gpu/drm/radeon/radeon_audio.c   | 45 +++++++++++++++-
 drivers/gpu/drm/radeon/radeon_audio.h   |  3 ++
 drivers/gpu/drm/radeon/sid.h            | 10 ++++
 8 files changed, 226 insertions(+), 100 deletions(-)

diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c
index f7b2659..6cb2f11 100644
--- a/drivers/gpu/drm/radeon/dce3_1_afmt.c
+++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c
@@ -113,6 +113,60 @@ void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder,
 	}
 }
 
+void dce3_2_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock)
+{
+	struct radeon_encoder *radeon_encoder;
+	struct radeon_encoder_atom_dig *dig;
+	unsigned int max_ratio = clock / 24000;
+	u32 dto_phase;
+	u32 wallclock_ratio;
+	u32 dto_cntl;
+
+	if (!crtc)
+		return;
+
+	radeon_encoder = to_radeon_encoder(crtc->encoder);
+	dig = radeon_encoder->enc_priv;
+
+	if (!dig)
+		return;
+
+	if (max_ratio >= 8) {
+		dto_phase = 192 * 1000;
+		wallclock_ratio = 3;
+	} else if (max_ratio >= 4) {
+		dto_phase = 96 * 1000;
+		wallclock_ratio = 2;
+	} else if (max_ratio >= 2) {
+		dto_phase = 48 * 1000;
+		wallclock_ratio = 1;
+	} else {
+		dto_phase = 24 * 1000;
+		wallclock_ratio = 0;
+	}
+
+	/* Express [24MHz / target pixel clock] as an exact rational
+	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
+	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+	 */
+	if (dig->dig_encoder == 0) {
+		dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
+		dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
+		WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl);
+		WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase);
+		WREG32(DCCG_AUDIO_DTO0_MODULE, clock);
+		WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
+	} else {
+		dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
+		dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
+		WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl);
+		WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase);
+		WREG32(DCCG_AUDIO_DTO1_MODULE, clock);
+		WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
+	}
+}
+
 /*
  * update the info frames with the data from the current display mode
  */
@@ -139,7 +193,7 @@ void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *m
 	dig->afmt->pin = radeon_audio_get_pin(encoder);
 	radeon_audio_enable(rdev, dig->afmt->pin, 0);
 
-	r600_audio_set_dto(encoder, mode->clock);
+	radeon_audio_set_dto(encoder, mode->clock);
 
 	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
 	       HDMI0_NULL_SEND); /* send null packets when required */
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c
index c4ff60f..1c87006 100644
--- a/drivers/gpu/drm/radeon/dce6_afmt.c
+++ b/drivers/gpu/drm/radeon/dce6_afmt.c
@@ -248,3 +248,42 @@ void dce6_audio_enable(struct radeon_device *rdev,
 	WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
 			enable_mask ? AUDIO_ENABLED : 0);
 }
+
+void dce6_hdmi_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock)
+{
+    /* Two dtos; generally use dto0 for HDMI */
+	u32 value = 0;
+
+    if (crtc)
+		value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id);
+
+	WREG32(DCCG_AUDIO_DTO_SOURCE, value);
+
+    /* Express [24MHz / target pixel clock] as an exact rational
+     * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
+     * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+     */
+    WREG32(DCCG_AUDIO_DTO0_PHASE, 24000);
+    WREG32(DCCG_AUDIO_DTO0_MODULE, clock);
+}
+
+void dce6_dp_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock)
+{
+    /* Two dtos; generally use dto1 for DP */
+	u32 value = 0;
+	value |= DCCG_AUDIO_DTO_SEL;
+
+    if (crtc)
+		value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id);
+
+	WREG32(DCCG_AUDIO_DTO_SOURCE, value);
+
+    /* Express [24MHz / target pixel clock] as an exact rational
+     * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
+     * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+     */
+    WREG32(DCCG_AUDIO_DTO1_PHASE, 24000);
+    WREG32(DCCG_AUDIO_DTO1_MODULE, clock);
+}
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c
index 2f29918..38b1c51 100644
--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c
+++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c
@@ -218,54 +218,74 @@ static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder,
 		frame[0xC] | (frame[0xD] << 8) | (header[1] << 24));
 }
 
-static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock)
+void dce4_hdmi_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock)
 {
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-	u32 base_rate = 24000;
-	u32 max_ratio = clock / base_rate;
+	unsigned int max_ratio = clock / 24000;
 	u32 dto_phase;
-	u32 dto_modulo = clock;
 	u32 wallclock_ratio;
-	u32 dto_cntl;
-
-	if (!dig || !dig->afmt)
-		return;
-
-	if (ASIC_IS_DCE6(rdev)) {
-		dto_phase = 24 * 1000;
+	u32 value;
+
+	if (max_ratio >= 8) {
+		dto_phase = 192 * 1000;
+		wallclock_ratio = 3;
+	} else if (max_ratio >= 4) {
+		dto_phase = 96 * 1000;
+		wallclock_ratio = 2;
+	} else if (max_ratio >= 2) {
+		dto_phase = 48 * 1000;
+		wallclock_ratio = 1;
 	} else {
-		if (max_ratio >= 8) {
-			dto_phase = 192 * 1000;
-			wallclock_ratio = 3;
-		} else if (max_ratio >= 4) {
-			dto_phase = 96 * 1000;
-			wallclock_ratio = 2;
-		} else if (max_ratio >= 2) {
-			dto_phase = 48 * 1000;
-			wallclock_ratio = 1;
-		} else {
-			dto_phase = 24 * 1000;
-			wallclock_ratio = 0;
-		}
-		dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
-		dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
-		WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl);
+		dto_phase = 24 * 1000;
+		wallclock_ratio = 0;
 	}
 
-	/* XXX two dtos; generally use dto0 for hdmi */
+	value = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
+	value |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
+	value &= ~DCCG_AUDIO_DTO1_USE_512FBR_DTO;
+	WREG32(DCCG_AUDIO_DTO0_CNTL, value);
+
+	/* Two dtos; generally use dto0 for HDMI */
+	value = 0;
+
+	if (crtc)
+		value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id);
+
+	WREG32(DCCG_AUDIO_DTO_SOURCE, value);
+
 	/* Express [24MHz / target pixel clock] as an exact rational
 	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
 	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
 	 */
-	WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id));
 	WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase);
-	WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo);
+	WREG32(DCCG_AUDIO_DTO0_MODULE, clock);
 }
 
+void dce4_dp_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock)
+{
+	u32 value;
+
+	value = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
+	value |= DCCG_AUDIO_DTO1_USE_512FBR_DTO;
+	WREG32(DCCG_AUDIO_DTO1_CNTL, value);
+
+	/* Two dtos; generally use dto1 for DP */
+	value = 0;
+	value |= DCCG_AUDIO_DTO_SEL;
+
+	if (crtc)
+		value |= DCCG_AUDIO_DTO0_SOURCE_SEL(crtc->crtc_id);
+
+	WREG32(DCCG_AUDIO_DTO_SOURCE, value);
+
+	/* Express [24MHz / target pixel clock] as an exact rational
+	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
+	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
+	 */
+	WREG32(DCCG_AUDIO_DTO1_PHASE, 24000);
+	WREG32(DCCG_AUDIO_DTO1_MODULE, rdev->clock.max_pixel_clock * 10);
+}
 
 /*
  * update the info frames with the data from the current display mode
@@ -302,7 +322,7 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
 	dig->afmt->pin = radeon_audio_get_pin(encoder);
 	radeon_audio_enable(rdev, dig->afmt->pin, 0);
 
-	evergreen_audio_set_dto(encoder, mode->clock);
+	radeon_audio_set_dto(encoder, mode->clock);
 
 	WREG32(HDMI_VBI_PACKET_CONTROL + offset,
 	       HDMI_NULL_SEND); /* send null packets when required */
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index b066d67..ee83d2a 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -509,6 +509,7 @@
 #define DCCG_AUDIO_DTO1_MODULE            0x05c4
 #define DCCG_AUDIO_DTO1_LOAD              0x05c8
 #define DCCG_AUDIO_DTO1_CNTL              0x05cc
+#       define DCCG_AUDIO_DTO1_USE_512FBR_DTO (1 << 3)
 
 /* DCE 4.0 AFMT */
 #define HDMI_CONTROL                         0x7030
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index 1c49f4d..30580d1 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -380,73 +380,29 @@ void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
 		 value, ~HDMI0_AUDIO_TEST_EN);
 }
 
-void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
+void r600_hdmi_audio_set_dto(struct radeon_device *rdev,
+    struct radeon_crtc *crtc, unsigned int clock)
 {
-	struct drm_device *dev = encoder->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-	u32 base_rate = 24000;
-	u32 max_ratio = clock / base_rate;
-	u32 dto_phase;
-	u32 dto_modulo = clock;
-	u32 wallclock_ratio;
-	u32 dto_cntl;
+	struct radeon_encoder *radeon_encoder;
+	struct radeon_encoder_atom_dig *dig;
 
-	if (!dig || !dig->afmt)
+	if (!crtc)
 		return;
 
-	if (max_ratio >= 8) {
-		dto_phase = 192 * 1000;
-		wallclock_ratio = 3;
-	} else if (max_ratio >= 4) {
-		dto_phase = 96 * 1000;
-		wallclock_ratio = 2;
-	} else if (max_ratio >= 2) {
-		dto_phase = 48 * 1000;
-		wallclock_ratio = 1;
-	} else {
-		dto_phase = 24 * 1000;
-		wallclock_ratio = 0;
-	}
+	radeon_encoder = to_radeon_encoder(crtc->encoder);
+	dig = radeon_encoder->enc_priv;
 
-	/* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT.
-	 * doesn't matter which one you use.  Just use the first one.
-	 */
-	/* XXX two dtos; generally use dto0 for hdmi */
-	/* Express [24MHz / target pixel clock] as an exact rational
-	 * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
-	 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
-	 */
-	if (ASIC_IS_DCE32(rdev)) {
-		if (dig->dig_encoder == 0) {
-			dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
-			dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
-			WREG32(DCCG_AUDIO_DTO0_CNTL, dto_cntl);
-			WREG32(DCCG_AUDIO_DTO0_PHASE, dto_phase);
-			WREG32(DCCG_AUDIO_DTO0_MODULE, dto_modulo);
-			WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
-		} else {
-			dto_cntl = RREG32(DCCG_AUDIO_DTO1_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
-			dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
-			WREG32(DCCG_AUDIO_DTO1_CNTL, dto_cntl);
-			WREG32(DCCG_AUDIO_DTO1_PHASE, dto_phase);
-			WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo);
-			WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
-		}
+	if (!dig)
+		return;
+
+	if (dig->dig_encoder == 0) {
+		WREG32(DCCG_AUDIO_DTO0_PHASE, 24000 * 100);
+		WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
+		WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
 	} else {
-		/* according to the reg specs, this should DCE3.2 only, but in
-		 * practice it seems to cover DCE2.0/3.0/3.1 as well.
-		 */
-		if (dig->dig_encoder == 0) {
-			WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
-			WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
-			WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
-		} else {
-			WREG32(DCCG_AUDIO_DTO1_PHASE, base_rate * 100);
-			WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100);
-			WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
-		}
+		WREG32(DCCG_AUDIO_DTO1_PHASE, 24000 * 100);
+		WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100);
+		WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
 	}
 }
 
@@ -477,7 +433,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
 	dig->afmt->pin = radeon_audio_get_pin(encoder);
 	radeon_audio_enable(rdev, dig->afmt->pin, 0);
 
-	r600_audio_set_dto(encoder, mode->clock);
+	radeon_audio_set_dto(encoder, mode->clock);
 
 	WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset,
 		 HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
index e6c73f8..2a2bf5b 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.c
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
@@ -62,6 +62,18 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
 struct r600_audio_pin* r600_audio_get_pin(struct radeon_device *rdev);
 struct r600_audio_pin* dce6_audio_get_pin(struct radeon_device *rdev);
 void dce6_afmt_select_pin(struct drm_encoder *encoder);
+void r600_hdmi_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
+void dce3_2_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
+void dce4_hdmi_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
+void dce4_dp_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
+void dce6_hdmi_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
+void dce6_dp_audio_set_dto(struct radeon_device *rdev,
+	struct radeon_crtc *crtc, unsigned int clock);
 
 static const u32 pin_offsets[7] =
 {
@@ -85,6 +97,12 @@ static void radeon_audio_wreg(struct radeon_device *rdev, u32 offset,
 	WREG32(reg, v);
 }
 
+static struct radeon_audio_basic_funcs r600_funcs = {
+	.endpoint_rreg = radeon_audio_rreg,
+	.endpoint_wreg = radeon_audio_wreg,
+	.enable = r600_audio_enable,
+};
+
 static struct radeon_audio_basic_funcs dce32_funcs = {
 	.endpoint_rreg = radeon_audio_rreg,
 	.endpoint_wreg = radeon_audio_wreg,
@@ -103,16 +121,23 @@ static struct radeon_audio_basic_funcs dce6_funcs = {
 	.enable = dce6_audio_enable,
 };
 
+static struct radeon_audio_funcs r600_hdmi_funcs = {
+	.get_pin = r600_audio_get_pin,
+	.set_dto = r600_hdmi_audio_set_dto,
+};
+
 static struct radeon_audio_funcs dce32_hdmi_funcs = {
 	.get_pin = r600_audio_get_pin,
 	.write_sad_regs = dce3_2_afmt_write_sad_regs,
 	.write_speaker_allocation = dce3_2_afmt_hdmi_write_speaker_allocation,
+	.set_dto = dce3_2_audio_set_dto,
 };
 
 static struct radeon_audio_funcs dce32_dp_funcs = {
 	.get_pin = r600_audio_get_pin,
 	.write_sad_regs = dce3_2_afmt_write_sad_regs,
 	.write_speaker_allocation = dce3_2_afmt_dp_write_speaker_allocation,
+	.set_dto = dce3_2_audio_set_dto,
 };
 
 static struct radeon_audio_funcs dce4_hdmi_funcs = {
@@ -120,6 +145,7 @@ static struct radeon_audio_funcs dce4_hdmi_funcs = {
 	.write_sad_regs = evergreen_hdmi_write_sad_regs,
 	.write_speaker_allocation = dce4_afmt_hdmi_write_speaker_allocation,
 	.write_latency_fields = dce4_afmt_write_latency_fields,
+	.set_dto = dce4_hdmi_audio_set_dto,
 };
 
 static struct radeon_audio_funcs dce4_dp_funcs = {
@@ -127,6 +153,7 @@ static struct radeon_audio_funcs dce4_dp_funcs = {
 	.write_sad_regs = evergreen_hdmi_write_sad_regs,
 	.write_speaker_allocation = dce4_afmt_dp_write_speaker_allocation,
 	.write_latency_fields = dce4_afmt_write_latency_fields,
+	.set_dto = dce4_dp_audio_set_dto,
 };
 
 static struct radeon_audio_funcs dce6_hdmi_funcs = {
@@ -135,6 +162,7 @@ static struct radeon_audio_funcs dce6_hdmi_funcs = {
 	.write_sad_regs = dce6_afmt_write_sad_regs,
 	.write_speaker_allocation = dce6_afmt_hdmi_write_speaker_allocation,
 	.write_latency_fields = dce6_afmt_write_latency_fields,
+	.set_dto = dce6_hdmi_audio_set_dto,
 };
 
 static struct radeon_audio_funcs dce6_dp_funcs = {
@@ -143,6 +171,7 @@ static struct radeon_audio_funcs dce6_dp_funcs = {
 	.write_sad_regs = dce6_afmt_write_sad_regs,
 	.write_speaker_allocation = dce6_afmt_dp_write_speaker_allocation,
 	.write_latency_fields = dce6_afmt_write_latency_fields,
+	.set_dto = dce6_dp_audio_set_dto,
 };
 
 static void radeon_audio_interface_init(struct radeon_device *rdev)
@@ -155,10 +184,14 @@ static void radeon_audio_interface_init(struct radeon_device *rdev)
 		rdev->audio.funcs = &dce4_funcs;
 		rdev->audio.hdmi_funcs = &dce4_hdmi_funcs;
 		rdev->audio.dp_funcs = &dce4_dp_funcs;
-	} else {
+	} else if (ASIC_IS_DCE32(rdev)) {
 		rdev->audio.funcs = &dce32_funcs;
 		rdev->audio.hdmi_funcs = &dce32_hdmi_funcs;
 		rdev->audio.dp_funcs = &dce32_dp_funcs;
+	} else {
+		rdev->audio.funcs = &r600_funcs;
+		rdev->audio.hdmi_funcs = &r600_hdmi_funcs;
+		rdev->audio.dp_funcs = 0;
 	}
 }
 
@@ -393,3 +426,13 @@ void radeon_audio_fini(struct radeon_device *rdev)
 
 	rdev->audio.enabled = false;
 }
+
+void radeon_audio_set_dto(struct drm_encoder *encoder, unsigned int clock)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_crtc *crtc = to_radeon_crtc(encoder->crtc);
+
+	if (radeon_encoder->audio && radeon_encoder->audio->set_dto)
+		radeon_encoder->audio->set_dto(rdev, crtc, clock);
+}
diff --git a/drivers/gpu/drm/radeon/radeon_audio.h b/drivers/gpu/drm/radeon/radeon_audio.h
index 5844993..06b80de 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.h
+++ b/drivers/gpu/drm/radeon/radeon_audio.h
@@ -51,6 +51,8 @@ struct radeon_audio_funcs
 		struct cea_sad *sads, int sad_count);
 	void (*write_speaker_allocation)(struct drm_encoder *encoder,
 		u8 *sadb, int sad_count);
+	void (*set_dto)(struct radeon_device *rdev,
+		struct radeon_crtc *crtc, unsigned int clock);
 };
 
 int radeon_audio_init(struct radeon_device *rdev);
@@ -69,5 +71,6 @@ void radeon_audio_select_pin(struct drm_encoder *encoder);
 void radeon_audio_enable(struct radeon_device *rdev,
 	struct r600_audio_pin *pin, u8 enable_mask);
 void radeon_audio_fini(struct radeon_device *rdev);
+void radeon_audio_set_dto(struct drm_encoder *encoder, unsigned int clock);
 
 #endif
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
index 4069be89..eb5293e 100644
--- a/drivers/gpu/drm/radeon/sid.h
+++ b/drivers/gpu/drm/radeon/sid.h
@@ -901,6 +901,16 @@
 /* 0x6e98, 0x7a98, 0x10698, 0x11298, 0x11e98, 0x12a98 */
 #define CRTC_STATUS_FRAME_COUNT                         0x6e98
 
+/* Audio clocks */
+#define DCCG_AUDIO_DTO_SOURCE                           0x05ac
+#       define DCCG_AUDIO_DTO0_SOURCE_SEL(x) ((x) << 0) /* crtc0 - crtc5 */
+#       define DCCG_AUDIO_DTO_SEL            (1 << 4)   /* 0=dto0 1=dto1 */
+
+#define DCCG_AUDIO_DTO0_PHASE                           0x05b0
+#define DCCG_AUDIO_DTO0_MODULE                          0x05b4
+#define DCCG_AUDIO_DTO1_PHASE                           0x05b8
+#define DCCG_AUDIO_DTO1_MODULE                          0x05bc
+
 #define AFMT_AUDIO_SRC_CONTROL                          0x713c
 #define		AFMT_AUDIO_SRC_SELECT(x)		(((x) & 7) << 0)
 /* AFMT_AUDIO_SRC_SELECT
-- 
1.8.3.1



More information about the dri-devel mailing list