~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php