From patchwork Mon Oct 28 23:19:16 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anssi Hannula X-Patchwork-Id: 3105301 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 698C0BF924 for ; Tue, 29 Oct 2013 00:09:42 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 79EA82030D for ; Tue, 29 Oct 2013 00:09:41 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id E6710202EB for ; Tue, 29 Oct 2013 00:09:39 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 08C3C822C9468; Mon, 28 Oct 2013 17:09:26 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org X-Greylist: delayed 1198 seconds by postgrey-1.32 at gabe; Mon, 28 Oct 2013 16:59:15 PDT Received: from sinikuusama.dnainternet.net (sinikuusama.dnainternet.net [83.102.40.134]) by gabe.freedesktop.org (Postfix) with ESMTP id 99C80E6376 for ; Mon, 28 Oct 2013 16:59:15 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by sinikuusama.dnainternet.net (Postfix) with ESMTP id 9158E3FB8D; Tue, 29 Oct 2013 01:19:59 +0200 (EET) X-Virus-Scanned: DNA Postiturva at dnainternet.net X-Spam-Score: -1 X-Spam-Level: X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from sinikuusama.dnainternet.net ([83.102.40.134]) by localhost (sinikuusama.dnainternet.net [127.0.0.1]) (DNA Postiturva, port 10041) with ESMTP id Do8ICMOGbuX5; Tue, 29 Oct 2013 01:19:58 +0200 (EET) Received: from luumupuu.dnainternet.net (luumupuu.dnainternet.net [83.102.40.213]) by sinikuusama.dnainternet.net (Postfix) with ESMTP id B37153FA69; Tue, 29 Oct 2013 01:19:58 +0200 (EET) Received: from mail.onse.fi (unknown [109.204.245.192]) by luumupuu.dnainternet.net (Postfix) with ESMTP id 7735D5FA7F; Tue, 29 Oct 2013 01:19:52 +0200 (EET) Received: by mail.onse.fi (Postfix, from userid 501) id 5AA0940479; Tue, 29 Oct 2013 01:19:52 +0200 (EET) From: Anssi Hannula To: Alex Deucher Subject: [PATCH] drm/radeon/audio: fix missing multichannel PCM SAD in some cases Date: Tue, 29 Oct 2013 01:19:16 +0200 Message-Id: <1383002356-2479-1-git-send-email-anssi.hannula@iki.fi> X-Mailer: git-send-email 1.8.1.5 In-Reply-To: <526EE844.4030608@iki.fi> References: <526EE844.4030608@iki.fi> MIME-Version: 1.0 Cc: Takashi Iwai , alsa-devel@alsa-project.org, dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The current code writing SADs to the audio registers seems to assume that there is at most a single SAD per audio format. However, that is not the case. Especially for PCM it is somewhat common for sinks to have two SADs, one for 8-channel and one for 2-channel audio, which may have different supported sample rates (i.e. the sink supports stereo audio at higher sample rates than multichannel audio). Because of this, only the 2-channel SAD may be used if it appears before the 8-channel SAD. Unless other SADs require otherwise, this may cause the ALSA HDA driver to allow stereo playback only. Fix the code to pick the PCM SAD with the highest number of channels, while merging the rate masks of PCM SADs with lower amount of channels into the additional stereo rate mask byte. Technically there are even more cases to handle (multiple non-PCM SADs of the same type, more than two PCM SADs with varying channel counts, etc), but those have not actually been encountered in the field and handling them would be non-trivial. Example affected EDID from Onkyo TX-SR674 specifying 192kHz stereo support and 96kHz 8-channel support (and other 8-channel compressed formats): 00ffffffffffff003dcb010000000001 ffff0103800000780a0dc9a057479827 12484c00000001010101010101010101 010101010101011d8018711c1620582c 2500c48e2100009e011d007251d01e20 6e285500c48e2100001e000000fc0054 582d53523637342020202020000000fd 00313d0f2e08000a202020202020019b 02032f724f8504030f0e07069413121e 1d1615012f097f070f1f071707503707 503f07c0834f000066030c00ffff808c 0ad08a20e02d10103e9600c48e210000 18011d80d0721c1620102c2580c48e21 00009e011d00bc52d01e20b8285540c4 8e2100001e8c0ad090204031200c4055 00c48e210000180000000000000000a8 Signed-off-by: Anssi Hannula Tested-by: Andre Heider Cc: Rafa? Mi?ecki Acked-by: Rafa? Mi?ecki --- drivers/gpu/drm/radeon/dce6_afmt.c | 20 +++++++++++++++----- drivers/gpu/drm/radeon/evergreen_hdmi.c | 20 +++++++++++++++----- drivers/gpu/drm/radeon/r600_hdmi.c | 20 +++++++++++++++----- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 85a69d2..0a0fcee 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -198,20 +198,30 @@ void dce6_afmt_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_ENDPOINT(offset, eld_reg_to_type[i][0], value); } diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index f71ce39..2a4837d 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -139,20 +139,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); } diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index f443010..da5cfa4 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -364,20 +364,30 @@ static void dce3_2_afmt_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); }