diff options
author | Shengjiu Wang <shengjiu.wang@freescale.com> | 2015-04-29 13:21:37 +0800 |
---|---|---|
committer | Jason Liu <r64343@freescale.com> | 2015-05-08 16:35:22 +0800 |
commit | 0d79b3290ad357ad9e3b8e0c3b06812c6f523956 (patch) | |
tree | ea0bd342138578b7efb470f11da2d72446ac81a2 /sound | |
parent | ffe449c84bb152ac6610c588a3e26a0eaa3f7de8 (diff) |
MLK-10775-2: ASoC: imx-mqs: add asrc p2p support in sai->mqs
add asrc p2p support in sai->mqs
Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/fsl/imx-mqs.c | 135 |
1 files changed, 122 insertions, 13 deletions
diff --git a/sound/soc/fsl/imx-mqs.c b/sound/soc/fsl/imx-mqs.c index 7ef07f7ad22e..85ad2520e573 100644 --- a/sound/soc/fsl/imx-mqs.c +++ b/sound/soc/fsl/imx-mqs.c @@ -1,5 +1,5 @@ /* - * Copyright 2012, 2014 Freescale Semiconductor, Inc. + * Copyright 2012, 2014-2015 Freescale Semiconductor, Inc. * Copyright 2012 Linaro Ltd. * * The code contained herein is licensed under the GNU General Public @@ -22,6 +22,9 @@ struct imx_priv { unsigned int mclk_freq; struct platform_device *pdev; + struct platform_device *asrc_pdev; + u32 asrc_rate; + u32 asrc_format; }; static struct imx_priv card_priv; @@ -73,19 +76,75 @@ static struct snd_soc_ops imx_mqs_ops = { .hw_params = imx_mqs_hw_params, }; -static struct snd_soc_dai_link imx_mqs_dai = { - .name = "HiFi", - .stream_name = "HiFi", - .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS, - .ops = &imx_mqs_ops, +static struct snd_soc_ops imx_mqs_ops_be = { + .hw_params = imx_mqs_hw_params, +}; + +static const struct snd_soc_dapm_route audio_map[] = { + {"CPU-Playback", NULL, "ASRC-Playback"}, + {"Playback", NULL, "CPU-Playback"},/* dai route for be and fe */ +}; + +static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) { + + struct imx_priv *priv = &card_priv; + struct snd_interval *rate; + struct snd_mask *mask; + + if (!priv->asrc_pdev) + return -EINVAL; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + rate->max = rate->min = priv->asrc_rate; + + mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + snd_mask_none(mask); + snd_mask_set(mask, priv->asrc_format); + + return 0; +} + +static struct snd_soc_dai_link imx_mqs_dai[] = { + { + .name = "HiFi", + .stream_name = "HiFi", + .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .ops = &imx_mqs_ops, + }, + { + .name = "HiFi-ASRC-FE", + .stream_name = "HiFi-ASRC-FE", + .codec_name = "snd-soc-dummy", + .codec_dai_name = "snd-soc-dummy-dai", + .dynamic = 1, + .ignore_pmdown_time = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + }, + { + .name = "HiFi-ASRC-BE", + .stream_name = "HiFi-ASRC-BE", + .codec_dai_name = "fsl-mqs-dai", + .platform_name = "snd-soc-dummy", + .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .no_pcm = 1, + .ignore_pmdown_time = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ops = &imx_mqs_ops_be, + .be_hw_params_fixup = be_hw_params_fixup, + }, }; static struct snd_soc_card snd_soc_card_imx_mqs = { .name = "mqs-audio", - .dai_link = &imx_mqs_dai, + .dai_link = imx_mqs_dai, .owner = THIS_MODULE, - .num_links = 1, + .dapm_routes = audio_map, + .num_dapm_routes = ARRAY_SIZE(audio_map), }; static int imx_mqs_probe(struct platform_device *pdev) @@ -94,7 +153,11 @@ static int imx_mqs_probe(struct platform_device *pdev) struct imx_priv *priv = &card_priv; struct clk *codec_clk = NULL; struct platform_device *codec_dev; + struct platform_device *asrc_pdev = NULL; + struct platform_device *cpu_pdev; + struct device_node *asrc_np; int ret; + u32 width; priv->pdev = pdev; @@ -104,6 +167,19 @@ static int imx_mqs_probe(struct platform_device *pdev) goto fail; } + cpu_pdev = of_find_device_by_node(cpu_np); + if (!cpu_pdev) { + dev_err(&pdev->dev, "failed to find cpu dai device\n"); + ret = -EINVAL; + goto fail; + } + + asrc_np = of_parse_phandle(pdev->dev.of_node, "asrc-controller", 0); + if (asrc_np) { + asrc_pdev = of_find_device_by_node(asrc_np); + priv->asrc_pdev = asrc_pdev; + } + codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0); if (!codec_np) { dev_err(&pdev->dev, "phandle missing or invalid\n"); @@ -126,11 +202,44 @@ static int imx_mqs_probe(struct platform_device *pdev) } priv->mclk_freq = clk_get_rate(codec_clk); + imx_mqs_dai[0].codec_dai_name = "fsl-mqs-dai"; + + if (!asrc_pdev) { + imx_mqs_dai[0].codec_of_node = codec_np; + imx_mqs_dai[0].cpu_dai_name = dev_name(&cpu_pdev->dev); + imx_mqs_dai[0].platform_of_node = cpu_np; + snd_soc_card_imx_mqs.num_links = 1; + } else { + imx_mqs_dai[0].codec_of_node = codec_np; + imx_mqs_dai[0].cpu_dai_name = dev_name(&cpu_pdev->dev); + imx_mqs_dai[0].platform_of_node = cpu_np; + imx_mqs_dai[1].cpu_of_node = asrc_np; + imx_mqs_dai[1].platform_of_node = asrc_np; + imx_mqs_dai[2].codec_of_node = codec_np; + imx_mqs_dai[2].cpu_dai_name = dev_name(&cpu_pdev->dev); + snd_soc_card_imx_mqs.num_links = 3; + + ret = of_property_read_u32(asrc_np, "fsl,asrc-rate", + &priv->asrc_rate); + if (ret) { + dev_err(&pdev->dev, "failed to get output rate\n"); + ret = -EINVAL; + goto fail; + } + + ret = of_property_read_u32(asrc_np, "fsl,asrc-width", &width); + if (ret) { + dev_err(&pdev->dev, "failed to get output rate\n"); + ret = -EINVAL; + goto fail; + } + + if (width == 24) + priv->asrc_format = SNDRV_PCM_FORMAT_S24_LE; + else + priv->asrc_format = SNDRV_PCM_FORMAT_S16_LE; + } - imx_mqs_dai.cpu_of_node = cpu_np; - imx_mqs_dai.platform_of_node = cpu_np; - imx_mqs_dai.codec_dai_name = "fsl-mqs-dai"; - imx_mqs_dai.codec_of_node = codec_np; snd_soc_card_imx_mqs.dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_imx_mqs); |