summaryrefslogtreecommitdiff
path: root/sound/pci/hda/patch_hdmi.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-08-13 08:45:23 +0200
committerTakashi Iwai <tiwai@suse.de>2010-08-13 08:45:23 +0200
commitbbbe33900d1f3c4402148ccb85234a741a6606a3 (patch)
tree294143653bfb5a045dea0396b8fee00ed7164b6e /sound/pci/hda/patch_hdmi.c
parent8a345a042ae75097fd493633633382644257cfc3 (diff)
ALSA: hda - Restrict PCM parameters per ELD information over HDMI
When a device is plugged over HDMI, it passes some information in ELD including the supported PCM parameters like formats, rates, channels. This patch adds the check to PCM open callback of HDMI streams so that only valid parameters the device supports are used. When no device is plugged, the parameters the codec supports are used; it's mostly all parameters the hardware can work. This is for apps that are started before device plugging and do probing (e.g. a sound daemon), so that at least, probing would work even before the device plugging. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r--sound/pci/hda/patch_hdmi.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 522e0748ee99..2bc0f07cf33f 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -46,6 +46,7 @@ struct hdmi_spec {
* export one pcm per pipe
*/
struct hda_pcm pcm_rec[MAX_HDMI_CVTS];
+ struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS];
/*
* nvhdmi specific
@@ -766,6 +767,47 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
}
/*
+ * HDA PCM callbacks
+ */
+static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct hdmi_spec *spec = codec->spec;
+ struct hdmi_eld *eld;
+ struct hda_pcm_stream *codec_pars;
+ unsigned int idx;
+
+ for (idx = 0; idx < spec->num_cvts; idx++)
+ if (hinfo->nid == spec->cvt[idx])
+ break;
+ if (snd_BUG_ON(idx >= spec->num_cvts) ||
+ snd_BUG_ON(idx >= spec->num_pins))
+ return -EINVAL;
+
+ /* save the PCM info the codec provides */
+ codec_pars = &spec->codec_pcm_pars[idx];
+ if (!codec_pars->rates)
+ *codec_pars = *hinfo;
+
+ eld = &spec->sink_eld[idx];
+ if (eld->sad_count > 0) {
+ hdmi_eld_update_pcm_info(eld, hinfo, codec_pars);
+ if (hinfo->channels_min > hinfo->channels_max ||
+ !hinfo->rates || !hinfo->formats)
+ return -ENODEV;
+ } else {
+ /* fallback to the codec default */
+ hinfo->channels_min = codec_pars->channels_min;
+ hinfo->channels_max = codec_pars->channels_max;
+ hinfo->rates = codec_pars->rates;
+ hinfo->formats = codec_pars->formats;
+ hinfo->maxbps = codec_pars->maxbps;
+ }
+ return 0;
+}
+
+/*
* HDA/HDMI auto parsing
*/