Message ID | 1366299343-28669-3-git-send-email-alexdeucher@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
2013/4/18 <alexdeucher@gmail.com>: > - switch (radeon_encoder->encoder_id) { > - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: > - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: > - WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); > - break; > - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: > - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: > - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: > - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: > - WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); > - break; > - default: > - dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n", > - radeon_encoder->encoder_id); > - return; > - } Are you sure we can just drop that part? I'd appreciate waiting with this patch until next week, I'll test it over the weekend on my RV620.
On Fri, Apr 19, 2013 at 2:10 AM, Rafa? Mi?ecki <zajec5@gmail.com> wrote: > 2013/4/18 <alexdeucher@gmail.com>: >> - switch (radeon_encoder->encoder_id) { >> - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: >> - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: >> - WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); >> - break; >> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: >> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: >> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: >> - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: >> - WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); >> - break; >> - default: >> - dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n", >> - radeon_encoder->encoder_id); >> - return; >> - } > > Are you sure we can just drop that part? Yes we should be able to drop that part. The only relevant bits are 9:8 which allows you to force which DTO is used by the audio block. 0 = auto, 1 = force dto0, 2 = force dto1. Additionally, that register doesn't exist on evergreen and newer. On evergreen and newer there is a DIG PHY register at the same offset which may explain the display problems some people are experiencing. > > I'd appreciate waiting with this patch until next week, I'll test it > over the weekend on my RV620. Sounds good. Alex
2013/4/19 Alex Deucher <alexdeucher@gmail.com>: > On Fri, Apr 19, 2013 at 2:10 AM, Rafa? Mi?ecki <zajec5@gmail.com> wrote: >> 2013/4/18 <alexdeucher@gmail.com>: >>> - switch (radeon_encoder->encoder_id) { >>> - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: >>> - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: >>> - WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); >>> - break; >>> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: >>> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: >>> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: >>> - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: >>> - WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); >>> - break; >>> - default: >>> - dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n", >>> - radeon_encoder->encoder_id); >>> - return; >>> - } >> >> Are you sure we can just drop that part? > > Yes we should be able to drop that part. The only relevant bits are > 9:8 which allows you to force which DTO is used by the audio block. 0 > = auto, 1 = force dto0, 2 = force dto1. Additionally, that register > doesn't exist on evergreen and newer. On evergreen and newer there is > a DIG PHY register at the same offset which may explain the display > problems some people are experiencing. > >> >> I'd appreciate waiting with this patch until next week, I'll test it >> over the weekend on my RV620. > > Sounds good. Due to problems with running fglrx I didn't manage to test that patch over weekend. As you see some docs and know that registers, I hope this patch is fine. In case of problems we can always easy revert the problematic part :)
2013/4/19 Alex Deucher <alexdeucher@gmail.com>: > On Fri, Apr 19, 2013 at 2:10 AM, Rafa? Mi?ecki <zajec5@gmail.com> wrote: >> 2013/4/18 <alexdeucher@gmail.com>: >>> - switch (radeon_encoder->encoder_id) { >>> - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: >>> - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: >>> - WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); >>> - break; >>> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: >>> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: >>> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: >>> - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: >>> - WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); >>> - break; >>> - default: >>> - dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n", >>> - radeon_encoder->encoder_id); >>> - return; >>> - } >> >> Are you sure we can just drop that part? > > Yes we should be able to drop that part. The only relevant bits are > 9:8 which allows you to force which DTO is used by the audio block. 0 > = auto, 1 = force dto0, 2 = force dto1. Additionally, that register > doesn't exist on evergreen and newer. On evergreen and newer there is > a DIG PHY register at the same offset which may explain the display > problems some people are experiencing. For now I can only say that fglrx seems to be changing that 0x7344: RREG32(0x00000534); -> 0x00000001 DCCG_AUDIO_DTO_SELECT WREG32(0x00000534, 0x00000000); DCCG_AUDIO_DTO_SELECT RREG32(0x00007344); -> 0x00000270 WREG32(0x00007344, 0x00000170); RREG32(0x00000518); -> 0x00000000 DCCG_AUDIO_DTO0_MODULE WREG32(0x00000518, 0x00e297d0); DCCG_AUDIO_DTO0_MODULE RREG32(0x00000514); -> 0x00000000 DCCG_AUDIO_DTO0_PHASE WREG32(0x00000514, 0x00249f00); DCCG_AUDIO_DTO0_PHASE I can't say how well radeon is going to work without that, just informing you about fglrx.
On Mon, Apr 22, 2013 at 1:43 AM, Rafa? Mi?ecki <zajec5@gmail.com> wrote: > 2013/4/19 Alex Deucher <alexdeucher@gmail.com>: >> On Fri, Apr 19, 2013 at 2:10 AM, Rafa? Mi?ecki <zajec5@gmail.com> wrote: >>> 2013/4/18 <alexdeucher@gmail.com>: >>>> - switch (radeon_encoder->encoder_id) { >>>> - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: >>>> - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: >>>> - WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); >>>> - break; >>>> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: >>>> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: >>>> - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: >>>> - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: >>>> - WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); >>>> - break; >>>> - default: >>>> - dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n", >>>> - radeon_encoder->encoder_id); >>>> - return; >>>> - } >>> >>> Are you sure we can just drop that part? >> >> Yes we should be able to drop that part. The only relevant bits are >> 9:8 which allows you to force which DTO is used by the audio block. 0 >> = auto, 1 = force dto0, 2 = force dto1. Additionally, that register >> doesn't exist on evergreen and newer. On evergreen and newer there is >> a DIG PHY register at the same offset which may explain the display >> problems some people are experiencing. > > For now I can only say that fglrx seems to be changing that 0x7344: > > RREG32(0x00000534); -> 0x00000001 DCCG_AUDIO_DTO_SELECT > WREG32(0x00000534, 0x00000000); DCCG_AUDIO_DTO_SELECT Selects DTO0. > > RREG32(0x00007344); -> 0x00000270 > WREG32(0x00007344, 0x00000170); Force audio to use DTO0. I think "auto" should work, but I can add this back for dce2/3 if you'd prefer. > > RREG32(0x00000518); -> 0x00000000 DCCG_AUDIO_DTO0_MODULE > WREG32(0x00000518, 0x00e297d0); DCCG_AUDIO_DTO0_MODULE > RREG32(0x00000514); -> 0x00000000 DCCG_AUDIO_DTO0_PHASE > WREG32(0x00000514, 0x00249f00); DCCG_AUDIO_DTO0_PHASE > Set the DTO0 dividers. > I can't say how well radeon is going to work without that, just > informing you about fglrx. There are two dtos, you can use either one. AUDIO_DTO_SELECT selects whether you are using DTO0 or DTO1. The dtos determine how the audio signal is encoded so that it can be reconstructed in the sink. 24Mhz / pixel clock = AUDIO_DTO0_PHASE / AUDIO_DTO0_MODULE The current code needs to be updated to calculate this properly at some point. Alex
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 380933b..9fc22ee 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -85,6 +85,30 @@ static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder, frame[0xC] | (frame[0xD] << 8)); } +static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 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 = 48000; + + if (!dig || !dig->afmt) + return; + + /* XXX: properly calculate this */ + /* 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 + */ + WREG32(DCCG_AUDIO_DTO0_PHASE, (base_rate*50) & 0xffffff); + WREG32(DCCG_AUDIO_DTO0_MODULE, (clock*100) & 0xffffff); + WREG32(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL(radeon_crtc->crtc_id)); +} + + /* * update the info frames with the data from the current display mode */ @@ -104,7 +128,7 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode return; offset = dig->afmt->offset; - r600_audio_set_clock(encoder, mode->clock); + evergreen_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/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c index 72561e4..c92eb86 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c @@ -181,65 +181,6 @@ int r600_audio_init(struct radeon_device *rdev) } /* - * atach the audio codec to the clock source of the encoder - */ -void r600_audio_set_clock(struct drm_encoder *encoder, 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); - int base_rate = 48000; - - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: - case ENCODER_OBJECT_ID_INTERNAL_LVTM1: - WREG32_P(R600_AUDIO_TIMING, 0, ~0x301); - break; - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301); - break; - default: - dev_err(rdev->dev, "Unsupported encoder type 0x%02X\n", - radeon_encoder->encoder_id); - return; - } - - if (ASIC_IS_DCE4(rdev)) { - /* TODO: other PLLs? */ - WREG32(EVERGREEN_AUDIO_PLL1_MUL, base_rate * 10); - WREG32(EVERGREEN_AUDIO_PLL1_DIV, clock * 10); - WREG32(EVERGREEN_AUDIO_PLL1_UNK, 0x00000071); - - /* Select DTO source */ - WREG32(0x5ac, radeon_crtc->crtc_id); - } else { - switch (dig->dig_encoder) { - case 0: - WREG32(R600_AUDIO_PLL1_MUL, base_rate * 50); - WREG32(R600_AUDIO_PLL1_DIV, clock * 100); - WREG32(R600_AUDIO_CLK_SRCSEL, 0); - break; - - case 1: - WREG32(R600_AUDIO_PLL2_MUL, base_rate * 50); - WREG32(R600_AUDIO_PLL2_DIV, clock * 100); - WREG32(R600_AUDIO_CLK_SRCSEL, 1); - break; - default: - dev_err(rdev->dev, - "Unsupported DIG on encoder 0x%02X\n", - radeon_encoder->encoder_id); - return; - } - } -} - -/* * release the audio timer * TODO: How to do this correctly on SMP systems? */ diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 95397b2..62721bf 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -226,6 +226,30 @@ static 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) +{ + 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 = 48000; + + if (!dig || !dig->afmt) + return; + + /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT. + * doesn't matter which one you use. Just use the first one. + */ + /* XXX: properly calculate this */ + /* 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 + */ + WREG32(DCCG_AUDIO_DTO0_PHASE, (base_rate*50) & 0xffffff); + WREG32(DCCG_AUDIO_DTO0_MODULE, (clock*100) & 0xffffff); + WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */ +} /* * update the info frames with the data from the current display mode @@ -246,7 +270,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod return; offset = dig->afmt->offset; - r600_audio_set_clock(encoder, mode->clock); + r600_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/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 2add526..fa8b8bf 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -374,7 +374,6 @@ void r600_disable_interrupts(struct radeon_device *rdev); void r600_rlc_stop(struct radeon_device *rdev); /* r600 audio */ int r600_audio_init(struct radeon_device *rdev); -void r600_audio_set_clock(struct drm_encoder *encoder, int clock); struct r600_audio r600_audio_status(struct radeon_device *rdev); void r600_audio_fini(struct radeon_device *rdev); int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);