]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
ASoC: mediatek: simplify the control logic of MT2701 I2S
authorRyder Lee <ryder.lee@mediatek.com>
Wed, 25 Apr 2018 04:19:55 +0000 (12:19 +0800)
committerMark Brown <broonie@kernel.org>
Thu, 26 Apr 2018 14:08:43 +0000 (15:08 +0100)
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>
sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h
sound/soc/mediatek/mt2701/mt2701-afe-pcm.c

index 949fc3a1d02578d4e718cb80c87af4263de72d9f..565005f821d03c6559aaf99f0accd9bde4518b6e 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2016 MediaTek Inc.
  * Author: Garlic Tseng <garlic.tseng@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
@@ -102,10 +103,10 @@ int mt2701_init_clock(struct mtk_base_afe *afe)
        return 0;
 }
 
-int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, int id, int dir)
+int mt2701_afe_enable_i2s(struct mtk_base_afe *afe,
+                         struct mt2701_i2s_path *i2s_path,
+                         int dir)
 {
-       struct mt2701_afe_private *afe_priv = afe->platform_priv;
-       struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
        int ret;
 
        ret = clk_prepare_enable(i2s_path->asrco_ck);
@@ -128,11 +129,10 @@ err_hop_ck:
        return ret;
 }
 
-void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, int id, int dir)
+void mt2701_afe_disable_i2s(struct mtk_base_afe *afe,
+                           struct mt2701_i2s_path *i2s_path,
+                           int dir)
 {
-       struct mt2701_afe_private *afe_priv = afe->platform_priv;
-       struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
-
        clk_disable_unprepare(i2s_path->hop_ck[dir]);
        clk_disable_unprepare(i2s_path->asrco_ck);
 }
@@ -272,27 +272,32 @@ int mt2701_afe_disable_clock(struct mtk_base_afe *afe)
        return 0;
 }
 
-void mt2701_mclk_configuration(struct mtk_base_afe *afe, int id, int domain,
-                              int mclk)
+int mt2701_mclk_configuration(struct mtk_base_afe *afe, int id)
+
 {
        struct mt2701_afe_private *priv = afe->platform_priv;
        struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id];
-       int ret;
+       int ret = -EINVAL;
 
        /* Set mclk source */
-       if (domain == 0)
+       if (!(MT2701_PLL_DOMAIN_0_RATE % i2s_path->mclk_rate))
                ret = clk_set_parent(i2s_path->sel_ck,
                                     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]);
-       else
+       else if (!(MT2701_PLL_DOMAIN_1_RATE % i2s_path->mclk_rate))
                ret = clk_set_parent(i2s_path->sel_ck,
                                     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]);
 
-       if (ret)
-               dev_err(afe->dev, "failed to set domain%d mclk source %d\n",
-                       domain, ret);
+       if (ret) {
+               dev_err(afe->dev, "failed to set mclk source\n");
+               return ret;
+       }
 
        /* Set mclk divider */
-       ret = clk_set_rate(i2s_path->div_ck, mclk);
-       if (ret)
+       ret = clk_set_rate(i2s_path->div_ck, i2s_path->mclk_rate);
+       if (ret) {
                dev_err(afe->dev, "failed to set mclk divider %d\n", ret);
+               return ret;
+       }
+
+       return 0;
 }
index 15417d9d6597879d9b567f11c3fa0179267747f1..1957219cc3fe3c6f7cfd02b25f4a6246abc8f719 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2016 MediaTek Inc.
  * Author: Garlic Tseng <garlic.tseng@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
 #define _MT2701_AFE_CLOCK_CTRL_H_
 
 struct mtk_base_afe;
+struct mt2701_i2s_path;
 
 int mt2701_init_clock(struct mtk_base_afe *afe);
 int mt2701_afe_enable_clock(struct mtk_base_afe *afe);
 int mt2701_afe_disable_clock(struct mtk_base_afe *afe);
 
-int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, int id, int dir);
-void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, int id, int dir);
+int mt2701_afe_enable_i2s(struct mtk_base_afe *afe,
+                         struct mt2701_i2s_path *path,
+                         int dir);
+void mt2701_afe_disable_i2s(struct mtk_base_afe *afe,
+                           struct mt2701_i2s_path *path,
+                           int dir);
 int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id);
 void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id);
 
 int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe);
 void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe);
 
-void mt2701_mclk_configuration(struct mtk_base_afe *afe, int id, int domain,
-                              int mclk);
+int mt2701_mclk_configuration(struct mtk_base_afe *afe, int id);
 
 #endif
index 8219f553415038f5e20162643b2db393de491be6..2a161f4d01f6f33b16b05ff11dca642361060079 100644 (file)
@@ -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;
 }