summaryrefslogtreecommitdiff
path: root/sound/pci/hda/patch_hdmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r--sound/pci/hda/patch_hdmi.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index e287015cbbb3..b03efbc17132 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -34,6 +34,11 @@
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/jack.h>
+
+#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA
+#include <mach/hdmi-audio.h>
+#endif
+
#include "hda_codec.h"
#include "hda_local.h"
@@ -865,6 +870,34 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
hinfo->formats = per_cvt->formats;
hinfo->maxbps = per_cvt->maxbps;
+#ifdef CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA
+ if ((codec->preset->id == 0x10de0020) &&
+ (!eld->eld_valid || !eld->sad_count)) {
+ int err = 0;
+ unsigned long timeout;
+
+ if (!eld->eld_valid) {
+ err = tegra_hdmi_setup_hda_presence();
+ if (err < 0) {
+ snd_printk(KERN_WARNING
+ "HDMI: No HDMI device connected\n");
+ return -ENODEV;
+ }
+ }
+
+ timeout = jiffies + msecs_to_jiffies(5000);
+ for (;;) {
+ if (eld->eld_valid && eld->sad_count)
+ break;
+
+ if (time_after(jiffies, timeout))
+ break;
+
+ mdelay(10);
+ }
+ }
+#endif
+
/* Restrict capabilities by ELD if this isn't disabled */
if (!static_hdmi_pcm && eld->eld_valid) {
snd_hdmi_eld_update_pcm_info(eld, hinfo);
@@ -1057,8 +1090,8 @@ static int hdmi_parse_codec(struct hda_codec *codec)
* HDA link is powered off at hot plug or hw initialization time.
*/
#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
- AC_PWRST_EPSS))
+ if ((!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+ AC_PWRST_EPSS)) && (codec->preset->id != 0x10de0020))
codec->bus->power_keep_link_on = 1;
#endif
@@ -1089,6 +1122,21 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
int pin_idx = hinfo_to_pin_index(spec, hinfo);
hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid;
+#if defined(CONFIG_SND_HDA_PLATFORM_NVIDIA_TEGRA) && defined(CONFIG_TEGRA_DC)
+ if (codec->preset->id == 0x10de0020) {
+ int err = 0;
+ /* Set hdmi:audio freq and source selection*/
+ err = tegra_hdmi_setup_audio_freq_source(
+ substream->runtime->rate, HDA);
+ if ( err < 0 ) {
+ snd_printk(KERN_ERR
+ "Unable to set hdmi audio freq to %d \n",
+ substream->runtime->rate);
+ return err;
+ }
+ }
+#endif
+
hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels);
hdmi_setup_audio_infoframe(codec, pin_idx, substream);
@@ -1189,6 +1237,14 @@ static int generic_hdmi_init(struct hda_codec *codec)
struct hdmi_spec *spec = codec->spec;
int pin_idx;
+ switch (codec->preset->id) {
+ case 0x10de0020:
+ snd_hda_codec_write(codec, 4, 0,
+ AC_VERB_SET_DIGI_CONVERT_1, 0x11);
+ default:
+ break;
+ }
+
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
hda_nid_t pin_nid = per_pin->pin_nid;
@@ -1803,6 +1859,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_generic_hdmi },
{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_generic_hdmi },
{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_generic_hdmi },
+{ .id = 0x10de0020, .name = "Tegra30 HDMI", .patch = patch_generic_hdmi },
{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_generic_hdmi },
{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_generic_hdmi },
{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi },
@@ -1848,6 +1905,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0019");
MODULE_ALIAS("snd-hda-codec-id:10de001a");
MODULE_ALIAS("snd-hda-codec-id:10de001b");
MODULE_ALIAS("snd-hda-codec-id:10de001c");
+MODULE_ALIAS("snd-hda-codec-id:10de0020");
MODULE_ALIAS("snd-hda-codec-id:10de0040");
MODULE_ALIAS("snd-hda-codec-id:10de0041");
MODULE_ALIAS("snd-hda-codec-id:10de0042");