diff options
author | Viorel Suman <viorel.suman@nxp.com> | 2018-09-04 13:25:12 +0300 |
---|---|---|
committer | Viorel Suman <viorel.suman@nxp.com> | 2018-09-05 10:46:00 +0300 |
commit | 3a8025b673788daf1a0ab75e6feae5761381ca1e (patch) | |
tree | 31dc39cda3d946bfa877f44bbbd0aedbac07cd18 | |
parent | 26be34a709a1fea299674d567c221e586bf58313 (diff) |
MLK-19432-1: ASoC: imx-ak5558: limit max rate as function of sample bits
According to AK5558 MCLK frequence must not exceed 36.864 MHz.
Limit maximum supported rate as function of max MCLK frequency,
sample bits and number of slots.
Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
Reviewed-by: Shengjiu Wang <shengjiu.wang@nxp.com>
(cherry picked from commit 236796cad225daa39d5b77d763a1d964dd4de4c9)
-rw-r--r-- | Documentation/devicetree/bindings/sound/imx-audio-ak5558.txt | 2 | ||||
-rw-r--r-- | sound/soc/fsl/imx-ak5558.c | 43 |
2 files changed, 40 insertions, 5 deletions
diff --git a/Documentation/devicetree/bindings/sound/imx-audio-ak5558.txt b/Documentation/devicetree/bindings/sound/imx-audio-ak5558.txt index 3da95878a34a..7b62fbb14f8d 100644 --- a/Documentation/devicetree/bindings/sound/imx-audio-ak5558.txt +++ b/Documentation/devicetree/bindings/sound/imx-audio-ak5558.txt @@ -2,7 +2,7 @@ Freescale i.MX audio complex with AK5558 ADC Required properties: -- compatible : "fsl,imx-audio-ak5558" +- compatible : "fsl,imx-audio-ak5558", "fsl,imx-audio-ak5558-mq" - model : The user-visible name of this sound complex - audio-cpu : The phandle of CPU DAI - audio-codec : The phandle of the AK5558 audio ADC diff --git a/sound/soc/fsl/imx-ak5558.c b/sound/soc/fsl/imx-ak5558.c index 2c4e974a1b4c..c500b75786ff 100644 --- a/sound/soc/fsl/imx-ak5558.c +++ b/sound/soc/fsl/imx-ak5558.c @@ -30,6 +30,7 @@ struct imx_ak5558_data { bool tdm_mode; unsigned long slots; unsigned long slot_width; + bool one2one_ratio; }; /* @@ -52,8 +53,8 @@ static const struct imx_ak5558_fs_mul fs_mul[] = { { .min = 44100, .max = 48000, .mul = 512 }, { .min = 88200, .max = 96000, .mul = 256 }, { .min = 176400, .max = 192000, .mul = 128 }, - { .min = 352800, .max = 384000, .mul = 2*64 }, - { .min = 705600, .max = 768000, .mul = 2*32 }, + { .min = 352800, .max = 384000, .mul = 64 }, + { .min = 705600, .max = 768000, .mul = 32 }, }; /* @@ -196,6 +197,35 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, return ret; } +static int imx_ak5558_hw_rule_rate(struct snd_pcm_hw_params *p, + struct snd_pcm_hw_rule *r) +{ + struct imx_ak5558_data *data = r->private; + struct snd_interval t = { .min = 8000, .max = 8000, }; + unsigned int fs; + unsigned long mclk_freq; + int i; + + fs = hw_param_interval(p, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min; + fs *= data->tdm_mode ? 8 : 2; + + /* Identify maximum supported rate */ + for (i = 0; i < ARRAY_SIZE(ak5558_rates); i++) { + mclk_freq = fs * ak5558_rates[i]; + /* Adjust SAI bclk:mclk ratio */ + mclk_freq *= data->one2one_ratio ? 1 : 2; + + /* Skip rates for which MCLK is beyond supported value */ + if (mclk_freq > 36864000) + continue; + + if (t.max < ak5558_rates[i]) + t.max = ak5558_rates[i]; + } + + return snd_interval_refine(hw_param_interval(p, r->var), &t); +} + static int imx_aif_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -224,10 +254,12 @@ static int imx_aif_startup(struct snd_pcm_substream *substream) constraint_channels.count = ARRAY_SIZE(ak5558_channels); ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &constraint_channels); - if (ret) + if (ret < 0) return ret; - return 0; + return snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, imx_ak5558_hw_rule_rate, data, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); } static struct snd_soc_ops imx_aif_ops = { @@ -289,6 +321,8 @@ static int imx_ak5558_probe(struct platform_device *pdev) priv->card.owner = THIS_MODULE; priv->card.dapm_widgets = imx_ak5558_dapm_widgets; priv->card.num_dapm_widgets = ARRAY_SIZE(imx_ak5558_dapm_widgets); + priv->one2one_ratio = !of_device_is_compatible(pdev->dev.of_node, + "fsl,imx-audio-ak5558-mq"); ret = snd_soc_of_parse_card_name(&priv->card, "model"); if (ret) @@ -314,6 +348,7 @@ fail: static const struct of_device_id imx_ak5558_dt_ids[] = { { .compatible = "fsl,imx-audio-ak5558", }, + { .compatible = "fsl,imx-audio-ak5558-mq", }, { }, }; MODULE_DEVICE_TABLE(of, imx_ak5558_dt_ids); |