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