aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_eld.c49
-rw-r--r--sound/pci/hda/hda_local.h2
-rw-r--r--sound/pci/hda/patch_hdmi.c42
-rw-r--r--sound/pci/hda/patch_intelhdmi.c1
-rw-r--r--sound/pci/hda/patch_nvhdmi.c4
5 files changed, 95 insertions, 3 deletions
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index d8da18a9e98b..803b298f7411 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)
596} 596}
597EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); 597EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free);
598 598
599/* update PCM info based on ELD */
600void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
601 struct hda_pcm_stream *codec_pars)
602{
603 int i;
604
605 pcm->rates = 0;
606 pcm->formats = 0;
607 pcm->maxbps = 0;
608 pcm->channels_min = -1;
609 pcm->channels_max = 0;
610 for (i = 0; i < eld->sad_count; i++) {
611 struct cea_sad *a = &eld->sad[i];
612 pcm->rates |= a->rates;
613 if (a->channels < pcm->channels_min)
614 pcm->channels_min = a->channels;
615 if (a->channels > pcm->channels_max)
616 pcm->channels_max = a->channels;
617 if (a->format == AUDIO_CODING_TYPE_LPCM) {
618 if (a->sample_bits & AC_SUPPCM_BITS_16) {
619 pcm->formats |= SNDRV_PCM_FMTBIT_S16_LE;
620 if (pcm->maxbps < 16)
621 pcm->maxbps = 16;
622 }
623 if (a->sample_bits & AC_SUPPCM_BITS_20) {
624 pcm->formats |= SNDRV_PCM_FMTBIT_S32_LE;
625 if (pcm->maxbps < 20)
626 pcm->maxbps = 20;
627 }
628 if (a->sample_bits & AC_SUPPCM_BITS_24) {
629 pcm->formats |= SNDRV_PCM_FMTBIT_S32_LE;
630 if (pcm->maxbps < 24)
631 pcm->maxbps = 24;
632 }
633 }
634 }
635
636 if (!codec_pars)
637 return;
638
639 /* restrict the parameters by the values the codec provides */
640 pcm->rates &= codec_pars->rates;
641 pcm->formats &= codec_pars->formats;
642 pcm->channels_min = max(pcm->channels_min, codec_pars->channels_min);
643 pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max);
644 pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps);
645}
646EXPORT_SYMBOL_HDA(hdmi_eld_update_pcm_info);
647
599#endif /* CONFIG_PROC_FS */ 648#endif /* CONFIG_PROC_FS */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 7a97f126f6f7..28ab4aead48f 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -604,6 +604,8 @@ struct hdmi_eld {
604int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid); 604int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
605int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t); 605int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t);
606void snd_hdmi_show_eld(struct hdmi_eld *eld); 606void snd_hdmi_show_eld(struct hdmi_eld *eld);
607void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
608 struct hda_pcm_stream *codec_pars);
607 609
608#ifdef CONFIG_PROC_FS 610#ifdef CONFIG_PROC_FS
609int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, 611int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
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 {
46 * export one pcm per pipe 46 * export one pcm per pipe
47 */ 47 */
48 struct hda_pcm pcm_rec[MAX_HDMI_CVTS]; 48 struct hda_pcm pcm_rec[MAX_HDMI_CVTS];
49 struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS];
49 50
50 /* 51 /*
51 * nvhdmi specific 52 * nvhdmi specific
@@ -766,6 +767,47 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
766} 767}
767 768
768/* 769/*
770 * HDA PCM callbacks
771 */
772static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
773 struct hda_codec *codec,
774 struct snd_pcm_substream *substream)
775{
776 struct hdmi_spec *spec = codec->spec;
777 struct hdmi_eld *eld;
778 struct hda_pcm_stream *codec_pars;
779 unsigned int idx;
780
781 for (idx = 0; idx < spec->num_cvts; idx++)
782 if (hinfo->nid == spec->cvt[idx])
783 break;
784 if (snd_BUG_ON(idx >= spec->num_cvts) ||
785 snd_BUG_ON(idx >= spec->num_pins))
786 return -EINVAL;
787
788 /* save the PCM info the codec provides */
789 codec_pars = &spec->codec_pcm_pars[idx];
790 if (!codec_pars->rates)
791 *codec_pars = *hinfo;
792
793 eld = &spec->sink_eld[idx];
794 if (eld->sad_count > 0) {
795 hdmi_eld_update_pcm_info(eld, hinfo, codec_pars);
796 if (hinfo->channels_min > hinfo->channels_max ||
797 !hinfo->rates || !hinfo->formats)
798 return -ENODEV;
799 } else {
800 /* fallback to the codec default */
801 hinfo->channels_min = codec_pars->channels_min;
802 hinfo->channels_max = codec_pars->channels_max;
803 hinfo->rates = codec_pars->rates;
804 hinfo->formats = codec_pars->formats;
805 hinfo->maxbps = codec_pars->maxbps;
806 }
807 return 0;
808}
809
810/*
769 * HDA/HDMI auto parsing 811 * HDA/HDMI auto parsing
770 */ 812 */
771 813
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
index 5972d5e7d01f..d382d3c81c0f 100644
--- a/sound/pci/hda/patch_intelhdmi.c
+++ b/sound/pci/hda/patch_intelhdmi.c
@@ -80,6 +80,7 @@ static struct hda_pcm_stream intel_hdmi_pcm_playback = {
80 .substreams = 1, 80 .substreams = 1,
81 .channels_min = 2, 81 .channels_min = 2,
82 .ops = { 82 .ops = {
83 .open = hdmi_pcm_open,
83 .prepare = intel_hdmi_playback_pcm_prepare, 84 .prepare = intel_hdmi_playback_pcm_prepare,
84 .cleanup = intel_hdmi_playback_pcm_cleanup, 85 .cleanup = intel_hdmi_playback_pcm_cleanup,
85 }, 86 },
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 77e2b4028b9f..f636870dc718 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -347,10 +347,8 @@ static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
347static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { 347static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = {
348 .substreams = 1, 348 .substreams = 1,
349 .channels_min = 2, 349 .channels_min = 2,
350 .rates = SUPPORTED_RATES,
351 .maxbps = SUPPORTED_MAXBPS,
352 .formats = SUPPORTED_FORMATS,
353 .ops = { 350 .ops = {
351 .open = hdmi_pcm_open,
354 .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89, 352 .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89,
355 .cleanup = nvhdmi_playback_pcm_cleanup, 353 .cleanup = nvhdmi_playback_pcm_cleanup,
356 }, 354 },