diff options
author | Ryder Lee <ryder.lee@mediatek.com> | 2018-04-25 06:19:55 +0200 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-04-26 16:08:43 +0200 |
commit | cf8702736032cd593f481e4c2ac38cfe6fa67799 (patch) | |
tree | 645ad19dd7bf4a73215f81002fba98edc5d8390f /sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | |
parent | ASoC: add mt6351 codec driver (diff) | |
download | linux-cf8702736032cd593f481e4c2ac38cfe6fa67799.tar.xz linux-cf8702736032cd593f481e4c2ac38cfe6fa67799.zip |
ASoC: mediatek: simplify the control logic of MT2701 I2S
This patch adjusts the mt2701_afe_i2s_ops to simplify the control
logic of the I2S path.
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Reviewed-by: Garlic Tseng <garlic.tseng@mediatek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/mediatek/mt2701/mt2701-afe-pcm.c')
-rw-r--r-- | sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 114 |
1 files changed, 35 insertions, 79 deletions
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index 8219f5534150..2a161f4d01f6 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c @@ -3,7 +3,8 @@ * * Copyright (c) 2016 MediaTek Inc. * Author: Garlic Tseng <garlic.tseng@mediatek.com> - * Ir Lian <ir.lian@mediatek.com> + * Ir Lian <ir.lian@mediatek.com> + * Ryder Lee <ryder.lee@mediatek.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -101,31 +102,15 @@ static int mt2701_afe_i2s_startup(struct snd_pcm_substream *substream, return mt2701_afe_enable_mclk(afe, i2s_num); } -static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai, - int i2s_num, - int dir_invert) +static int mt2701_afe_i2s_path_disable(struct mtk_base_afe *afe, + struct mt2701_i2s_path *i2s_path, + int stream_dir) { - struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); - struct mt2701_afe_private *afe_priv = afe->platform_priv; - struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i2s_num]; - const struct mt2701_i2s_data *i2s_data; - int stream_dir = substream->stream; - - if (dir_invert) { - if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) - stream_dir = SNDRV_PCM_STREAM_CAPTURE; - else - stream_dir = SNDRV_PCM_STREAM_PLAYBACK; - } - i2s_data = i2s_path->i2s_data[stream_dir]; + const struct mt2701_i2s_data *i2s_data = i2s_path->i2s_data[stream_dir]; - i2s_path->on[stream_dir]--; - if (i2s_path->on[stream_dir] < 0) { - dev_warn(afe->dev, "i2s_path->on: %d, dir: %d\n", - i2s_path->on[stream_dir], stream_dir); + if (--i2s_path->on[stream_dir] < 0) i2s_path->on[stream_dir] = 0; - } + if (i2s_path->on[stream_dir]) return 0; @@ -133,7 +118,7 @@ static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream, regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, ASYS_I2S_CON_I2S_EN, 0); - mt2701_afe_disable_i2s(afe, i2s_num, stream_dir); + mt2701_afe_disable_i2s(afe, i2s_path, stream_dir); return 0; } @@ -154,48 +139,32 @@ static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream, if (i2s_path->occupied[substream->stream]) i2s_path->occupied[substream->stream] = 0; else - goto I2S_UNSTART; + goto exit; - mt2701_afe_i2s_path_shutdown(substream, dai, i2s_num, 0); + mt2701_afe_i2s_path_disable(afe, i2s_path, substream->stream); /* need to disable i2s-out path when disable i2s-in */ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - mt2701_afe_i2s_path_shutdown(substream, dai, i2s_num, 1); + mt2701_afe_i2s_path_disable(afe, i2s_path, !substream->stream); -I2S_UNSTART: +exit: /* disable mclk */ mt2701_afe_disable_mclk(afe, i2s_num); } -static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai, - int i2s_num, - int dir_invert) +static int mt2701_i2s_path_enable(struct mtk_base_afe *afe, + struct mt2701_i2s_path *i2s_path, + int stream_dir, int rate) { - struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); - struct mt2701_afe_private *afe_priv = afe->platform_priv; - struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i2s_num]; - const struct mt2701_i2s_data *i2s_data; - struct snd_pcm_runtime * const runtime = substream->runtime; + const struct mt2701_i2s_data *i2s_data = i2s_path->i2s_data[stream_dir]; int reg, fs, w_len = 1; /* now we support bck 64bits only */ - int stream_dir = substream->stream; unsigned int mask, val; - if (dir_invert) { - if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) - stream_dir = SNDRV_PCM_STREAM_CAPTURE; - else - stream_dir = SNDRV_PCM_STREAM_PLAYBACK; - } - i2s_data = i2s_path->i2s_data[stream_dir]; - /* no need to enable if already done */ - i2s_path->on[stream_dir]++; - - if (i2s_path->on[stream_dir] != 1) + if (++i2s_path->on[stream_dir] != 1) return 0; - fs = mt2701_afe_i2s_fs(runtime->rate); + fs = mt2701_afe_i2s_fs(rate); mask = ASYS_I2S_CON_FS | ASYS_I2S_CON_I2S_COUPLE_MODE | /* 0 */ @@ -209,22 +178,20 @@ static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream, if (stream_dir == SNDRV_PCM_STREAM_CAPTURE) { mask |= ASYS_I2S_IN_PHASE_FIX; val |= ASYS_I2S_IN_PHASE_FIX; + reg = ASMI_TIMING_CON1; + } else { + reg = ASMO_TIMING_CON1; } regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, mask, val); - if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) - reg = ASMO_TIMING_CON1; - else - reg = ASMI_TIMING_CON1; - regmap_update_bits(afe->regmap, reg, i2s_data->i2s_asrc_fs_mask << i2s_data->i2s_asrc_fs_shift, fs << i2s_data->i2s_asrc_fs_shift); /* enable i2s */ - mt2701_afe_enable_i2s(afe, i2s_num, stream_dir); + mt2701_afe_enable_i2s(afe, i2s_path, stream_dir); /* reset i2s hw status before enable */ regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, @@ -241,43 +208,32 @@ static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream, static int mt2701_afe_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - int clk_domain; struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt2701_afe_private *afe_priv = afe->platform_priv; - int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); + int ret, i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); struct mt2701_i2s_path *i2s_path; - int mclk_rate; if (i2s_num < 0) return i2s_num; i2s_path = &afe_priv->i2s_path[i2s_num]; - mclk_rate = i2s_path->mclk_rate; if (i2s_path->occupied[substream->stream]) return -EBUSY; + + ret = mt2701_mclk_configuration(afe, i2s_num); + if (ret) + return ret; + i2s_path->occupied[substream->stream] = 1; - if (MT2701_PLL_DOMAIN_0_RATE % mclk_rate == 0) { - clk_domain = 0; - } else if (MT2701_PLL_DOMAIN_1_RATE % mclk_rate == 0) { - clk_domain = 1; - } else { - dev_err(dai->dev, "%s() bad mclk rate %d\n", - __func__, mclk_rate); - return -EINVAL; - } - mt2701_mclk_configuration(afe, i2s_num, clk_domain, mclk_rate); + /* need to enable i2s-out path when enable i2s-in */ + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + mt2701_i2s_path_enable(afe, i2s_path, !substream->stream, + substream->runtime->rate); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 0); - } else { - /* need to enable i2s-out path when enable i2s-in */ - /* prepare for another direction "out" */ - mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 1); - /* prepare for "in" */ - mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 0); - } + mt2701_i2s_path_enable(afe, i2s_path, substream->stream, + substream->runtime->rate); return 0; } |