aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/radeon/evergreen_hdmi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-15 14:19:54 +0900
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-15 14:19:54 +0900
commit049ffa8ab33a63b3bff672d1a0ee6a35ad253fe8 (patch)
tree70f4c684818b1c9871fa800088427e40d260592e /drivers/gpu/drm/radeon/evergreen_hdmi.c
parentc681427e5ca22925fcc1be76a2e260a11e0a8498 (diff)
parent0846c728e20a0cd1e43fb75a3015f3b176a26466 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "This is a combo of -next and some -fixes that came in in the intervening time. Highlights: New drivers: ARM Armada driver for Marvell Armada 510 SOCs Intel: Broadwell initial support under a default off switch, Stereo/3D HDMI mode support Valleyview improvements Displayport improvements Haswell fixes initial mipi dsi panel support CRC support for debugging build with CONFIG_FB=n Radeon: enable DPM on a number of GPUs by default secondary GPU powerdown support enable HDMI audio by default Hawaii support Nouveau: dynamic pm code infrastructure reworked, does nothing major yet GK208 modesetting support MSI fixes, on by default again PMPEG improvements pageflipping fixes GMA500: minnowboard SDVO support VMware: misc fixes MSM: prime, plane and rendernodes support Tegra: rearchitected to put the drm driver into the drm subsystem. HDMI and gr2d support for tegra 114 SoC QXL: oops fix, and multi-head fixes DRM core: sysfs lifetime fixes client capability ioctl further cleanups to device midlayer more vblank timestamp fixes" * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (789 commits) drm/nouveau: do not map evicted vram buffers in nouveau_bo_vma_add drm/nvc0-/gr: shift wrapping bug in nvc0_grctx_generate_r406800 drm/nouveau/pwr: fix missing mutex unlock in a failure path drm/nv40/therm: fix slowing down fan when pstate undefined drm/nv11-: synchronise flips to vblank, unless async flip requested drm/nvc0-: remove nasty fifo swmthd hack for flip completion method drm/nv10-: we no longer need to create nvsw object on user channels drm/nouveau: always queue flips relative to kernel channel activity drm/nouveau: there is no need to reserve/fence the new fb when flipping drm/nouveau: when bailing out of a pushbuf ioctl, do not remove previous fence drm/nouveau: allow nouveau_fence_ref() to be a noop drm/nvc8/mc: msi rearm is via the nvc0 method drm/ttm: Fix vma page_prot bit manipulation drm/vmwgfx: Fix a couple of compile / sparse warnings and errors drm/vmwgfx: Resource evict fixes drm/edid: compare actual vrefresh for all modes for quirks drm: shmob_drm: Convert to clk_prepare/unprepare drm/nouveau: fix 32-bit build drm/i915/opregion: fix build error on CONFIG_ACPI=n Revert "drm/radeon/audio: don't set speaker allocation on DCE4+" ...
Diffstat (limited to 'drivers/gpu/drm/radeon/evergreen_hdmi.c')
-rw-r--r--drivers/gpu/drm/radeon/evergreen_hdmi.c71
1 files changed, 61 insertions, 10 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c
index 57fcc4b16a5..aa695c4feb3 100644
--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c
+++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c
@@ -35,6 +35,8 @@
extern void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder);
extern void dce6_afmt_write_sad_regs(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);
/*
* update the N and CTS parameters for a given pixel clock rate
@@ -58,6 +60,42 @@ static void evergreen_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t cloc
WREG32(HDMI_ACR_48_1 + offset, acr.n_48khz);
}
+static void dce4_afmt_write_latency_fields(struct drm_encoder *encoder,
+ struct drm_display_mode *mode)
+{
+ struct radeon_device *rdev = encoder->dev->dev_private;
+ struct drm_connector *connector;
+ struct radeon_connector *radeon_connector = NULL;
+ u32 tmp = 0;
+
+ 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;
+ }
+
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+ if (connector->latency_present[1])
+ tmp = VIDEO_LIPSYNC(connector->video_latency[1]) |
+ AUDIO_LIPSYNC(connector->audio_latency[1]);
+ else
+ tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255);
+ } else {
+ if (connector->latency_present[0])
+ tmp = VIDEO_LIPSYNC(connector->video_latency[0]) |
+ AUDIO_LIPSYNC(connector->audio_latency[0]);
+ else
+ tmp = VIDEO_LIPSYNC(255) | AUDIO_LIPSYNC(255);
+ }
+ WREG32(AZ_F0_CODEC_PIN0_CONTROL_RESPONSE_LIPSYNC, tmp);
+}
+
static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
{
struct radeon_device *rdev = encoder->dev->dev_private;
@@ -67,12 +105,11 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
u8 *sadb;
int sad_count;
- /* XXX: setting this register causes hangs on some asics */
- return;
-
list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder)
+ if (connector->encoder == encoder) {
radeon_connector = to_radeon_connector(connector);
+ break;
+ }
}
if (!radeon_connector) {
@@ -124,8 +161,10 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
};
list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder)
+ if (connector->encoder == encoder) {
radeon_connector = to_radeon_connector(connector);
+ break;
+ }
}
if (!radeon_connector) {
@@ -142,20 +181,30 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
u32 value = 0;
+ u8 stereo_freqs = 0;
+ int max_channels = -1;
int j;
for (j = 0; j < sad_count; j++) {
struct cea_sad *sad = &sads[j];
if (sad->format == eld_reg_to_type[i][1]) {
- value = MAX_CHANNELS(sad->channels) |
- DESCRIPTOR_BYTE_2(sad->byte2) |
- SUPPORTED_FREQUENCIES(sad->freq);
+ if (sad->channels > max_channels) {
+ value = MAX_CHANNELS(sad->channels) |
+ DESCRIPTOR_BYTE_2(sad->byte2) |
+ SUPPORTED_FREQUENCIES(sad->freq);
+ max_channels = sad->channels;
+ }
+
if (sad->format == HDMI_AUDIO_CODING_TYPE_PCM)
- value |= SUPPORTED_FREQUENCIES_STEREO(sad->freq);
- break;
+ stereo_freqs |= sad->freq;
+ else
+ break;
}
}
+
+ value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
+
WREG32(eld_reg_to_type[i][0], value);
}
@@ -324,8 +373,10 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode
if (ASIC_IS_DCE6(rdev)) {
dce6_afmt_select_pin(encoder);
dce6_afmt_write_sad_regs(encoder);
+ dce6_afmt_write_latency_fields(encoder, mode);
} else {
evergreen_hdmi_write_sad_regs(encoder);
+ dce4_afmt_write_latency_fields(encoder, mode);
}
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);