aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/radeon/r600_hdmi.c42
-rw-r--r--drivers/gpu/drm/radeon/r600d.h7
2 files changed, 49 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index e1dec1339461..6d7128d02493 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -283,6 +283,45 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
283 } 283 }
284} 284}
285 285
286static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
287{
288 struct radeon_device *rdev = encoder->dev->dev_private;
289 struct drm_connector *connector;
290 struct radeon_connector *radeon_connector = NULL;
291 u32 tmp;
292 u8 *sadb;
293 int sad_count;
294
295 list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
296 if (connector->encoder == encoder)
297 radeon_connector = to_radeon_connector(connector);
298 }
299
300 if (!radeon_connector) {
301 DRM_ERROR("Couldn't find encoder's connector\n");
302 return;
303 }
304
305 sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
306 if (sad_count < 0) {
307 DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
308 return;
309 }
310
311 /* program the speaker allocation */
312 tmp = RREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER);
313 tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
314 /* set HDMI mode */
315 tmp |= HDMI_CONNECTION;
316 if (sad_count)
317 tmp |= SPEAKER_ALLOCATION(sadb[0]);
318 else
319 tmp |= SPEAKER_ALLOCATION(5); /* stereo */
320 WREG32(AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER, tmp);
321
322 kfree(sadb);
323}
324
286/* 325/*
287 * update the info frames with the data from the current display mode 326 * update the info frames with the data from the current display mode
288 */ 327 */
@@ -327,6 +366,9 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
327 HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ 366 HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
328 } 367 }
329 368
369 if (ASIC_IS_DCE32(rdev))
370 dce3_2_afmt_write_speaker_allocation(encoder);
371
330 WREG32(HDMI0_ACR_PACKET_CONTROL + offset, 372 WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
331 HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */ 373 HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */
332 HDMI0_ACR_SOURCE); /* select SW CTS value */ 374 HDMI0_ACR_SOURCE); /* select SW CTS value */
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index 7c780839a7f4..44ec7a148c3d 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -960,6 +960,13 @@
960# define DIG_MODE_SDVO 4 960# define DIG_MODE_SDVO 4
961#define DIG1_CNTL 0x79a0 961#define DIG1_CNTL 0x79a0
962 962
963#define AZ_F0_CODEC_PIN0_CONTROL_CHANNEL_SPEAKER 0x71bc
964#define SPEAKER_ALLOCATION(x) (((x) & 0x7f) << 0)
965#define SPEAKER_ALLOCATION_MASK (0x7f << 0)
966#define SPEAKER_ALLOCATION_SHIFT 0
967#define HDMI_CONNECTION (1 << 16)
968#define DP_CONNECTION (1 << 17)
969
963/* rs6xx/rs740 and r6xx share the same HDMI blocks, however, rs6xx has only one 970/* rs6xx/rs740 and r6xx share the same HDMI blocks, however, rs6xx has only one
964 * instance of the blocks while r6xx has 2. DCE 3.0 cards are slightly 971 * instance of the blocks while r6xx has 2. DCE 3.0 cards are slightly
965 * different due to the new DIG blocks, but also have 2 instances. 972 * different due to the new DIG blocks, but also have 2 instances.