aboutsummaryrefslogtreecommitdiffstats
path: root/sound/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-04-16 02:19:06 -0400
committerTakashi Iwai <tiwai@suse.de>2015-04-16 02:47:28 -0400
commitb7d023e11434131e5a7ceb4be33c3afa2c855e89 (patch)
tree76faf07a3123683f002fcf947e2b0e164bb4bd00 /sound/hda
parent602518a21b4c0673fee2146d46be4eb2464553b2 (diff)
ALSA: hda - Move PCM format and rate handling code to core library
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/hda')
-rw-r--r--sound/hda/hdac_device.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c
index f75bf5622687..55c7d086b9dd 100644
--- a/sound/hda/hdac_device.c
+++ b/sound/hda/hdac_device.c
@@ -10,6 +10,7 @@
10#include <linux/pm_runtime.h> 10#include <linux/pm_runtime.h>
11#include <sound/hdaudio.h> 11#include <sound/hdaudio.h>
12#include <sound/hda_regmap.h> 12#include <sound/hda_regmap.h>
13#include <sound/pcm.h>
13#include "local.h" 14#include "local.h"
14 15
15static void setup_fg_nodes(struct hdac_device *codec); 16static void setup_fg_nodes(struct hdac_device *codec);
@@ -597,3 +598,302 @@ static int get_codec_vendor_name(struct hdac_device *codec)
597 codec->vendor_name = kasprintf(GFP_KERNEL, "Generic %04x", vendor_id); 598 codec->vendor_name = kasprintf(GFP_KERNEL, "Generic %04x", vendor_id);
598 return codec->vendor_name ? 0 : -ENOMEM; 599 return codec->vendor_name ? 0 : -ENOMEM;
599} 600}
601
602/*
603 * stream formats
604 */
605struct hda_rate_tbl {
606 unsigned int hz;
607 unsigned int alsa_bits;
608 unsigned int hda_fmt;
609};
610
611/* rate = base * mult / div */
612#define HDA_RATE(base, mult, div) \
613 (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \
614 (((div) - 1) << AC_FMT_DIV_SHIFT))
615
616static struct hda_rate_tbl rate_bits[] = {
617 /* rate in Hz, ALSA rate bitmask, HDA format value */
618
619 /* autodetected value used in snd_hda_query_supported_pcm */
620 { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) },
621 { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) },
622 { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) },
623 { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) },
624 { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) },
625 { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) },
626 { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) },
627 { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) },
628 { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) },
629 { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) },
630 { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) },
631#define AC_PAR_PCM_RATE_BITS 11
632 /* up to bits 10, 384kHZ isn't supported properly */
633
634 /* not autodetected value */
635 { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) },
636
637 { 0 } /* terminator */
638};
639
640/**
641 * snd_hdac_calc_stream_format - calculate the format bitset
642 * @rate: the sample rate
643 * @channels: the number of channels
644 * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
645 * @maxbps: the max. bps
646 * @spdif_ctls: HD-audio SPDIF status bits (0 if irrelevant)
647 *
648 * Calculate the format bitset from the given rate, channels and th PCM format.
649 *
650 * Return zero if invalid.
651 */
652unsigned int snd_hdac_calc_stream_format(unsigned int rate,
653 unsigned int channels,
654 unsigned int format,
655 unsigned int maxbps,
656 unsigned short spdif_ctls)
657{
658 int i;
659 unsigned int val = 0;
660
661 for (i = 0; rate_bits[i].hz; i++)
662 if (rate_bits[i].hz == rate) {
663 val = rate_bits[i].hda_fmt;
664 break;
665 }
666 if (!rate_bits[i].hz)
667 return 0;
668
669 if (channels == 0 || channels > 8)
670 return 0;
671 val |= channels - 1;
672
673 switch (snd_pcm_format_width(format)) {
674 case 8:
675 val |= AC_FMT_BITS_8;
676 break;
677 case 16:
678 val |= AC_FMT_BITS_16;
679 break;
680 case 20:
681 case 24:
682 case 32:
683 if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE)
684 val |= AC_FMT_BITS_32;
685 else if (maxbps >= 24)
686 val |= AC_FMT_BITS_24;
687 else
688 val |= AC_FMT_BITS_20;
689 break;
690 default:
691 return 0;
692 }
693
694 if (spdif_ctls & AC_DIG1_NONAUDIO)
695 val |= AC_FMT_TYPE_NON_PCM;
696
697 return val;
698}
699EXPORT_SYMBOL_GPL(snd_hdac_calc_stream_format);
700
701static unsigned int query_pcm_param(struct hdac_device *codec, hda_nid_t nid)
702{
703 unsigned int val = 0;
704
705 if (nid != codec->afg &&
706 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
707 val = snd_hdac_read_parm(codec, nid, AC_PAR_PCM);
708 if (!val || val == -1)
709 val = snd_hdac_read_parm(codec, codec->afg, AC_PAR_PCM);
710 if (!val || val == -1)
711 return 0;
712 return val;
713}
714
715static unsigned int query_stream_param(struct hdac_device *codec, hda_nid_t nid)
716{
717 unsigned int streams = snd_hdac_read_parm(codec, nid, AC_PAR_STREAM);
718
719 if (!streams || streams == -1)
720 streams = snd_hdac_read_parm(codec, codec->afg, AC_PAR_STREAM);
721 if (!streams || streams == -1)
722 return 0;
723 return streams;
724}
725
726/**
727 * snd_hdac_query_supported_pcm - query the supported PCM rates and formats
728 * @codec: the codec object
729 * @nid: NID to query
730 * @ratesp: the pointer to store the detected rate bitflags
731 * @formatsp: the pointer to store the detected formats
732 * @bpsp: the pointer to store the detected format widths
733 *
734 * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
735 * or @bsps argument is ignored.
736 *
737 * Returns 0 if successful, otherwise a negative error code.
738 */
739int snd_hdac_query_supported_pcm(struct hdac_device *codec, hda_nid_t nid,
740 u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
741{
742 unsigned int i, val, wcaps;
743
744 wcaps = get_wcaps(codec, nid);
745 val = query_pcm_param(codec, nid);
746
747 if (ratesp) {
748 u32 rates = 0;
749 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
750 if (val & (1 << i))
751 rates |= rate_bits[i].alsa_bits;
752 }
753 if (rates == 0) {
754 dev_err(&codec->dev,
755 "rates == 0 (nid=0x%x, val=0x%x, ovrd=%i)\n",
756 nid, val,
757 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
758 return -EIO;
759 }
760 *ratesp = rates;
761 }
762
763 if (formatsp || bpsp) {
764 u64 formats = 0;
765 unsigned int streams, bps;
766
767 streams = query_stream_param(codec, nid);
768 if (!streams)
769 return -EIO;
770
771 bps = 0;
772 if (streams & AC_SUPFMT_PCM) {
773 if (val & AC_SUPPCM_BITS_8) {
774 formats |= SNDRV_PCM_FMTBIT_U8;
775 bps = 8;
776 }
777 if (val & AC_SUPPCM_BITS_16) {
778 formats |= SNDRV_PCM_FMTBIT_S16_LE;
779 bps = 16;
780 }
781 if (wcaps & AC_WCAP_DIGITAL) {
782 if (val & AC_SUPPCM_BITS_32)
783 formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
784 if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
785 formats |= SNDRV_PCM_FMTBIT_S32_LE;
786 if (val & AC_SUPPCM_BITS_24)
787 bps = 24;
788 else if (val & AC_SUPPCM_BITS_20)
789 bps = 20;
790 } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
791 AC_SUPPCM_BITS_32)) {
792 formats |= SNDRV_PCM_FMTBIT_S32_LE;
793 if (val & AC_SUPPCM_BITS_32)
794 bps = 32;
795 else if (val & AC_SUPPCM_BITS_24)
796 bps = 24;
797 else if (val & AC_SUPPCM_BITS_20)
798 bps = 20;
799 }
800 }
801#if 0 /* FIXME: CS4206 doesn't work, which is the only codec supporting float */
802 if (streams & AC_SUPFMT_FLOAT32) {
803 formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
804 if (!bps)
805 bps = 32;
806 }
807#endif
808 if (streams == AC_SUPFMT_AC3) {
809 /* should be exclusive */
810 /* temporary hack: we have still no proper support
811 * for the direct AC3 stream...
812 */
813 formats |= SNDRV_PCM_FMTBIT_U8;
814 bps = 8;
815 }
816 if (formats == 0) {
817 dev_err(&codec->dev,
818 "formats == 0 (nid=0x%x, val=0x%x, ovrd=%i, streams=0x%x)\n",
819 nid, val,
820 (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
821 streams);
822 return -EIO;
823 }
824 if (formatsp)
825 *formatsp = formats;
826 if (bpsp)
827 *bpsp = bps;
828 }
829
830 return 0;
831}
832EXPORT_SYMBOL_GPL(snd_hdac_query_supported_pcm);
833
834/**
835 * snd_hdac_is_supported_format - Check the validity of the format
836 * @codec: the codec object
837 * @nid: NID to check
838 * @format: the HD-audio format value to check
839 *
840 * Check whether the given node supports the format value.
841 *
842 * Returns true if supported, false if not.
843 */
844bool snd_hdac_is_supported_format(struct hdac_device *codec, hda_nid_t nid,
845 unsigned int format)
846{
847 int i;
848 unsigned int val = 0, rate, stream;
849
850 val = query_pcm_param(codec, nid);
851 if (!val)
852 return false;
853
854 rate = format & 0xff00;
855 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
856 if (rate_bits[i].hda_fmt == rate) {
857 if (val & (1 << i))
858 break;
859 return false;
860 }
861 if (i >= AC_PAR_PCM_RATE_BITS)
862 return false;
863
864 stream = query_stream_param(codec, nid);
865 if (!stream)
866 return false;
867
868 if (stream & AC_SUPFMT_PCM) {
869 switch (format & 0xf0) {
870 case 0x00:
871 if (!(val & AC_SUPPCM_BITS_8))
872 return false;
873 break;
874 case 0x10:
875 if (!(val & AC_SUPPCM_BITS_16))
876 return false;
877 break;
878 case 0x20:
879 if (!(val & AC_SUPPCM_BITS_20))
880 return false;
881 break;
882 case 0x30:
883 if (!(val & AC_SUPPCM_BITS_24))
884 return false;
885 break;
886 case 0x40:
887 if (!(val & AC_SUPPCM_BITS_32))
888 return false;
889 break;
890 default:
891 return false;
892 }
893 } else {
894 /* FIXME: check for float32 and AC3? */
895 }
896
897 return true;
898}
899EXPORT_SYMBOL_GPL(snd_hdac_is_supported_format);