diff options
Diffstat (limited to 'sound/soc/sh/rcar/rsrc-card.c')
-rw-r--r-- | sound/soc/sh/rcar/rsrc-card.c | 129 |
1 files changed, 89 insertions, 40 deletions
diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index d61db9c38..8a357fdf1 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -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; |