root/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mt2701_init_clock
  2. mt2701_afe_enable_i2s
  3. mt2701_afe_disable_i2s
  4. mt2701_afe_enable_mclk
  5. mt2701_afe_disable_mclk
  6. mt2701_enable_btmrg_clk
  7. mt2701_disable_btmrg_clk
  8. mt2701_afe_enable_audsys
  9. mt2701_afe_disable_audsys
  10. mt2701_afe_enable_clock
  11. mt2701_afe_disable_clock
  12. mt2701_mclk_configuration

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * mt2701-afe-clock-ctrl.c  --  Mediatek 2701 afe clock ctrl
   4  *
   5  * Copyright (c) 2016 MediaTek Inc.
   6  * Author: Garlic Tseng <garlic.tseng@mediatek.com>
   7  *         Ryder Lee <ryder.lee@mediatek.com>
   8  */
   9 
  10 #include "mt2701-afe-common.h"
  11 #include "mt2701-afe-clock-ctrl.h"
  12 
  13 static const char *const base_clks[] = {
  14         [MT2701_INFRA_SYS_AUDIO] = "infra_sys_audio_clk",
  15         [MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel",
  16         [MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel",
  17         [MT2701_TOP_AUD_A1SYS] = "top_audio_a1sys_hp",
  18         [MT2701_TOP_AUD_A2SYS] = "top_audio_a2sys_hp",
  19         [MT2701_AUDSYS_AFE] = "audio_afe_pd",
  20         [MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd",
  21         [MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd",
  22         [MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd",
  23 };
  24 
  25 int mt2701_init_clock(struct mtk_base_afe *afe)
  26 {
  27         struct mt2701_afe_private *afe_priv = afe->platform_priv;
  28         int i;
  29 
  30         for (i = 0; i < MT2701_BASE_CLK_NUM; i++) {
  31                 afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]);
  32                 if (IS_ERR(afe_priv->base_ck[i])) {
  33                         dev_err(afe->dev, "failed to get %s\n", base_clks[i]);
  34                         return PTR_ERR(afe_priv->base_ck[i]);
  35                 }
  36         }
  37 
  38         /* Get I2S related clocks */
  39         for (i = 0; i < afe_priv->soc->i2s_num; i++) {
  40                 struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i];
  41                 struct clk *i2s_ck;
  42                 char name[13];
  43 
  44                 snprintf(name, sizeof(name), "i2s%d_src_sel", i);
  45                 i2s_path->sel_ck = devm_clk_get(afe->dev, name);
  46                 if (IS_ERR(i2s_path->sel_ck)) {
  47                         dev_err(afe->dev, "failed to get %s\n", name);
  48                         return PTR_ERR(i2s_path->sel_ck);
  49                 }
  50 
  51                 snprintf(name, sizeof(name), "i2s%d_src_div", i);
  52                 i2s_path->div_ck = devm_clk_get(afe->dev, name);
  53                 if (IS_ERR(i2s_path->div_ck)) {
  54                         dev_err(afe->dev, "failed to get %s\n", name);
  55                         return PTR_ERR(i2s_path->div_ck);
  56                 }
  57 
  58                 snprintf(name, sizeof(name), "i2s%d_mclk_en", i);
  59                 i2s_path->mclk_ck = devm_clk_get(afe->dev, name);
  60                 if (IS_ERR(i2s_path->mclk_ck)) {
  61                         dev_err(afe->dev, "failed to get %s\n", name);
  62                         return PTR_ERR(i2s_path->mclk_ck);
  63                 }
  64 
  65                 snprintf(name, sizeof(name), "i2so%d_hop_ck", i);
  66                 i2s_ck = devm_clk_get(afe->dev, name);
  67                 if (IS_ERR(i2s_ck)) {
  68                         dev_err(afe->dev, "failed to get %s\n", name);
  69                         return PTR_ERR(i2s_ck);
  70                 }
  71                 i2s_path->hop_ck[SNDRV_PCM_STREAM_PLAYBACK] = i2s_ck;
  72 
  73                 snprintf(name, sizeof(name), "i2si%d_hop_ck", i);
  74                 i2s_ck = devm_clk_get(afe->dev, name);
  75                 if (IS_ERR(i2s_ck)) {
  76                         dev_err(afe->dev, "failed to get %s\n", name);
  77                         return PTR_ERR(i2s_ck);
  78                 }
  79                 i2s_path->hop_ck[SNDRV_PCM_STREAM_CAPTURE] = i2s_ck;
  80 
  81                 snprintf(name, sizeof(name), "asrc%d_out_ck", i);
  82                 i2s_path->asrco_ck = devm_clk_get(afe->dev, name);
  83                 if (IS_ERR(i2s_path->asrco_ck)) {
  84                         dev_err(afe->dev, "failed to get %s\n", name);
  85                         return PTR_ERR(i2s_path->asrco_ck);
  86                 }
  87         }
  88 
  89         /* Some platforms may support BT path */
  90         afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd");
  91         if (IS_ERR(afe_priv->mrgif_ck)) {
  92                 if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER)
  93                         return -EPROBE_DEFER;
  94 
  95                 afe_priv->mrgif_ck = NULL;
  96         }
  97 
  98         return 0;
  99 }
 100 
 101 int mt2701_afe_enable_i2s(struct mtk_base_afe *afe,
 102                           struct mt2701_i2s_path *i2s_path,
 103                           int dir)
 104 {
 105         int ret;
 106 
 107         ret = clk_prepare_enable(i2s_path->asrco_ck);
 108         if (ret) {
 109                 dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret);
 110                 return ret;
 111         }
 112 
 113         ret = clk_prepare_enable(i2s_path->hop_ck[dir]);
 114         if (ret) {
 115                 dev_err(afe->dev, "failed to enable I2S clock %d\n", ret);
 116                 goto err_hop_ck;
 117         }
 118 
 119         return 0;
 120 
 121 err_hop_ck:
 122         clk_disable_unprepare(i2s_path->asrco_ck);
 123 
 124         return ret;
 125 }
 126 
 127 void mt2701_afe_disable_i2s(struct mtk_base_afe *afe,
 128                             struct mt2701_i2s_path *i2s_path,
 129                             int dir)
 130 {
 131         clk_disable_unprepare(i2s_path->hop_ck[dir]);
 132         clk_disable_unprepare(i2s_path->asrco_ck);
 133 }
 134 
 135 int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id)
 136 {
 137         struct mt2701_afe_private *afe_priv = afe->platform_priv;
 138         struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
 139 
 140         return clk_prepare_enable(i2s_path->mclk_ck);
 141 }
 142 
 143 void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id)
 144 {
 145         struct mt2701_afe_private *afe_priv = afe->platform_priv;
 146         struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
 147 
 148         clk_disable_unprepare(i2s_path->mclk_ck);
 149 }
 150 
 151 int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe)
 152 {
 153         struct mt2701_afe_private *afe_priv = afe->platform_priv;
 154 
 155         return clk_prepare_enable(afe_priv->mrgif_ck);
 156 }
 157 
 158 void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe)
 159 {
 160         struct mt2701_afe_private *afe_priv = afe->platform_priv;
 161 
 162         clk_disable_unprepare(afe_priv->mrgif_ck);
 163 }
 164 
 165 static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe)
 166 {
 167         struct mt2701_afe_private *afe_priv = afe->platform_priv;
 168         int ret;
 169 
 170         /* Enable infra clock gate */
 171         ret = clk_prepare_enable(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);
 172         if (ret)
 173                 return ret;
 174 
 175         /* Enable top a1sys clock gate */
 176         ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);
 177         if (ret)
 178                 goto err_a1sys;
 179 
 180         /* Enable top a2sys clock gate */
 181         ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);
 182         if (ret)
 183                 goto err_a2sys;
 184 
 185         /* Internal clock gates */
 186         ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
 187         if (ret)
 188                 goto err_afe;
 189 
 190         ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
 191         if (ret)
 192                 goto err_audio_a1sys;
 193 
 194         ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
 195         if (ret)
 196                 goto err_audio_a2sys;
 197 
 198         ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);
 199         if (ret)
 200                 goto err_afe_conn;
 201 
 202         return 0;
 203 
 204 err_afe_conn:
 205         clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
 206 err_audio_a2sys:
 207         clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
 208 err_audio_a1sys:
 209         clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
 210 err_afe:
 211         clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);
 212 err_a2sys:
 213         clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);
 214 err_a1sys:
 215         clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);
 216 
 217         return ret;
 218 }
 219 
 220 static void mt2701_afe_disable_audsys(struct mtk_base_afe *afe)
 221 {
 222         struct mt2701_afe_private *afe_priv = afe->platform_priv;
 223 
 224         clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);
 225         clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
 226         clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
 227         clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
 228         clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);
 229         clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);
 230         clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);
 231 }
 232 
 233 int mt2701_afe_enable_clock(struct mtk_base_afe *afe)
 234 {
 235         int ret;
 236 
 237         /* Enable audio system */
 238         ret = mt2701_afe_enable_audsys(afe);
 239         if (ret) {
 240                 dev_err(afe->dev, "failed to enable audio system %d\n", ret);
 241                 return ret;
 242         }
 243 
 244         regmap_update_bits(afe->regmap, ASYS_TOP_CON,
 245                            ASYS_TOP_CON_ASYS_TIMING_ON,
 246                            ASYS_TOP_CON_ASYS_TIMING_ON);
 247         regmap_update_bits(afe->regmap, AFE_DAC_CON0,
 248                            AFE_DAC_CON0_AFE_ON,
 249                            AFE_DAC_CON0_AFE_ON);
 250 
 251         /* Configure ASRC */
 252         regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL);
 253         regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL);
 254 
 255         return 0;
 256 }
 257 
 258 int mt2701_afe_disable_clock(struct mtk_base_afe *afe)
 259 {
 260         regmap_update_bits(afe->regmap, ASYS_TOP_CON,
 261                            ASYS_TOP_CON_ASYS_TIMING_ON, 0);
 262         regmap_update_bits(afe->regmap, AFE_DAC_CON0,
 263                            AFE_DAC_CON0_AFE_ON, 0);
 264 
 265         mt2701_afe_disable_audsys(afe);
 266 
 267         return 0;
 268 }
 269 
 270 int mt2701_mclk_configuration(struct mtk_base_afe *afe, int id)
 271 
 272 {
 273         struct mt2701_afe_private *priv = afe->platform_priv;
 274         struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id];
 275         int ret = -EINVAL;
 276 
 277         /* Set mclk source */
 278         if (!(MT2701_PLL_DOMAIN_0_RATE % i2s_path->mclk_rate))
 279                 ret = clk_set_parent(i2s_path->sel_ck,
 280                                      priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]);
 281         else if (!(MT2701_PLL_DOMAIN_1_RATE % i2s_path->mclk_rate))
 282                 ret = clk_set_parent(i2s_path->sel_ck,
 283                                      priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]);
 284 
 285         if (ret) {
 286                 dev_err(afe->dev, "failed to set mclk source\n");
 287                 return ret;
 288         }
 289 
 290         /* Set mclk divider */
 291         ret = clk_set_rate(i2s_path->div_ck, i2s_path->mclk_rate);
 292         if (ret) {
 293                 dev_err(afe->dev, "failed to set mclk divider %d\n", ret);
 294                 return ret;
 295         }
 296 
 297         return 0;
 298 }

/* [<][>][^][v][top][bottom][index][help] */