Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
26488 views
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 <[email protected]>
7
* Ryder Lee <[email protected]>
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
300