File Index
Files and directories
Sign in
FILE

mt2701-afe-clock-ctrl.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c C
  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
 13static 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
 25int 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
101int 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
121err_hop_ck:
122	clk_disable_unprepare(i2s_path->asrco_ck);
123
124	return ret;
125}
126
127void 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
135int 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
143void 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
151int 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
158void 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
165static 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
204err_afe_conn:
205	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
206err_audio_a2sys:
207	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
208err_audio_a1sys:
209	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
210err_afe:
211	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);
212err_a2sys:
213	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);
214err_a1sys:
215	clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);
216
217	return ret;
218}
219
220static 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
233int 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
258int 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
270int 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}
~/ Read-only file preview.