xref: /linux/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c (revision 600b2fd4f0f7ae5ebcb604c39c9a97e573f9d23e)
1d6f3710aSGarlic Tseng /*
2d6f3710aSGarlic Tseng  * mt2701-afe-clock-ctrl.c  --  Mediatek 2701 afe clock ctrl
3d6f3710aSGarlic Tseng  *
4d6f3710aSGarlic Tseng  * Copyright (c) 2016 MediaTek Inc.
5d6f3710aSGarlic Tseng  * Author: Garlic Tseng <garlic.tseng@mediatek.com>
6d6f3710aSGarlic Tseng  *
7d6f3710aSGarlic Tseng  * This program is free software; you can redistribute it and/or modify
8d6f3710aSGarlic Tseng  * it under the terms of the GNU General Public License version 2 and
9d6f3710aSGarlic Tseng  * only version 2 as published by the Free Software Foundation.
10d6f3710aSGarlic Tseng  *
11d6f3710aSGarlic Tseng  * This program is distributed in the hope that it will be useful,
12d6f3710aSGarlic Tseng  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13d6f3710aSGarlic Tseng  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14d6f3710aSGarlic Tseng  * GNU General Public License for more details.
15d6f3710aSGarlic Tseng  */
16d6f3710aSGarlic Tseng 
17d6f3710aSGarlic Tseng #include "mt2701-afe-common.h"
18d6f3710aSGarlic Tseng #include "mt2701-afe-clock-ctrl.h"
19d6f3710aSGarlic Tseng 
20d8d99d8eSRyder Lee static const char *const base_clks[] = {
21d8d99d8eSRyder Lee 	[MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel",
22d8d99d8eSRyder Lee 	[MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel",
23d8d99d8eSRyder Lee 	[MT2701_AUDSYS_AFE] = "audio_afe_pd",
24d8d99d8eSRyder Lee 	[MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd",
25d8d99d8eSRyder Lee 	[MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd",
26d8d99d8eSRyder Lee 	[MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd",
27d6f3710aSGarlic Tseng };
28d6f3710aSGarlic Tseng 
29d6f3710aSGarlic Tseng int mt2701_init_clock(struct mtk_base_afe *afe)
30d6f3710aSGarlic Tseng {
31d6f3710aSGarlic Tseng 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
32d8d99d8eSRyder Lee 	int i;
33d6f3710aSGarlic Tseng 
34d8d99d8eSRyder Lee 	for (i = 0; i < MT2701_BASE_CLK_NUM; i++) {
35d8d99d8eSRyder Lee 		afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]);
36d8d99d8eSRyder Lee 		if (IS_ERR(afe_priv->base_ck[i])) {
37d8d99d8eSRyder Lee 			dev_err(afe->dev, "failed to get %s\n", base_clks[i]);
38d8d99d8eSRyder Lee 			return PTR_ERR(afe_priv->base_ck[i]);
39d6f3710aSGarlic Tseng 		}
40d6f3710aSGarlic Tseng 	}
41d6f3710aSGarlic Tseng 
42d8d99d8eSRyder Lee 	/* Get I2S related clocks */
43d8d99d8eSRyder Lee 	for (i = 0; i < MT2701_I2S_NUM; i++) {
44d8d99d8eSRyder Lee 		struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i];
45d8d99d8eSRyder Lee 		char name[13];
46d8d99d8eSRyder Lee 
47d8d99d8eSRyder Lee 		snprintf(name, sizeof(name), "i2s%d_src_sel", i);
48d8d99d8eSRyder Lee 		i2s_path->sel_ck = devm_clk_get(afe->dev, name);
49d8d99d8eSRyder Lee 		if (IS_ERR(i2s_path->sel_ck)) {
50d8d99d8eSRyder Lee 			dev_err(afe->dev, "failed to get %s\n", name);
51d8d99d8eSRyder Lee 			return PTR_ERR(i2s_path->sel_ck);
52d8d99d8eSRyder Lee 		}
53d8d99d8eSRyder Lee 
54d8d99d8eSRyder Lee 		snprintf(name, sizeof(name), "i2s%d_src_div", i);
55d8d99d8eSRyder Lee 		i2s_path->div_ck = devm_clk_get(afe->dev, name);
56d8d99d8eSRyder Lee 		if (IS_ERR(i2s_path->div_ck)) {
57d8d99d8eSRyder Lee 			dev_err(afe->dev, "failed to get %s\n", name);
58d8d99d8eSRyder Lee 			return PTR_ERR(i2s_path->div_ck);
59d8d99d8eSRyder Lee 		}
60d8d99d8eSRyder Lee 
61d8d99d8eSRyder Lee 		snprintf(name, sizeof(name), "i2s%d_mclk_en", i);
62d8d99d8eSRyder Lee 		i2s_path->mclk_ck = devm_clk_get(afe->dev, name);
63d8d99d8eSRyder Lee 		if (IS_ERR(i2s_path->mclk_ck)) {
64d8d99d8eSRyder Lee 			dev_err(afe->dev, "failed to get %s\n", name);
65d8d99d8eSRyder Lee 			return PTR_ERR(i2s_path->mclk_ck);
66d8d99d8eSRyder Lee 		}
67d8d99d8eSRyder Lee 
68d8d99d8eSRyder Lee 		snprintf(name, sizeof(name), "i2so%d_hop_ck", i);
69d8d99d8eSRyder Lee 		i2s_path->hop_ck[I2S_OUT] = devm_clk_get(afe->dev, name);
70d8d99d8eSRyder Lee 		if (IS_ERR(i2s_path->hop_ck[I2S_OUT])) {
71d8d99d8eSRyder Lee 			dev_err(afe->dev, "failed to get %s\n", name);
72d8d99d8eSRyder Lee 			return PTR_ERR(i2s_path->hop_ck[I2S_OUT]);
73d8d99d8eSRyder Lee 		}
74d8d99d8eSRyder Lee 
75d8d99d8eSRyder Lee 		snprintf(name, sizeof(name), "i2si%d_hop_ck", i);
76d8d99d8eSRyder Lee 		i2s_path->hop_ck[I2S_IN] = devm_clk_get(afe->dev, name);
77d8d99d8eSRyder Lee 		if (IS_ERR(i2s_path->hop_ck[I2S_IN])) {
78d8d99d8eSRyder Lee 			dev_err(afe->dev, "failed to get %s\n", name);
79d8d99d8eSRyder Lee 			return PTR_ERR(i2s_path->hop_ck[I2S_IN]);
80d8d99d8eSRyder Lee 		}
81d8d99d8eSRyder Lee 
82d8d99d8eSRyder Lee 		snprintf(name, sizeof(name), "asrc%d_out_ck", i);
83d8d99d8eSRyder Lee 		i2s_path->asrco_ck = devm_clk_get(afe->dev, name);
84d8d99d8eSRyder Lee 		if (IS_ERR(i2s_path->asrco_ck)) {
85d8d99d8eSRyder Lee 			dev_err(afe->dev, "failed to get %s\n", name);
86d8d99d8eSRyder Lee 			return PTR_ERR(i2s_path->asrco_ck);
87d8d99d8eSRyder Lee 		}
88d8d99d8eSRyder Lee 	}
89d8d99d8eSRyder Lee 
90d8d99d8eSRyder Lee 	/* Some platforms may support BT path */
91d8d99d8eSRyder Lee 	afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd");
92d8d99d8eSRyder Lee 	if (IS_ERR(afe_priv->mrgif_ck)) {
93d8d99d8eSRyder Lee 		if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER)
94d8d99d8eSRyder Lee 			return -EPROBE_DEFER;
95d8d99d8eSRyder Lee 
96d8d99d8eSRyder Lee 		afe_priv->mrgif_ck = NULL;
97d8d99d8eSRyder Lee 	}
98d8d99d8eSRyder Lee 
99d6f3710aSGarlic Tseng 	return 0;
100d6f3710aSGarlic Tseng }
101d6f3710aSGarlic Tseng 
102d8d99d8eSRyder Lee int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, int id, int dir)
103d8d99d8eSRyder Lee {
104d8d99d8eSRyder Lee 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
105d8d99d8eSRyder Lee 	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
106d8d99d8eSRyder Lee 	int ret;
107d8d99d8eSRyder Lee 
108d8d99d8eSRyder Lee 	ret = clk_prepare_enable(i2s_path->asrco_ck);
109d8d99d8eSRyder Lee 	if (ret) {
110d8d99d8eSRyder Lee 		dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret);
111d8d99d8eSRyder Lee 		return ret;
112d8d99d8eSRyder Lee 	}
113d8d99d8eSRyder Lee 
114d8d99d8eSRyder Lee 	ret = clk_prepare_enable(i2s_path->hop_ck[dir]);
115d8d99d8eSRyder Lee 	if (ret) {
116d8d99d8eSRyder Lee 		dev_err(afe->dev, "failed to enable I2S clock %d\n", ret);
117d8d99d8eSRyder Lee 		goto err_hop_ck;
118d8d99d8eSRyder Lee 	}
119d8d99d8eSRyder Lee 
120d8d99d8eSRyder Lee 	return 0;
121d8d99d8eSRyder Lee 
122d8d99d8eSRyder Lee err_hop_ck:
123d8d99d8eSRyder Lee 	clk_disable_unprepare(i2s_path->asrco_ck);
124d8d99d8eSRyder Lee 
125d8d99d8eSRyder Lee 	return ret;
126d8d99d8eSRyder Lee }
127d8d99d8eSRyder Lee 
128d8d99d8eSRyder Lee void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, int id, int dir)
129d8d99d8eSRyder Lee {
130d8d99d8eSRyder Lee 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
131d8d99d8eSRyder Lee 	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
132d8d99d8eSRyder Lee 
133d8d99d8eSRyder Lee 	clk_disable_unprepare(i2s_path->hop_ck[dir]);
134d8d99d8eSRyder Lee 	clk_disable_unprepare(i2s_path->asrco_ck);
135d8d99d8eSRyder Lee }
136d8d99d8eSRyder Lee 
137d8d99d8eSRyder Lee int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id)
138d8d99d8eSRyder Lee {
139d8d99d8eSRyder Lee 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
140d8d99d8eSRyder Lee 	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
141d8d99d8eSRyder Lee 
142d8d99d8eSRyder Lee 	return clk_prepare_enable(i2s_path->mclk_ck);
143d8d99d8eSRyder Lee }
144d8d99d8eSRyder Lee 
145d8d99d8eSRyder Lee void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id)
146d8d99d8eSRyder Lee {
147d8d99d8eSRyder Lee 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
148d8d99d8eSRyder Lee 	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
149d8d99d8eSRyder Lee 
150d8d99d8eSRyder Lee 	clk_disable_unprepare(i2s_path->mclk_ck);
151d8d99d8eSRyder Lee }
152d8d99d8eSRyder Lee 
153d8d99d8eSRyder Lee int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe)
154d8d99d8eSRyder Lee {
155d8d99d8eSRyder Lee 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
156d8d99d8eSRyder Lee 
157d8d99d8eSRyder Lee 	return clk_prepare_enable(afe_priv->mrgif_ck);
158d8d99d8eSRyder Lee }
159d8d99d8eSRyder Lee 
160d8d99d8eSRyder Lee void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe)
161d8d99d8eSRyder Lee {
162d8d99d8eSRyder Lee 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
163d8d99d8eSRyder Lee 
164d8d99d8eSRyder Lee 	clk_disable_unprepare(afe_priv->mrgif_ck);
165d8d99d8eSRyder Lee }
166d8d99d8eSRyder Lee 
167d8d99d8eSRyder Lee static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe)
168d8d99d8eSRyder Lee {
169d8d99d8eSRyder Lee 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
170d8d99d8eSRyder Lee 	int ret;
171d8d99d8eSRyder Lee 
172d8d99d8eSRyder Lee 	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
173d8d99d8eSRyder Lee 	if (ret)
174d8d99d8eSRyder Lee 		return ret;
175d8d99d8eSRyder Lee 
176d8d99d8eSRyder Lee 	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
177d8d99d8eSRyder Lee 	if (ret)
178d8d99d8eSRyder Lee 		goto err_audio_a1sys;
179d8d99d8eSRyder Lee 
180d8d99d8eSRyder Lee 	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
181d8d99d8eSRyder Lee 	if (ret)
182d8d99d8eSRyder Lee 		goto err_audio_a2sys;
183d8d99d8eSRyder Lee 
184d8d99d8eSRyder Lee 	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);
185d8d99d8eSRyder Lee 	if (ret)
186d8d99d8eSRyder Lee 		goto err_afe_conn;
187d8d99d8eSRyder Lee 
188d8d99d8eSRyder Lee 	return 0;
189d8d99d8eSRyder Lee 
190d8d99d8eSRyder Lee err_afe_conn:
191d8d99d8eSRyder Lee 	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
192d8d99d8eSRyder Lee err_audio_a2sys:
193d8d99d8eSRyder Lee 	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
194d8d99d8eSRyder Lee err_audio_a1sys:
195d8d99d8eSRyder Lee 	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
196d8d99d8eSRyder Lee 
197d8d99d8eSRyder Lee 	return ret;
198d8d99d8eSRyder Lee }
199d8d99d8eSRyder Lee 
200d8d99d8eSRyder Lee static void mt2701_afe_disable_audsys(struct mtk_base_afe *afe)
201d8d99d8eSRyder Lee {
202d8d99d8eSRyder Lee 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
203d8d99d8eSRyder Lee 
204d8d99d8eSRyder Lee 	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);
205d8d99d8eSRyder Lee 	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
206d8d99d8eSRyder Lee 	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
207d8d99d8eSRyder Lee 	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
208d8d99d8eSRyder Lee }
209d8d99d8eSRyder Lee 
210d6f3710aSGarlic Tseng int mt2701_afe_enable_clock(struct mtk_base_afe *afe)
211d6f3710aSGarlic Tseng {
212d8d99d8eSRyder Lee 	int ret;
213d6f3710aSGarlic Tseng 
214d8d99d8eSRyder Lee 	/* Enable audio system */
215d8d99d8eSRyder Lee 	ret = mt2701_afe_enable_audsys(afe);
216d6f3710aSGarlic Tseng 	if (ret) {
217d8d99d8eSRyder Lee 		dev_err(afe->dev, "failed to enable audio system %d\n", ret);
218d6f3710aSGarlic Tseng 		return ret;
219d6f3710aSGarlic Tseng 	}
220d6f3710aSGarlic Tseng 
221d6f3710aSGarlic Tseng 	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
222*600b2fd4SRyder Lee 			   ASYS_TOP_CON_ASYS_TIMING_ON,
223*600b2fd4SRyder Lee 			   ASYS_TOP_CON_ASYS_TIMING_ON);
224d6f3710aSGarlic Tseng 	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
225d6f3710aSGarlic Tseng 			   AFE_DAC_CON0_AFE_ON,
226d6f3710aSGarlic Tseng 			   AFE_DAC_CON0_AFE_ON);
227d8d99d8eSRyder Lee 
228d8d99d8eSRyder Lee 	/* Configure ASRC */
229d8d99d8eSRyder Lee 	regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL);
230d8d99d8eSRyder Lee 	regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL);
231d6f3710aSGarlic Tseng 
232d6f3710aSGarlic Tseng 	return 0;
233d6f3710aSGarlic Tseng }
234d6f3710aSGarlic Tseng 
235d8d99d8eSRyder Lee int mt2701_afe_disable_clock(struct mtk_base_afe *afe)
236d6f3710aSGarlic Tseng {
237d6f3710aSGarlic Tseng 	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
238*600b2fd4SRyder Lee 			   ASYS_TOP_CON_ASYS_TIMING_ON, 0);
239d6f3710aSGarlic Tseng 	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
240d6f3710aSGarlic Tseng 			   AFE_DAC_CON0_AFE_ON, 0);
241d6f3710aSGarlic Tseng 
242d8d99d8eSRyder Lee 	mt2701_afe_disable_audsys(afe);
243d6f3710aSGarlic Tseng 
244d6f3710aSGarlic Tseng 	return 0;
245d6f3710aSGarlic Tseng }
246d6f3710aSGarlic Tseng 
247d6f3710aSGarlic Tseng void mt2701_mclk_configuration(struct mtk_base_afe *afe, int id, int domain,
248d6f3710aSGarlic Tseng 			       int mclk)
249d6f3710aSGarlic Tseng {
250d8d99d8eSRyder Lee 	struct mt2701_afe_private *priv = afe->platform_priv;
251d8d99d8eSRyder Lee 	struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id];
252d6f3710aSGarlic Tseng 	int ret;
253d6f3710aSGarlic Tseng 
254d8d99d8eSRyder Lee 	/* Set mclk source */
255d8d99d8eSRyder Lee 	if (domain == 0)
256d8d99d8eSRyder Lee 		ret = clk_set_parent(i2s_path->sel_ck,
257d8d99d8eSRyder Lee 				     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]);
258d8d99d8eSRyder Lee 	else
259d8d99d8eSRyder Lee 		ret = clk_set_parent(i2s_path->sel_ck,
260d8d99d8eSRyder Lee 				     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]);
261d6f3710aSGarlic Tseng 
262d6f3710aSGarlic Tseng 	if (ret)
263d8d99d8eSRyder Lee 		dev_err(afe->dev, "failed to set domain%d mclk source %d\n",
264d8d99d8eSRyder Lee 			domain, ret);
265d6f3710aSGarlic Tseng 
266d8d99d8eSRyder Lee 	/* Set mclk divider */
267d8d99d8eSRyder Lee 	ret = clk_set_rate(i2s_path->div_ck, mclk);
268d6f3710aSGarlic Tseng 	if (ret)
269d8d99d8eSRyder Lee 		dev_err(afe->dev, "failed to set mclk divider %d\n", ret);
270d6f3710aSGarlic Tseng }
271