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