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

2015-12-04 Thread Subhransu S. Prusty
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 
Signed-off-by: Vinod Koul 
---
 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 
 #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(>dev, (sizeof(*hdmi_dais) * num_dais),
+   GFP_KERNEL);
+   if (!hdmi_dais)
+   return -ENOMEM;
+
+   list_for_each_entry(cvt, >cvt_list, head) {
+   ret = snd_hdac_query_supported_pcm(hdac, cvt->nid, ,
+   , );
+   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(>dev, dai_name,
+   GFP_KERNEL);
+
+   snprintf(name, sizeof(name), "hifi%d", i+1);
+   hdmi_dais[i].playback.stream_name =
+   devm_kstrdup(>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 = _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(>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 = {
-   

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

2015-12-03 Thread Takashi Iwai
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 
> Signed-off-by: Vinod Koul 
> ---
>  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 
>  #include "../../hda/local.h"
>  
> +#define NAME_SIZE32
> +
>  #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(>dev, (sizeof(*hdmi_dais) * num_dais),
> + GFP_KERNEL);
> + if (!hdmi_dais)
> + return -ENOMEM;
> +
> + list_for_each_entry(cvt, >cvt_list, head) {
> + ret = snd_hdac_query_supported_pcm(hdac, cvt->nid, ,
> + , );
> + 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