radeon/audio: consolidate audio_set_dto() functions
authorSlava Grigorev <slava.grigorev@amd.com>
Fri, 5 Dec 2014 18:38:31 +0000 (13:38 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 22 Jan 2015 15:42:10 +0000 (10:42 -0500)
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Slava Grigorev <slava.grigorev@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/dce3_1_afmt.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/radeon_audio.c
drivers/gpu/drm/radeon/radeon_audio.h
drivers/gpu/drm/radeon/sid.h

index f7b26592c74faaac7db4273cb8398674dfacd3cd..6cb2f1171539c37717f9fd82b04526b765ccc9f4 100644 (file)
@@ -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 */
index c4ff60f005d222b95318172e04709ff08924e3e6..1c870060c29b7bd7552c12a76c0678990e91f64c 100644 (file)
@@ -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);
+}
index 2f29918ee49f830a44be18f47ade8a1b16dd8efe..38b1c51cce4d19ed7c2c072881785c75d221eee6 100644 (file)
@@ -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 */
index b066d6711b8df54c698650b159b49be26fd31fd7..ee83d2a88750aafb865c30dd89e42c2041700a61 100644 (file)
 #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
index 1c49f4d2945a806fb25cf1bc9b859b853bc9fd45..30580d1a14f0d4fee7ed3add9725758d11959c4a 100644 (file)
@@ -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 */
index e6c73f8206b218ed5edb59bb3cc039597f9fb657..2a2bf5b5b805e6d520d6a91c895cf8ac1bf70bb8 100644 (file)
@@ -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);
+}
index 5844993a1edb26a751a3aa279ef5a5183e44f69e..06b80de7cdbe4eaddf693cdc8784ee2c55cb7d8d 100644 (file)
@@ -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
index 84999242c74746317dfeed4954fee7baec4019e7..cbd91d226f3ce232b5933686ad41cae3ace64ebe 100644 (file)
 /* 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