From bbbe33900d1f3c4402148ccb85234a741a6606a3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 13 Aug 2010 08:45:23 +0200 Subject: 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 --- sound/pci/hda/hda_eld.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'sound/pci/hda/hda_eld.c') diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index d8da18a9e98..803b298f741 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -596,4 +596,53 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) } EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); +/* update PCM info based on ELD */ +void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm, + struct hda_pcm_stream *codec_pars) +{ + int i; + + pcm->rates = 0; + pcm->formats = 0; + pcm->maxbps = 0; + pcm->channels_min = -1; + pcm->channels_max = 0; + for (i = 0; i < eld->sad_count; i++) { + struct cea_sad *a = &eld->sad[i]; + pcm->rates |= a->rates; + if (a->channels < pcm->channels_min) + pcm->channels_min = a->channels; + if (a->channels > pcm->channels_max) + pcm->channels_max = a->channels; + if (a->format == AUDIO_CODING_TYPE_LPCM) { + if (a->sample_bits & AC_SUPPCM_BITS_16) { + pcm->formats |= SNDRV_PCM_FMTBIT_S16_LE; + if (pcm->maxbps < 16) + pcm->maxbps = 16; + } + if (a->sample_bits & AC_SUPPCM_BITS_20) { + pcm->formats |= SNDRV_PCM_FMTBIT_S32_LE; + if (pcm->maxbps < 20) + pcm->maxbps = 20; + } + if (a->sample_bits & AC_SUPPCM_BITS_24) { + pcm->formats |= SNDRV_PCM_FMTBIT_S32_LE; + if (pcm->maxbps < 24) + pcm->maxbps = 24; + } + } + } + + if (!codec_pars) + return; + + /* restrict the parameters by the values the codec provides */ + pcm->rates &= codec_pars->rates; + pcm->formats &= codec_pars->formats; + pcm->channels_min = max(pcm->channels_min, codec_pars->channels_min); + pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max); + pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps); +} +EXPORT_SYMBOL_HDA(hdmi_eld_update_pcm_info); + #endif /* CONFIG_PROC_FS */ -- cgit v1.2.3-18-g5258