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 f7b2659..6cb2f11 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 c4ff60f..1c87006 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 2f29918..38b1c51 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 */
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge