diff options
-rw-r--r-- | drivers/gpu/drm/radeon/r600_hdmi.c | 42 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600d.h | 7 |
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 | ||
286 | static 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. |