blob: ae620890bb3ac92ceaf955dcb6d134e87b854ec3 [file] [log] [blame]
Ryder Lee3a280ed2018-04-25 12:19:59 +08001// SPDX-License-Identifier: GPL-2.0
Garlic Tsengd6f37102016-06-17 15:43:56 +08002/*
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>
Ryder Leecf870272018-04-25 12:19:55 +08007 * Ryder Lee <ryder.lee@mediatek.com>
Garlic Tsengd6f37102016-06-17 15:43:56 +08008 */
9
Garlic Tsengd6f37102016-06-17 15:43:56 +080010#include "mt2701-afe-common.h"
11#include "mt2701-afe-clock-ctrl.h"
12
Ryder Leed8d99d82018-01-02 19:47:19 +080013static const char *const base_clks[] = {
Ryder Lee96365d92018-01-04 15:44:07 +080014 [MT2701_INFRA_SYS_AUDIO] = "infra_sys_audio_clk",
Ryder Leed8d99d82018-01-02 19:47:19 +080015 [MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel",
16 [MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel",
Ryder Lee96365d92018-01-04 15:44:07 +080017 [MT2701_TOP_AUD_A1SYS] = "top_audio_a1sys_hp",
18 [MT2701_TOP_AUD_A2SYS] = "top_audio_a2sys_hp",
Ryder Leed8d99d82018-01-02 19:47:19 +080019 [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",
Garlic Tsengd6f37102016-06-17 15:43:56 +080023};
24
25int mt2701_init_clock(struct mtk_base_afe *afe)
26{
27 struct mt2701_afe_private *afe_priv = afe->platform_priv;
Ryder Leed8d99d82018-01-02 19:47:19 +080028 int i;
Garlic Tsengd6f37102016-06-17 15:43:56 +080029
Ryder Leed8d99d82018-01-02 19:47:19 +080030 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]);
Garlic Tsengd6f37102016-06-17 15:43:56 +080035 }
36 }
37
Ryder Leed8d99d82018-01-02 19:47:19 +080038 /* Get I2S related clocks */
Ryder Leebfdc56e2018-04-25 12:19:57 +080039 for (i = 0; i < afe_priv->soc->i2s_num; i++) {
Ryder Leed8d99d82018-01-02 19:47:19 +080040 struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i];
Ryder Leeab7b4ee2018-04-25 12:19:56 +080041 struct clk *i2s_ck;
Ryder Leed8d99d82018-01-02 19:47:19 +080042 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);
Ryder Leeab7b4ee2018-04-25 12:19:56 +080066 i2s_ck = devm_clk_get(afe->dev, name);
67 if (IS_ERR(i2s_ck)) {
Ryder Leed8d99d82018-01-02 19:47:19 +080068 dev_err(afe->dev, "failed to get %s\n", name);
Ryder Leeab7b4ee2018-04-25 12:19:56 +080069 return PTR_ERR(i2s_ck);
Ryder Leed8d99d82018-01-02 19:47:19 +080070 }
Ryder Leeab7b4ee2018-04-25 12:19:56 +080071 i2s_path->hop_ck[SNDRV_PCM_STREAM_PLAYBACK] = i2s_ck;
Ryder Leed8d99d82018-01-02 19:47:19 +080072
73 snprintf(name, sizeof(name), "i2si%d_hop_ck", i);
Ryder Leeab7b4ee2018-04-25 12:19:56 +080074 i2s_ck = devm_clk_get(afe->dev, name);
75 if (IS_ERR(i2s_ck)) {
Ryder Leed8d99d82018-01-02 19:47:19 +080076 dev_err(afe->dev, "failed to get %s\n", name);
Ryder Leeab7b4ee2018-04-25 12:19:56 +080077 return PTR_ERR(i2s_ck);
Ryder Leed8d99d82018-01-02 19:47:19 +080078 }
Ryder Leeab7b4ee2018-04-25 12:19:56 +080079 i2s_path->hop_ck[SNDRV_PCM_STREAM_CAPTURE] = i2s_ck;
Ryder Leed8d99d82018-01-02 19:47:19 +080080
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
Garlic Tsengd6f37102016-06-17 15:43:56 +080098 return 0;
99}
100
Ryder Leecf870272018-04-25 12:19:55 +0800101int mt2701_afe_enable_i2s(struct mtk_base_afe *afe,
102 struct mt2701_i2s_path *i2s_path,
103 int dir)
Ryder Leed8d99d82018-01-02 19:47:19 +0800104{
Ryder Leed8d99d82018-01-02 19:47:19 +0800105 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
Ryder Leecf870272018-04-25 12:19:55 +0800127void mt2701_afe_disable_i2s(struct mtk_base_afe *afe,
128 struct mt2701_i2s_path *i2s_path,
129 int dir)
Ryder Leed8d99d82018-01-02 19:47:19 +0800130{
Ryder Leed8d99d82018-01-02 19:47:19 +0800131 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
Ryder Lee96365d92018-01-04 15:44:07 +0800170 /* Enable infra clock gate */
171 ret = clk_prepare_enable(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);
Ryder Leed8d99d82018-01-02 19:47:19 +0800172 if (ret)
173 return ret;
174
Ryder Lee96365d92018-01-04 15:44:07 +0800175 /* 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
Ryder Leed8d99d82018-01-02 19:47:19 +0800190 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]);
Ryder Lee96365d92018-01-04 15:44:07 +0800210err_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]);
Ryder Leed8d99d82018-01-02 19:47:19 +0800216
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]);
Ryder Lee96365d92018-01-04 15:44:07 +0800228 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]);
Ryder Leed8d99d82018-01-02 19:47:19 +0800231}
232
Garlic Tsengd6f37102016-06-17 15:43:56 +0800233int mt2701_afe_enable_clock(struct mtk_base_afe *afe)
234{
Ryder Leed8d99d82018-01-02 19:47:19 +0800235 int ret;
Garlic Tsengd6f37102016-06-17 15:43:56 +0800236
Ryder Leed8d99d82018-01-02 19:47:19 +0800237 /* Enable audio system */
238 ret = mt2701_afe_enable_audsys(afe);
Garlic Tsengd6f37102016-06-17 15:43:56 +0800239 if (ret) {
Ryder Leed8d99d82018-01-02 19:47:19 +0800240 dev_err(afe->dev, "failed to enable audio system %d\n", ret);
Garlic Tsengd6f37102016-06-17 15:43:56 +0800241 return ret;
242 }
243
244 regmap_update_bits(afe->regmap, ASYS_TOP_CON,
Ryder Lee600b2fd2018-01-02 19:47:20 +0800245 ASYS_TOP_CON_ASYS_TIMING_ON,
246 ASYS_TOP_CON_ASYS_TIMING_ON);
Garlic Tsengd6f37102016-06-17 15:43:56 +0800247 regmap_update_bits(afe->regmap, AFE_DAC_CON0,
248 AFE_DAC_CON0_AFE_ON,
249 AFE_DAC_CON0_AFE_ON);
Ryder Leed8d99d82018-01-02 19:47:19 +0800250
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);
Garlic Tsengd6f37102016-06-17 15:43:56 +0800254
255 return 0;
256}
257
Ryder Leed8d99d82018-01-02 19:47:19 +0800258int mt2701_afe_disable_clock(struct mtk_base_afe *afe)
Garlic Tsengd6f37102016-06-17 15:43:56 +0800259{
Garlic Tsengd6f37102016-06-17 15:43:56 +0800260 regmap_update_bits(afe->regmap, ASYS_TOP_CON,
Ryder Lee600b2fd2018-01-02 19:47:20 +0800261 ASYS_TOP_CON_ASYS_TIMING_ON, 0);
Garlic Tsengd6f37102016-06-17 15:43:56 +0800262 regmap_update_bits(afe->regmap, AFE_DAC_CON0,
263 AFE_DAC_CON0_AFE_ON, 0);
Garlic Tsengd6f37102016-06-17 15:43:56 +0800264
Ryder Leed8d99d82018-01-02 19:47:19 +0800265 mt2701_afe_disable_audsys(afe);
Garlic Tsengd6f37102016-06-17 15:43:56 +0800266
267 return 0;
Garlic Tsengd6f37102016-06-17 15:43:56 +0800268}
269
Ryder Leecf870272018-04-25 12:19:55 +0800270int mt2701_mclk_configuration(struct mtk_base_afe *afe, int id)
271
Garlic Tsengd6f37102016-06-17 15:43:56 +0800272{
Ryder Leed8d99d82018-01-02 19:47:19 +0800273 struct mt2701_afe_private *priv = afe->platform_priv;
274 struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id];
Ryder Leecf870272018-04-25 12:19:55 +0800275 int ret = -EINVAL;
Garlic Tsengd6f37102016-06-17 15:43:56 +0800276
Ryder Leed8d99d82018-01-02 19:47:19 +0800277 /* Set mclk source */
Ryder Leecf870272018-04-25 12:19:55 +0800278 if (!(MT2701_PLL_DOMAIN_0_RATE % i2s_path->mclk_rate))
Ryder Leed8d99d82018-01-02 19:47:19 +0800279 ret = clk_set_parent(i2s_path->sel_ck,
280 priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]);
Ryder Leecf870272018-04-25 12:19:55 +0800281 else if (!(MT2701_PLL_DOMAIN_1_RATE % i2s_path->mclk_rate))
Ryder Leed8d99d82018-01-02 19:47:19 +0800282 ret = clk_set_parent(i2s_path->sel_ck,
283 priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]);
284
Ryder Leecf870272018-04-25 12:19:55 +0800285 if (ret) {
286 dev_err(afe->dev, "failed to set mclk source\n");
287 return ret;
288 }
Garlic Tsengd6f37102016-06-17 15:43:56 +0800289
Ryder Leed8d99d82018-01-02 19:47:19 +0800290 /* Set mclk divider */
Ryder Leecf870272018-04-25 12:19:55 +0800291 ret = clk_set_rate(i2s_path->div_ck, i2s_path->mclk_rate);
292 if (ret) {
Ryder Leed8d99d82018-01-02 19:47:19 +0800293 dev_err(afe->dev, "failed to set mclk divider %d\n", ret);
Ryder Leecf870272018-04-25 12:19:55 +0800294 return ret;
295 }
296
297 return 0;
Garlic Tsengd6f37102016-06-17 15:43:56 +0800298}