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 } 299
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.