diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_eld.c | 49 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 42 | ||||
-rw-r--r-- | sound/pci/hda/patch_intelhdmi.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_nvhdmi.c | 4 |
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 | } |
597 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); | 597 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); |
598 | 598 | ||
599 | /* update PCM info based on ELD */ | ||
600 | void 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 | } | ||
646 | EXPORT_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 { | |||
604 | int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid); | 604 | int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid); |
605 | int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t); | 605 | int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t); |
606 | void snd_hdmi_show_eld(struct hdmi_eld *eld); | 606 | void snd_hdmi_show_eld(struct hdmi_eld *eld); |
607 | void 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 |
609 | int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, | 611 | int 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 | */ | ||
772 | static 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, | |||
347 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { | 347 | static 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 | }, |