diff mbox

[v2,08/14] ASoC: hdac_hdmi - create dais based on number of streams

Message ID 1449176942-3441-8-git-send-email-subhransu.s.prusty@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Subhransu S. Prusty Dec. 3, 2015, 9:08 p.m. UTC
A stream is mapped to a converter. So based on the converters
queried, dais are created.

The streams can be dynamically routed to any converter. For
now it is mapped statically. The dynamic mapping of stream
to converter will be added when required.

Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
---
 sound/soc/codecs/hdac_hdmi.c | 124 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 92 insertions(+), 32 deletions(-)

Comments

Takashi Iwai Dec. 3, 2015, 4:13 p.m. UTC | #1
On Thu, 03 Dec 2015 22:08:56 +0100,
Subhransu S. Prusty wrote:
> 
> A stream is mapped to a converter. So based on the converters
> queried, dais are created.
> 
> The streams can be dynamically routed to any converter. For
> now it is mapped statically. The dynamic mapping of stream
> to converter will be added when required.
> 
> Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
> ---
>  sound/soc/codecs/hdac_hdmi.c | 124 ++++++++++++++++++++++++++++++++-----------
>  1 file changed, 92 insertions(+), 32 deletions(-)
> 
> diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
> index 325d22b..83248ad 100644
> --- a/sound/soc/codecs/hdac_hdmi.c
> +++ b/sound/soc/codecs/hdac_hdmi.c
> @@ -29,6 +29,8 @@
>  #include <sound/pcm_drm_eld.h>
>  #include "../../hda/local.h"
>  
> +#define NAME_SIZE	32
> +
>  #define AMP_OUT_MUTE		0xb080
>  #define AMP_OUT_UNMUTE		0xb000
>  #define PIN_OUT			(AC_PINCTL_OUT_EN)
> @@ -640,11 +642,84 @@ static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac)
>  
>  }
>  
> +static struct snd_soc_dai_ops hdmi_dai_ops = {
> +	.startup = hdac_hdmi_pcm_open,
> +	.shutdown = hdac_hdmi_pcm_close,
> +	.hw_params = hdac_hdmi_set_hw_params,
> +	.prepare = hdac_hdmi_playback_prepare,
> +	.hw_free = hdac_hdmi_playback_cleanup,
> +};
> +
> +static int hdac_hdmi_create_dais(struct hdac_device *hdac,
> +		struct snd_soc_dai_driver **dais,
> +		struct hdac_hdmi_priv *hdmi, int num_dais)
> +{
> +	struct snd_soc_dai_driver *hdmi_dais;
> +	struct hdac_hdmi_cvt *cvt;
> +	char name[NAME_SIZE], dai_name[NAME_SIZE];
> +	int i = 0, j;
> +	u32 rates, bps;
> +	unsigned int rate_max = 384000, rate_min = 8000;
> +	u64 formats;
> +	int ret;
> +	static unsigned int rate_pcm[] = {
> +		8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
> +		96000, 176400, 192000, 384000
> +	};
> +
> +	hdmi_dais = devm_kzalloc(&hdac->dev, (sizeof(*hdmi_dais) * num_dais),
> +			GFP_KERNEL);
> +	if (!hdmi_dais)
> +		return -ENOMEM;
> +
> +	list_for_each_entry(cvt, &hdmi->cvt_list, head) {
> +		ret = snd_hdac_query_supported_pcm(hdac, cvt->nid, &rates,
> +			&formats, &bps);
> +		if (ret)
> +			return ret;
> +		for (j = 0; j < ARRAY_SIZE(rate_pcm); j++) {
> +			if (rates & (1 << j)) {
> +				rate_min = rate_pcm[j];
> +				break;
> +			}
> +		}
> +
> +		for (j = ARRAY_SIZE(rate_pcm) - 1; j >= 0; j--) {
> +			if (rates & (1 << j)) {
> +				rate_max = rate_pcm[j];
> +				break;
> +			}
> +		}

This is ugly...  Can't we just set rate_min/max with the fixed numbers
that cover the all possible ranges?  The refinement is done by the
rates bitmap and hw_constraint in anyway.


Takashi
diff mbox

Patch

diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index 325d22b..83248ad 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -29,6 +29,8 @@ 
 #include <sound/pcm_drm_eld.h>
 #include "../../hda/local.h"
 
+#define NAME_SIZE	32
+
 #define AMP_OUT_MUTE		0xb080
 #define AMP_OUT_UNMUTE		0xb000
 #define PIN_OUT			(AC_PINCTL_OUT_EN)
@@ -640,11 +642,84 @@  static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac)
 
 }
 
+static struct snd_soc_dai_ops hdmi_dai_ops = {
+	.startup = hdac_hdmi_pcm_open,
+	.shutdown = hdac_hdmi_pcm_close,
+	.hw_params = hdac_hdmi_set_hw_params,
+	.prepare = hdac_hdmi_playback_prepare,
+	.hw_free = hdac_hdmi_playback_cleanup,
+};
+
+static int hdac_hdmi_create_dais(struct hdac_device *hdac,
+		struct snd_soc_dai_driver **dais,
+		struct hdac_hdmi_priv *hdmi, int num_dais)
+{
+	struct snd_soc_dai_driver *hdmi_dais;
+	struct hdac_hdmi_cvt *cvt;
+	char name[NAME_SIZE], dai_name[NAME_SIZE];
+	int i = 0, j;
+	u32 rates, bps;
+	unsigned int rate_max = 384000, rate_min = 8000;
+	u64 formats;
+	int ret;
+	static unsigned int rate_pcm[] = {
+		8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
+		96000, 176400, 192000, 384000
+	};
+
+	hdmi_dais = devm_kzalloc(&hdac->dev, (sizeof(*hdmi_dais) * num_dais),
+			GFP_KERNEL);
+	if (!hdmi_dais)
+		return -ENOMEM;
+
+	list_for_each_entry(cvt, &hdmi->cvt_list, head) {
+		ret = snd_hdac_query_supported_pcm(hdac, cvt->nid, &rates,
+			&formats, &bps);
+		if (ret)
+			return ret;
+		for (j = 0; j < ARRAY_SIZE(rate_pcm); j++) {
+			if (rates & (1 << j)) {
+				rate_min = rate_pcm[j];
+				break;
+			}
+		}
+
+		for (j = ARRAY_SIZE(rate_pcm) - 1; j >= 0; j--) {
+			if (rates & (1 << j)) {
+				rate_max = rate_pcm[j];
+				break;
+			}
+		}
+
+		sprintf(dai_name, "intel-hdmi-hifi%d", i+1);
+		hdmi_dais[i].name = devm_kstrdup(&hdac->dev, dai_name,
+						GFP_KERNEL);
+
+		snprintf(name, sizeof(name), "hifi%d", i+1);
+		hdmi_dais[i].playback.stream_name =
+				devm_kstrdup(&hdac->dev, name, GFP_KERNEL);
+		hdmi_dais[i].playback.formats = formats;
+		hdmi_dais[i].playback.rates = rates;
+		hdmi_dais[i].playback.rate_max = rate_max;
+		hdmi_dais[i].playback.rate_min = rate_min;
+		hdmi_dais[i].playback.channels_min = 2;
+		hdmi_dais[i].playback.channels_max = 2;
+		hdmi_dais[i].ops = &hdmi_dai_ops;
+
+		i++;
+	}
+
+	*dais = hdmi_dais;
+
+	return 0;
+}
+
 /*
  * Parse all nodes and store the cvt/pin nids in array
  * Add one time initialization for pin and cvt widgets
  */
-static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
+static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev,
+		struct snd_soc_dai_driver **dais, int *num_dais)
 {
 	hda_nid_t nid;
 	int i, num_nodes;
@@ -695,6 +770,15 @@  static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev)
 	if (!hdmi->num_pin || !hdmi->num_cvt)
 		return -EIO;
 
+	ret = hdac_hdmi_create_dais(hdac, dais, hdmi, hdmi->num_cvt);
+	if (ret) {
+		dev_err(&hdac->dev, "Failed to create dais with err: %d\n",
+							ret);
+		return ret;
+	}
+
+	*num_dais = hdmi->num_cvt;
+
 	return hdac_hdmi_init_dai_map(edev);
 }
 
@@ -784,38 +868,12 @@  static struct snd_soc_codec_driver hdmi_hda_codec = {
 	.idle_bias_off	= true,
 };
 
-static struct snd_soc_dai_ops hdmi_dai_ops = {
-	.startup = hdac_hdmi_pcm_open,
-	.shutdown = hdac_hdmi_pcm_close,
-	.hw_params = hdac_hdmi_set_hw_params,
-	.prepare = hdac_hdmi_playback_prepare,
-	.hw_free = hdac_hdmi_playback_cleanup,
-};
-
-static struct snd_soc_dai_driver hdmi_dais[] = {
-	{	.name = "intel-hdmi-hif1",
-		.playback = {
-			.stream_name = "hif1",
-			.channels_min = 2,
-			.channels_max = 2,
-			.rates = SNDRV_PCM_RATE_32000 |
-				SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-				SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-				SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE |
-				SNDRV_PCM_FMTBIT_S20_3LE |
-				SNDRV_PCM_FMTBIT_S24_LE |
-				SNDRV_PCM_FMTBIT_S32_LE,
-
-		},
-		.ops = &hdmi_dai_ops,
-	},
-};
-
 static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
 {
 	struct hdac_device *codec = &edev->hdac;
 	struct hdac_hdmi_priv *hdmi_priv;
+	struct snd_soc_dai_driver *hdmi_dais = NULL;
+	int num_dais = 0;
 	int ret = 0;
 
 	hdmi_priv = devm_kzalloc(&codec->dev, sizeof(*hdmi_priv), GFP_KERNEL);
@@ -829,13 +887,15 @@  static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev)
 	INIT_LIST_HEAD(&hdmi_priv->pin_list);
 	INIT_LIST_HEAD(&hdmi_priv->cvt_list);
 
-	ret = hdac_hdmi_parse_and_map_nid(edev);
-	if (ret < 0)
+	ret = hdac_hdmi_parse_and_map_nid(edev, &hdmi_dais, &num_dais);
+	if (ret < 0) {
+		dev_err(&codec->dev, "Failed in parse and map nid with err: %d\n", ret);
 		return ret;
+	}
 
 	/* ASoC specific initialization */
 	return snd_soc_register_codec(&codec->dev, &hdmi_hda_codec,
-			hdmi_dais, ARRAY_SIZE(hdmi_dais));
+			hdmi_dais, num_dais);
 }
 
 static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev)