]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - sound/soc/sh/rcar/rsrc-card.c
Merge remote-tracking branches 'asoc/topic/pxa', 'asoc/topic/qcom', 'asoc/topic/rcar...
[mirror_ubuntu-bionic-kernel.git] / sound / soc / sh / rcar / rsrc-card.c
index d61db9c385eafd3bc6fca47edad10bff696b3ba2..8a357fdf1077c91822d6699dcf79e7aa96574809 100644 (file)
@@ -48,8 +48,11 @@ MODULE_DEVICE_TABLE(of, rsrc_card_of_match);
 
 #define DAI_NAME_NUM   32
 struct rsrc_card_dai {
-       unsigned int fmt;
        unsigned int sysclk;
+       unsigned int tx_slot_mask;
+       unsigned int rx_slot_mask;
+       int slots;
+       int slot_width;
        struct clk *clk;
        char dai_name[DAI_NAME_NUM];
 };
@@ -75,7 +78,7 @@ static int rsrc_card_startup(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct rsrc_card_priv *priv =   snd_soc_card_get_drvdata(rtd->card);
        struct rsrc_card_dai *dai_props =
-               rsrc_priv_to_props(priv, rtd - rtd->card->rtd);
+               rsrc_priv_to_props(priv, rtd->num);
 
        return clk_prepare_enable(dai_props->clk);
 }
@@ -85,7 +88,7 @@ static void rsrc_card_shutdown(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct rsrc_card_priv *priv =   snd_soc_card_get_drvdata(rtd->card);
        struct rsrc_card_dai *dai_props =
-               rsrc_priv_to_props(priv, rtd - rtd->card->rtd);
+               rsrc_priv_to_props(priv, rtd->num);
 
        clk_disable_unprepare(dai_props->clk);
 }
@@ -101,7 +104,7 @@ static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_dai *dai;
        struct snd_soc_dai_link *dai_link;
        struct rsrc_card_dai *dai_props;
-       int num = rtd - rtd->card->rtd;
+       int num = rtd->num;
        int ret;
 
        dai_link        = rsrc_priv_to_link(priv, num);
@@ -110,18 +113,22 @@ static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd)
                                rtd->cpu_dai :
                                rtd->codec_dai;
 
-       if (dai_props->fmt) {
-               ret = snd_soc_dai_set_fmt(dai, dai_props->fmt);
+       if (dai_props->sysclk) {
+               ret = snd_soc_dai_set_sysclk(dai, 0, dai_props->sysclk, 0);
                if (ret && ret != -ENOTSUPP) {
-                       dev_err(dai->dev, "set_fmt error\n");
+                       dev_err(dai->dev, "set_sysclk error\n");
                        goto err;
                }
        }
 
-       if (dai_props->sysclk) {
-               ret = snd_soc_dai_set_sysclk(dai, 0, dai_props->sysclk, 0);
+       if (dai_props->slots) {
+               ret = snd_soc_dai_set_tdm_slot(dai,
+                                              dai_props->tx_slot_mask,
+                                              dai_props->rx_slot_mask,
+                                              dai_props->slots,
+                                              dai_props->slot_width);
                if (ret && ret != -ENOTSUPP) {
-                       dev_err(dai->dev, "set_sysclk error\n");
+                       dev_err(dai->dev, "set_tdm_slot error\n");
                        goto err;
                }
        }
@@ -148,14 +155,13 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 }
 
 static int rsrc_card_parse_daifmt(struct device_node *node,
-                                 struct device_node *np,
+                                 struct device_node *codec,
                                  struct rsrc_card_priv *priv,
-                                 int idx, bool is_fe)
+                                 struct snd_soc_dai_link *dai_link,
+                                 unsigned int *retfmt)
 {
-       struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx);
        struct device_node *bitclkmaster = NULL;
        struct device_node *framemaster = NULL;
-       struct device_node *codec = is_fe ? NULL : np;
        unsigned int daifmt;
 
        daifmt = snd_soc_of_parse_daifmt(node, NULL,
@@ -172,11 +178,11 @@ static int rsrc_card_parse_daifmt(struct device_node *node,
                daifmt |= (codec == framemaster) ?
                        SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
 
-       dai_props->fmt  = daifmt;
-
        of_node_put(bitclkmaster);
        of_node_put(framemaster);
 
+       *retfmt = daifmt;
+
        return 0;
 }
 
@@ -198,6 +204,15 @@ static int rsrc_card_parse_links(struct device_node *np,
        if (ret)
                return ret;
 
+       /* Parse TDM slot */
+       ret = snd_soc_of_parse_tdm_slot(np,
+                                       &dai_props->tx_slot_mask,
+                                       &dai_props->rx_slot_mask,
+                                       &dai_props->slots,
+                                       &dai_props->slot_width);
+       if (ret)
+               return ret;
+
        if (is_fe) {
                /* BE is dummy */
                dai_link->codec_of_node         = NULL;
@@ -208,7 +223,9 @@ static int rsrc_card_parse_links(struct device_node *np,
                dai_link->dynamic               = 1;
                dai_link->dpcm_merged_format    = 1;
                dai_link->cpu_of_node           = args.np;
-               snd_soc_of_get_dai_name(np, &dai_link->cpu_dai_name);
+               ret = snd_soc_of_get_dai_name(np, &dai_link->cpu_dai_name);
+               if (ret < 0)
+                       return ret;
 
                /* set dai_name */
                snprintf(dai_props->dai_name, DAI_NAME_NUM, "fe.%s",
@@ -240,7 +257,9 @@ static int rsrc_card_parse_links(struct device_node *np,
                dai_link->no_pcm                = 1;
                dai_link->be_hw_params_fixup    = rsrc_card_be_hw_params_fixup;
                dai_link->codec_of_node         = args.np;
-               snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name);
+               ret = snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name);
+               if (ret < 0)
+                       return ret;
 
                /* additional name prefix */
                if (of_data) {
@@ -305,23 +324,16 @@ static int rsrc_card_parse_clk(struct device_node *np,
        return 0;
 }
 
-static int rsrc_card_dai_link_of(struct device_node *node,
-                                struct device_node *np,
-                                struct rsrc_card_priv *priv,
-                                int idx)
+static int rsrc_card_dai_sub_link_of(struct device_node *node,
+                                    struct device_node *np,
+                                    struct rsrc_card_priv *priv,
+                                    int idx, bool is_fe)
 {
        struct device *dev = rsrc_priv_to_dev(priv);
+       struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx);
        struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx);
-       bool is_fe = false;
        int ret;
 
-       if (0 == strcmp(np->name, "cpu"))
-               is_fe = true;
-
-       ret = rsrc_card_parse_daifmt(node, np, priv, idx, is_fe);
-       if (ret < 0)
-               return ret;
-
        ret = rsrc_card_parse_links(np, priv, idx, is_fe);
        if (ret < 0)
                return ret;
@@ -332,12 +344,54 @@ static int rsrc_card_dai_link_of(struct device_node *node,
 
        dev_dbg(dev, "\t%s / %04x / %d\n",
                dai_props->dai_name,
-               dai_props->fmt,
+               dai_link->dai_fmt,
                dai_props->sysclk);
 
        return ret;
 }
 
+static int rsrc_card_dai_link_of(struct device_node *node,
+                                struct rsrc_card_priv *priv)
+{
+       struct snd_soc_dai_link *dai_link;
+       struct device_node *np;
+       unsigned int daifmt = 0;
+       int ret, i;
+       bool is_fe;
+
+       /* find 1st codec */
+       i = 0;
+       for_each_child_of_node(node, np) {
+               dai_link = rsrc_priv_to_link(priv, i);
+
+               if (strcmp(np->name, "codec") == 0) {
+                       ret = rsrc_card_parse_daifmt(node, np, priv,
+                                                    dai_link, &daifmt);
+                       if (ret < 0)
+                               return ret;
+                       break;
+               }
+               i++;
+       }
+
+       i = 0;
+       for_each_child_of_node(node, np) {
+               dai_link = rsrc_priv_to_link(priv, i);
+               dai_link->dai_fmt = daifmt;
+
+               is_fe = false;
+               if (strcmp(np->name, "cpu") == 0)
+                       is_fe = true;
+
+               ret = rsrc_card_dai_sub_link_of(node, np, priv, i, is_fe);
+               if (ret < 0)
+                       return ret;
+               i++;
+       }
+
+       return 0;
+}
+
 static int rsrc_card_parse_of(struct device_node *node,
                              struct rsrc_card_priv *priv,
                              struct device *dev)
@@ -345,9 +399,8 @@ static int rsrc_card_parse_of(struct device_node *node,
        const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev);
        struct rsrc_card_dai *props;
        struct snd_soc_dai_link *links;
-       struct device_node *np;
        int ret;
-       int i, num;
+       int num;
 
        if (!node)
                return -EINVAL;
@@ -388,13 +441,9 @@ static int rsrc_card_parse_of(struct device_node *node,
                priv->snd_card.name ? priv->snd_card.name : "",
                priv->convert_rate);
 
-       i = 0;
-       for_each_child_of_node(node, np) {
-               ret = rsrc_card_dai_link_of(node, np, priv, i);
-               if (ret < 0)
-                       return ret;
-               i++;
-       }
+       ret = rsrc_card_dai_link_of(node, priv);
+       if (ret < 0)
+               return ret;
 
        if (!priv->snd_card.name)
                priv->snd_card.name = priv->snd_card.dai_link->name;