summaryrefslogtreecommitdiff
path: root/sound/pci
diff options
context:
space:
mode:
authorNikesh Oswal <noswal@nvidia.com>2012-09-13 14:28:02 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 12:34:29 -0700
commitef016d03e928e6be747f8fc9a5425b3c037c932f (patch)
tree6e3dbf29a53bdb331f6965ac2fea3901c9617f0c /sound/pci
parentea25ecb53a9045c4a43ba1de643c9c21a04026ed (diff)
ALSA: hda: check validity of speaker allocation field
Kernel 3.1 hda driver read the eld data once and if the speaker allocation field was 0 (not set yet by hdmi driver) then it considers it as 0xFFFF which allows multichannel and doesn't block it. In Kernel 3.4 hda driver there is a repolling mechanism added for ELD data, if the ELD data sanity check fails then HDA driver re-schedules the work unit to poll ELD data again hence the check on speaker allocation field was removed. But the NVIDIA hda/hdmi controller for some reason fails to update the speaker allocation field and the read data is not valid even after repeated attempts, hence the ASP channel mapping happens for default 2 channel case. Adding the check for speaker allocation field again solves the issue and multichannel content plays fine over hda/hdmi. Bug 1045435 Bug 1043021 Change-Id: I79fe33c0e354142f5af16c3ebbb3611a733dd88d Signed-off-by: Nikesh Oswal <noswal@nvidia.com> Reviewed-on: http://git-master/r/132128 Reviewed-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-by: Scott Peterson <speterson@nvidia.com> Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com> Rebase-Id: Racb3856e878119e64f393a578e9c6cae0e3ab4f4
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/patch_hdmi.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index e975fe5661f6..d048fa1f9418 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -964,6 +964,9 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
int pin_nid;
int pin_idx;
struct hda_jack_tbl *jack;
+#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA
+ struct hdmi_eld *eld = &spec->pins[pin_idx].sink_eld;
+#endif
jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
if (!jack)
@@ -981,6 +984,19 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
return;
hdmi_present_sense(get_pin(spec, pin_idx), 1);
+
+#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA
+ if (codec->preset->id == 0x10de0020) {
+ /*
+ * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+ * in console or for audio devices. Assume the highest speakers
+ * configuration, to _not_ prohibit multi-channel audio playback
+ */
+ if (!eld->spk_alloc)
+ eld->spk_alloc = 0xffff;
+ }
+#endif
+
snd_hda_jack_report_sync(codec);
}
@@ -1305,11 +1321,27 @@ static void hdmi_repoll_eld(struct work_struct *work)
{
struct hdmi_spec_per_pin *per_pin =
container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work);
+#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA
+ struct hda_codec *codec = per_pin->codec;
+ struct hdmi_eld *eld = &per_pin->sink_eld;
+#endif
if (per_pin->repoll_count++ > 6)
per_pin->repoll_count = 0;
hdmi_present_sense(per_pin, per_pin->repoll_count);
+
+#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA
+ if (codec->preset->id == 0x10de0020) {
+ /*
+ * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+ * in console or for audio devices. Assume the highest speakers
+ * configuration, to _not_ prohibit multi-channel audio playback
+ */
+ if (!eld->spk_alloc)
+ eld->spk_alloc = 0xffff;
+ }
+#endif
}
static void intel_haswell_fixup_connect_list(struct hda_codec *codec,