aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSubhransu S. Prusty <subhransu.s.prusty@intel.com>2016-02-11 21:16:04 -0500
committerMark Brown <broonie@kernel.org>2016-02-15 15:54:03 -0500
commit17a42c4500b05a6af4c32eb8e9cfc44bab945d1f (patch)
treec201c409f3a48f0d2baa364fd910fc386a155d63
parent211caab73b20dcc91ac103db0f68fe2388120d59 (diff)
ASoC: hdac_hdmi: create dais based on number of cvts
After enabling all pins/cvts, Skylake HDMI codec enumerates 3 converters. Three independent streams can be supported with 3 cvts. This patch removes the static dai creation and creates dais based on the number of cvts queried. Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/hdac_hdmi.c123
1 files changed, 91 insertions, 32 deletions
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index b2e5e549b022..c85deae68064 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -30,6 +30,8 @@
30#include <sound/pcm_drm_eld.h> 30#include <sound/pcm_drm_eld.h>
31#include "../../hda/local.h" 31#include "../../hda/local.h"
32 32
33#define NAME_SIZE 32
34
33#define AMP_OUT_MUTE 0xb080 35#define AMP_OUT_MUTE 0xb080
34#define AMP_OUT_UNMUTE 0xb000 36#define AMP_OUT_UNMUTE 0xb000
35#define PIN_OUT (AC_PINCTL_OUT_EN) 37#define PIN_OUT (AC_PINCTL_OUT_EN)
@@ -669,11 +671,82 @@ static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac)
669 671
670} 672}
671 673
674static struct snd_soc_dai_ops hdmi_dai_ops = {
675 .startup = hdac_hdmi_pcm_open,
676 .shutdown = hdac_hdmi_pcm_close,
677 .hw_params = hdac_hdmi_set_hw_params,
678 .prepare = hdac_hdmi_playback_prepare,
679 .hw_free = hdac_hdmi_playback_cleanup,
680};
681
682/*
683 * Each converter can support a stream independently. So a dai is created
684 * based on the number of converter queried.
685 */
686static int hdac_hdmi_create_dais(struct hdac_device *hdac,
687 struct snd_soc_dai_driver **dais,
688 struct hdac_hdmi_priv *hdmi, int num_dais)
689{
690 struct snd_soc_dai_driver *hdmi_dais;
691 struct hdac_hdmi_cvt *cvt;
692 char name[NAME_SIZE], dai_name[NAME_SIZE];
693 int i = 0;
694 u32 rates, bps;
695 unsigned int rate_max = 384000, rate_min = 8000;
696 u64 formats;
697 int ret;
698
699 hdmi_dais = devm_kzalloc(&hdac->dev,
700 (sizeof(*hdmi_dais) * num_dais),
701 GFP_KERNEL);
702 if (!hdmi_dais)
703 return -ENOMEM;
704
705 list_for_each_entry(cvt, &hdmi->cvt_list, head) {
706 ret = snd_hdac_query_supported_pcm(hdac, cvt->nid,
707 &rates, &formats, &bps);
708 if (ret)
709 return ret;
710
711 sprintf(dai_name, "intel-hdmi-hifi%d", i+1);
712 hdmi_dais[i].name = devm_kstrdup(&hdac->dev,
713 dai_name, GFP_KERNEL);
714
715 if (!hdmi_dais[i].name)
716 return -ENOMEM;
717
718 snprintf(name, sizeof(name), "hifi%d", i+1);
719 hdmi_dais[i].playback.stream_name =
720 devm_kstrdup(&hdac->dev, name, GFP_KERNEL);
721 if (!hdmi_dais[i].playback.stream_name)
722 return -ENOMEM;
723
724 /*
725 * Set caps based on capability queried from the converter.
726 * It will be constrained runtime based on ELD queried.
727 */
728 hdmi_dais[i].playback.formats = formats;
729 hdmi_dais[i].playback.rates = rates;
730 hdmi_dais[i].playback.rate_max = rate_max;
731 hdmi_dais[i].playback.rate_min = rate_min;
732 hdmi_dais[i].playback.channels_min = 2;
733 hdmi_dais[i].playback.channels_max = 2;
734 hdmi_dais[i].ops = &hdmi_dai_ops;
735
736 i++;
737 }
738
739 *dais = hdmi_dais;
740
741 return 0;
742}
743
672/* 744/*
673 * Parse all nodes and store the cvt/pin nids in array 745 * Parse all nodes and store the cvt/pin nids in array
674 * Add one time initialization for pin and cvt widgets 746 * Add one time initialization for pin and cvt widgets
675 */ 747 */
676static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev) 748static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
749 struct snd_soc_dai_driver **dais, int *num_dais)
677{ 750{
678 hda_nid_t nid; 751 hda_nid_t nid;
679 int i, num_nodes; 752 int i, num_nodes;
@@ -724,6 +797,15 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
724 if (!hdmi->num_pin || !hdmi->num_cvt) 797 if (!hdmi->num_pin || !hdmi->num_cvt)
725 return -EIO; 798 return -EIO;
726 799
800 ret = hdac_hdmi_create_dais(hdac, dais, hdmi, hdmi->num_cvt);
801 if (ret) {
802 dev_err(&hdac->dev, "Failed to create dais with err: %d\n",
803 ret);
804 return ret;
805 }
806
807 *num_dais = hdmi->num_cvt;
808
727 return hdac_hdmi_init_dai_map(edev); 809 return hdac_hdmi_init_dai_map(edev);
728} 810}
729 811
@@ -814,38 +896,12 @@ static struct snd_soc_codec_driver hdmi_hda_codec = {
814 .idle_bias_off = true, 896 .idle_bias_off = true,
815}; 897};
816 898
817static struct snd_soc_dai_ops hdmi_dai_ops = {
818 .startup = hdac_hdmi_pcm_open,
819 .shutdown = hdac_hdmi_pcm_close,
820 .hw_params = hdac_hdmi_set_hw_params,
821 .prepare = hdac_hdmi_playback_prepare,
822 .hw_free = hdac_hdmi_playback_cleanup,
823};
824
825static struct snd_soc_dai_driver hdmi_dais[] = {
826 { .name = "intel-hdmi-hif1",
827 .playback = {
828 .stream_name = "hif1",
829 .channels_min = 2,
830 .channels_max = 2,
831 .rates = SNDRV_PCM_RATE_32000 |
832 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
833 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
834 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
835 .formats = SNDRV_PCM_FMTBIT_S16_LE |
836 SNDRV_PCM_FMTBIT_S20_3LE |
837 SNDRV_PCM_FMTBIT_S24_LE |
838 SNDRV_PCM_FMTBIT_S32_LE,
839
840 },
841 .ops = &hdmi_dai_ops,
842 },
843};
844
845static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) 899static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
846{ 900{
847 struct hdac_device *codec = &edev->hdac; 901 struct hdac_device *codec = &edev->hdac;
848 struct hdac_hdmi_priv *hdmi_priv; 902 struct hdac_hdmi_priv *hdmi_priv;
903 struct snd_soc_dai_driver *hdmi_dais = NULL;
904 int num_dais = 0;
849 int ret = 0; 905 int ret = 0;
850 906
851 hdmi_priv = devm_kzalloc(&codec->dev, sizeof(*hdmi_priv), GFP_KERNEL); 907 hdmi_priv = devm_kzalloc(&codec->dev, sizeof(*hdmi_priv), GFP_KERNEL);
@@ -859,13 +915,16 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
859 INIT_LIST_HEAD(&hdmi_priv->pin_list); 915 INIT_LIST_HEAD(&hdmi_priv->pin_list);
860 INIT_LIST_HEAD(&hdmi_priv->cvt_list); 916 INIT_LIST_HEAD(&hdmi_priv->cvt_list);
861 917
862 ret = hdac_hdmi_parse_and_map_nid(edev); 918 ret = hdac_hdmi_parse_and_map_nid(edev, &hdmi_dais, &num_dais);
863 if (ret < 0) 919 if (ret < 0) {
920 dev_err(&codec->dev,
921 "Failed in parse and map nid with err: %d\n", ret);
864 return ret; 922 return ret;
923 }
865 924
866 /* ASoC specific initialization */ 925 /* ASoC specific initialization */
867 return snd_soc_register_codec(&codec->dev, &hdmi_hda_codec, 926 return snd_soc_register_codec(&codec->dev, &hdmi_hda_codec,
868 hdmi_dais, ARRAY_SIZE(hdmi_dais)); 927 hdmi_dais, num_dais);
869} 928}
870 929
871static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev) 930static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)