From: Slava Grigorev <slava.grigorev@xxxxxxx> Signed-off-by: Slava Grigorev <slava.grigorev@xxxxxxx> Signed-off-by: Alex Deucher <alexander.deucher@xxxxxxx> --- drivers/gpu/drm/radeon/dce3_1_afmt.c | 49 ++++++++++------------- drivers/gpu/drm/radeon/dce6_afmt.c | 50 ++++++++++++----------- drivers/gpu/drm/radeon/evergreen_hdmi.c | 54 ++++++++++--------------- drivers/gpu/drm/radeon/radeon_audio.c | 71 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_audio.h | 3 ++ 5 files changed, 144 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c index c74431e..613e611 100644 --- a/drivers/gpu/drm/radeon/dce3_1_afmt.c +++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c @@ -27,35 +27,14 @@ #include "radeon_audio.h" #include "r600d.h" -static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder) +void dce3_2_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count) { struct radeon_device *rdev = encoder->dev->dev_private; - struct drm_connector *connector; - struct radeon_connector *radeon_connector = NULL; u32 tmp; - u8 *sadb = NULL; - int sad_count; - - list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - radeon_connector = to_radeon_connector(connector); - break; - } - } - - if (!radeon_connector) { - DRM_ERROR("Couldn't find encoder's connector\n"); - return; - } - - sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); - if (sad_count < 0) { - DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); - sad_count = 0; - } /* program the speaker allocation */ - tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); + tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); /* set HDMI mode */ tmp |= HDMI_CONNECTION; @@ -63,9 +42,25 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder) tmp |= SPEAKER_ALLOCATION(sadb[0]); else tmp |= SPEAKER_ALLOCATION(5); /* stereo */ - WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); + WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); +} - kfree(sadb); +void dce3_2_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + u32 tmp; + + /* program the speaker allocation */ + tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); + tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); + /* set DP mode */ + tmp |= DP_CONNECTION; + if (sad_count) + tmp |= SPEAKER_ALLOCATION(sadb[0]); + else + tmp |= SPEAKER_ALLOCATION(5); /* stereo */ + WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); } void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder, @@ -167,7 +162,7 @@ void dce3_1_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *m } if (ASIC_IS_DCE32(rdev)) { - dce3_2_afmt_write_speaker_allocation(encoder); + radeon_audio_write_speaker_allocation(encoder); radeon_audio_write_sad_regs(encoder); } diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index f263eaa..a24c95a 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -144,40 +144,19 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp); } -void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder) +void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count) { struct radeon_device *rdev = encoder->dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - struct drm_connector *connector; - struct radeon_connector *radeon_connector = NULL; u32 offset, tmp; - u8 *sadb = NULL; - int sad_count; if (!dig || !dig->afmt || !dig->afmt->pin) return; offset = dig->afmt->pin->offset; - list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - radeon_connector = to_radeon_connector(connector); - break; - } - } - - if (!radeon_connector) { - DRM_ERROR("Couldn't find encoder's connector\n"); - return; - } - - sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb); - if (sad_count < 0) { - DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); - sad_count = 0; - } - /* program the speaker allocation */ tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); @@ -188,8 +167,31 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder) else tmp |= SPEAKER_ALLOCATION(5); /* stereo */ WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); +} - kfree(sadb); +void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + u32 offset, tmp; + + if (!dig || !dig->afmt || !dig->afmt->pin) + return; + + offset = dig->afmt->pin->offset; + + /* program the speaker allocation */ + tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); + tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); + /* set DP mode */ + tmp |= DP_CONNECTION; + if (sad_count) + tmp |= SPEAKER_ALLOCATION(sadb[0]); + else + tmp |= SPEAKER_ALLOCATION(5); /* stereo */ + WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp); } void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index dd142e3..3a9bb04 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -33,7 +33,6 @@ #include "evergreend.h" #include "atom.h" -extern void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder); extern void dce6_afmt_select_pin(struct drm_encoder *encoder); extern void dce6_afmt_write_latency_fields(struct drm_encoder *encoder, struct drm_display_mode *mode); @@ -127,35 +126,14 @@ static void dce4_afmt_write_latency_fields(struct drm_encoder *encoder, WREG32(AZ_F0_CODEC_PIN0_CONTROL_RESPONSE_LIPSYNC, tmp); } -static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder) +void dce4_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count) { struct radeon_device *rdev = encoder->dev->dev_private; - struct drm_connector *connector; - struct radeon_connector *radeon_connector = NULL; u32 tmp; - u8 *sadb = NULL; - int sad_count; - - list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - radeon_connector = to_radeon_connector(connector); - break; - } - } - - if (!radeon_connector) { - DRM_ERROR("Couldn't find encoder's connector\n"); - return; - } - - sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb); - if (sad_count < 0) { - DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); - sad_count = 0; - } /* program the speaker allocation */ - tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); + tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK); /* set HDMI mode */ tmp |= HDMI_CONNECTION; @@ -163,9 +141,25 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder) tmp |= SPEAKER_ALLOCATION(sadb[0]); else tmp |= SPEAKER_ALLOCATION(5); /* stereo */ - WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); + WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); +} - kfree(sadb); +void dce4_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count) +{ + struct radeon_device *rdev = encoder->dev->dev_private; + u32 tmp; + + /* program the speaker allocation */ + tmp = RREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER); + tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK); + /* set DP mode */ + tmp |= DP_CONNECTION; + if (sad_count) + tmp |= SPEAKER_ALLOCATION(sadb[0]); + else + tmp |= SPEAKER_ALLOCATION(5); /* stereo */ + WREG32_ENDPOINT(0, AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp); } void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder, @@ -417,11 +411,7 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode AFMT_60958_CS_CHANNEL_NUMBER_6(7) | AFMT_60958_CS_CHANNEL_NUMBER_7(8)); - if (ASIC_IS_DCE6(rdev)) { - dce6_afmt_write_speaker_allocation(encoder); - } else { - dce4_afmt_write_speaker_allocation(encoder); - } + radeon_audio_write_speaker_allocation(encoder); WREG32(AFMT_AUDIO_PACKET_CONTROL2 + offset, AFMT_AUDIO_CHANNEL_ENABLE(0xff)); diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c index 0fc7a93..f359a29 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.c +++ b/drivers/gpu/drm/radeon/radeon_audio.c @@ -41,6 +41,18 @@ void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder, struct cea_sad *sads, int sad_count); void dce6_afmt_write_sad_regs(struct drm_encoder *encoder, struct cea_sad *sads, int sad_count); +void dce3_2_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count); +void dce3_2_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count); +void dce4_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count); +void dce4_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count); +void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count); +void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder, + u8 *sadb, int sad_count); static const u32 pin_offsets[7] = { @@ -103,6 +115,30 @@ static struct radeon_audio_funcs dce6_dp_funcs = { .write_sad_regs = dce6_afmt_write_sad_regs, }; +static struct radeon_audio_funcs dce32_hdmi_funcs = { + .write_speaker_allocation = dce3_2_afmt_hdmi_write_speaker_allocation, +}; + +static struct radeon_audio_funcs dce32_dp_funcs = { + .write_speaker_allocation = dce3_2_afmt_dp_write_speaker_allocation, +}; + +static struct radeon_audio_funcs dce4_hdmi_funcs = { + .write_speaker_allocation = dce4_afmt_hdmi_write_speaker_allocation, +}; + +static struct radeon_audio_funcs dce4_dp_funcs = { + .write_speaker_allocation = dce4_afmt_dp_write_speaker_allocation, +}; + +static struct radeon_audio_funcs dce6_hdmi_funcs = { + .write_speaker_allocation = dce6_afmt_hdmi_write_speaker_allocation, +}; + +static struct radeon_audio_funcs dce6_dp_funcs = { + .write_speaker_allocation = dce6_afmt_dp_write_speaker_allocation, +}; + static void radeon_audio_interface_init(struct radeon_device *rdev) { if (ASIC_IS_DCE6(rdev)) { @@ -254,3 +290,38 @@ void radeon_audio_write_sad_regs(struct drm_encoder *encoder) kfree(sads); } + +void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder) +{ + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_connector *connector; + struct radeon_connector *radeon_connector = NULL; + u8 *sadb = NULL; + int sad_count; + + list_for_each_entry(connector, + &encoder->dev->mode_config.connector_list, head) { + if (connector->encoder == encoder) { + radeon_connector = to_radeon_connector(connector); + break; + } + } + + if (!radeon_connector) { + DRM_ERROR("Couldn't find encoder's connector\n"); + return; + } + + sad_count = drm_edid_to_speaker_allocation( + radeon_connector_edid(connector), &sadb); + if (sad_count < 0) { + DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", + sad_count); + sad_count = 0; + } + + if (radeon_encoder->audio && radeon_encoder->audio->write_speaker_allocation) + radeon_encoder->audio->write_speaker_allocation(encoder, sadb, sad_count); + + kfree(sadb); +} diff --git a/drivers/gpu/drm/radeon/radeon_audio.h b/drivers/gpu/drm/radeon/radeon_audio.h index ea3594e..cc0596f 100644 --- a/drivers/gpu/drm/radeon/radeon_audio.h +++ b/drivers/gpu/drm/radeon/radeon_audio.h @@ -43,6 +43,8 @@ struct radeon_audio_funcs { void (*write_sad_regs)(struct drm_encoder *encoder, struct cea_sad *sads, int sad_count); + void (*write_speaker_allocation)(struct drm_encoder *encoder, + u8 *sadb, int sad_count); }; int radeon_audio_init(struct radeon_device *rdev); @@ -53,5 +55,6 @@ u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset, u32 reg, u32 v); void radeon_audio_write_sad_regs(struct drm_encoder *encoder); +void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder); #endif -- 1.8.3.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel