mt2701-afe-clock-ctrl.c 8.4 KB
Newer Older
1 2 3 4 5
/*
 * mt2701-afe-clock-ctrl.c  --  Mediatek 2701 afe clock ctrl
 *
 * Copyright (c) 2016 MediaTek Inc.
 * Author: Garlic Tseng <garlic.tseng@mediatek.com>
6
 *	   Ryder Lee <ryder.lee@mediatek.com>
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "mt2701-afe-common.h"
#include "mt2701-afe-clock-ctrl.h"

21
static const char *const base_clks[] = {
22
	[MT2701_INFRA_SYS_AUDIO] = "infra_sys_audio_clk",
23 24
	[MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel",
	[MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel",
25 26
	[MT2701_TOP_AUD_A1SYS] = "top_audio_a1sys_hp",
	[MT2701_TOP_AUD_A2SYS] = "top_audio_a2sys_hp",
27 28 29 30
	[MT2701_AUDSYS_AFE] = "audio_afe_pd",
	[MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd",
	[MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd",
	[MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd",
31 32 33 34 35
};

int mt2701_init_clock(struct mtk_base_afe *afe)
{
	struct mt2701_afe_private *afe_priv = afe->platform_priv;
36 37 38 39 40 41 42
	int i;

	for (i = 0; i < MT2701_BASE_CLK_NUM; i++) {
		afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]);
		if (IS_ERR(afe_priv->base_ck[i])) {
			dev_err(afe->dev, "failed to get %s\n", base_clks[i]);
			return PTR_ERR(afe_priv->base_ck[i]);
43 44 45
		}
	}

46 47 48
	/* Get I2S related clocks */
	for (i = 0; i < MT2701_I2S_NUM; i++) {
		struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i];
49
		struct clk *i2s_ck;
50
		char name[13];
51

52 53 54 55 56 57
		snprintf(name, sizeof(name), "i2s%d_src_sel", i);
		i2s_path->sel_ck = devm_clk_get(afe->dev, name);
		if (IS_ERR(i2s_path->sel_ck)) {
			dev_err(afe->dev, "failed to get %s\n", name);
			return PTR_ERR(i2s_path->sel_ck);
		}
58

59 60 61 62 63 64
		snprintf(name, sizeof(name), "i2s%d_src_div", i);
		i2s_path->div_ck = devm_clk_get(afe->dev, name);
		if (IS_ERR(i2s_path->div_ck)) {
			dev_err(afe->dev, "failed to get %s\n", name);
			return PTR_ERR(i2s_path->div_ck);
		}
65

66 67 68 69 70 71
		snprintf(name, sizeof(name), "i2s%d_mclk_en", i);
		i2s_path->mclk_ck = devm_clk_get(afe->dev, name);
		if (IS_ERR(i2s_path->mclk_ck)) {
			dev_err(afe->dev, "failed to get %s\n", name);
			return PTR_ERR(i2s_path->mclk_ck);
		}
72

73
		snprintf(name, sizeof(name), "i2so%d_hop_ck", i);
74 75
		i2s_ck = devm_clk_get(afe->dev, name);
		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_PLAYBACK] = i2s_ck;
80 81

		snprintf(name, sizeof(name), "i2si%d_hop_ck", i);
82 83
		i2s_ck = devm_clk_get(afe->dev, name);
		if (IS_ERR(i2s_ck)) {
84
			dev_err(afe->dev, "failed to get %s\n", name);
85
			return PTR_ERR(i2s_ck);
86
		}
87
		i2s_path->hop_ck[SNDRV_PCM_STREAM_CAPTURE] = i2s_ck;
88 89 90 91 92 93 94

		snprintf(name, sizeof(name), "asrc%d_out_ck", i);
		i2s_path->asrco_ck = devm_clk_get(afe->dev, name);
		if (IS_ERR(i2s_path->asrco_ck)) {
			dev_err(afe->dev, "failed to get %s\n", name);
			return PTR_ERR(i2s_path->asrco_ck);
		}
95 96
	}

97 98 99 100 101
	/* Some platforms may support BT path */
	afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd");
	if (IS_ERR(afe_priv->mrgif_ck)) {
		if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER)
			return -EPROBE_DEFER;
102

103 104
		afe_priv->mrgif_ck = NULL;
	}
105

106
	return 0;
107 108
}

109 110 111
int mt2701_afe_enable_i2s(struct mtk_base_afe *afe,
			  struct mt2701_i2s_path *i2s_path,
			  int dir)
112
{
113
	int ret;
114

115
	ret = clk_prepare_enable(i2s_path->asrco_ck);
116
	if (ret) {
117 118
		dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret);
		return ret;
119 120
	}

121
	ret = clk_prepare_enable(i2s_path->hop_ck[dir]);
122
	if (ret) {
123 124
		dev_err(afe->dev, "failed to enable I2S clock %d\n", ret);
		goto err_hop_ck;
125 126
	}

127
	return 0;
128

129 130
err_hop_ck:
	clk_disable_unprepare(i2s_path->asrco_ck);
131

132 133
	return ret;
}
134

135 136 137
void mt2701_afe_disable_i2s(struct mtk_base_afe *afe,
			    struct mt2701_i2s_path *i2s_path,
			    int dir)
138 139 140 141
{
	clk_disable_unprepare(i2s_path->hop_ck[dir]);
	clk_disable_unprepare(i2s_path->asrco_ck);
}
142

143 144 145 146
int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id)
{
	struct mt2701_afe_private *afe_priv = afe->platform_priv;
	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
147

148
	return clk_prepare_enable(i2s_path->mclk_ck);
149 150
}

151
void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id)
152 153
{
	struct mt2701_afe_private *afe_priv = afe->platform_priv;
154
	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
155

156
	clk_disable_unprepare(i2s_path->mclk_ck);
157 158
}

159
int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe)
160 161 162
{
	struct mt2701_afe_private *afe_priv = afe->platform_priv;

163 164
	return clk_prepare_enable(afe_priv->mrgif_ck);
}
165

166 167 168
void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe)
{
	struct mt2701_afe_private *afe_priv = afe->platform_priv;
169

170 171
	clk_disable_unprepare(afe_priv->mrgif_ck);
}
172

173 174 175 176
static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe)
{
	struct mt2701_afe_private *afe_priv = afe->platform_priv;
	int ret;
177

178 179
	/* Enable infra clock gate */
	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);
180 181
	if (ret)
		return ret;
182

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
	/* Enable top a1sys clock gate */
	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);
	if (ret)
		goto err_a1sys;

	/* Enable top a2sys clock gate */
	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);
	if (ret)
		goto err_a2sys;

	/* Internal clock gates */
	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
	if (ret)
		goto err_afe;

198 199 200 201 202 203 204 205 206 207 208
	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
	if (ret)
		goto err_audio_a1sys;

	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
	if (ret)
		goto err_audio_a2sys;

	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);
	if (ret)
		goto err_afe_conn;
209 210 211

	return 0;

212 213 214 215 216 217
err_afe_conn:
	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
err_audio_a2sys:
	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
err_audio_a1sys:
	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
218 219 220 221 222 223
err_afe:
	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);
err_a2sys:
	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);
err_a1sys:
	clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);
224 225 226 227

	return ret;
}

228
static void mt2701_afe_disable_audsys(struct mtk_base_afe *afe)
229 230 231
{
	struct mt2701_afe_private *afe_priv = afe->platform_priv;

232 233 234 235
	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);
	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
236 237 238
	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);
	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);
	clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);
239 240
}

241
int mt2701_afe_enable_clock(struct mtk_base_afe *afe)
242 243 244
{
	int ret;

245 246
	/* Enable audio system */
	ret = mt2701_afe_enable_audsys(afe);
247
	if (ret) {
248 249
		dev_err(afe->dev, "failed to enable audio system %d\n", ret);
		return ret;
250 251
	}

252
	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
253 254
			   ASYS_TOP_CON_ASYS_TIMING_ON,
			   ASYS_TOP_CON_ASYS_TIMING_ON);
255 256 257
	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
			   AFE_DAC_CON0_AFE_ON,
			   AFE_DAC_CON0_AFE_ON);
258

259 260 261
	/* Configure ASRC */
	regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL);
	regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL);
262 263 264 265

	return 0;
}

266
int mt2701_afe_disable_clock(struct mtk_base_afe *afe)
267
{
268
	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
269
			   ASYS_TOP_CON_ASYS_TIMING_ON, 0);
270 271
	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
			   AFE_DAC_CON0_AFE_ON, 0);
272

273 274 275
	mt2701_afe_disable_audsys(afe);

	return 0;
276 277
}

278 279
int mt2701_mclk_configuration(struct mtk_base_afe *afe, int id)

280
{
281 282
	struct mt2701_afe_private *priv = afe->platform_priv;
	struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id];
283
	int ret = -EINVAL;
284

285
	/* Set mclk source */
286
	if (!(MT2701_PLL_DOMAIN_0_RATE % i2s_path->mclk_rate))
287 288
		ret = clk_set_parent(i2s_path->sel_ck,
				     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]);
289
	else if (!(MT2701_PLL_DOMAIN_1_RATE % i2s_path->mclk_rate))
290 291
		ret = clk_set_parent(i2s_path->sel_ck,
				     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]);
292

293 294 295 296
	if (ret) {
		dev_err(afe->dev, "failed to set mclk source\n");
		return ret;
	}
297

298
	/* Set mclk divider */
299 300
	ret = clk_set_rate(i2s_path->div_ck, i2s_path->mclk_rate);
	if (ret) {
301
		dev_err(afe->dev, "failed to set mclk divider %d\n", ret);
302 303 304 305
		return ret;
	}

	return 0;
306
}