162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * mt2701-afe-clock-ctrl.c  --  Mediatek 2701 afe clock ctrl
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2016 MediaTek Inc.
662306a36Sopenharmony_ci * Author: Garlic Tseng <garlic.tseng@mediatek.com>
762306a36Sopenharmony_ci *	   Ryder Lee <ryder.lee@mediatek.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "mt2701-afe-common.h"
1162306a36Sopenharmony_ci#include "mt2701-afe-clock-ctrl.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic const char *const base_clks[] = {
1462306a36Sopenharmony_ci	[MT2701_INFRA_SYS_AUDIO] = "infra_sys_audio_clk",
1562306a36Sopenharmony_ci	[MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel",
1662306a36Sopenharmony_ci	[MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel",
1762306a36Sopenharmony_ci	[MT2701_TOP_AUD_A1SYS] = "top_audio_a1sys_hp",
1862306a36Sopenharmony_ci	[MT2701_TOP_AUD_A2SYS] = "top_audio_a2sys_hp",
1962306a36Sopenharmony_ci	[MT2701_AUDSYS_AFE] = "audio_afe_pd",
2062306a36Sopenharmony_ci	[MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd",
2162306a36Sopenharmony_ci	[MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd",
2262306a36Sopenharmony_ci	[MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd",
2362306a36Sopenharmony_ci};
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ciint mt2701_init_clock(struct mtk_base_afe *afe)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	struct mt2701_afe_private *afe_priv = afe->platform_priv;
2862306a36Sopenharmony_ci	int i;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	for (i = 0; i < MT2701_BASE_CLK_NUM; i++) {
3162306a36Sopenharmony_ci		afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]);
3262306a36Sopenharmony_ci		if (IS_ERR(afe_priv->base_ck[i])) {
3362306a36Sopenharmony_ci			dev_err(afe->dev, "failed to get %s\n", base_clks[i]);
3462306a36Sopenharmony_ci			return PTR_ERR(afe_priv->base_ck[i]);
3562306a36Sopenharmony_ci		}
3662306a36Sopenharmony_ci	}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	/* Get I2S related clocks */
3962306a36Sopenharmony_ci	for (i = 0; i < afe_priv->soc->i2s_num; i++) {
4062306a36Sopenharmony_ci		struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i];
4162306a36Sopenharmony_ci		struct clk *i2s_ck;
4262306a36Sopenharmony_ci		char name[13];
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci		snprintf(name, sizeof(name), "i2s%d_src_sel", i);
4562306a36Sopenharmony_ci		i2s_path->sel_ck = devm_clk_get(afe->dev, name);
4662306a36Sopenharmony_ci		if (IS_ERR(i2s_path->sel_ck)) {
4762306a36Sopenharmony_ci			dev_err(afe->dev, "failed to get %s\n", name);
4862306a36Sopenharmony_ci			return PTR_ERR(i2s_path->sel_ck);
4962306a36Sopenharmony_ci		}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci		snprintf(name, sizeof(name), "i2s%d_src_div", i);
5262306a36Sopenharmony_ci		i2s_path->div_ck = devm_clk_get(afe->dev, name);
5362306a36Sopenharmony_ci		if (IS_ERR(i2s_path->div_ck)) {
5462306a36Sopenharmony_ci			dev_err(afe->dev, "failed to get %s\n", name);
5562306a36Sopenharmony_ci			return PTR_ERR(i2s_path->div_ck);
5662306a36Sopenharmony_ci		}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci		snprintf(name, sizeof(name), "i2s%d_mclk_en", i);
5962306a36Sopenharmony_ci		i2s_path->mclk_ck = devm_clk_get(afe->dev, name);
6062306a36Sopenharmony_ci		if (IS_ERR(i2s_path->mclk_ck)) {
6162306a36Sopenharmony_ci			dev_err(afe->dev, "failed to get %s\n", name);
6262306a36Sopenharmony_ci			return PTR_ERR(i2s_path->mclk_ck);
6362306a36Sopenharmony_ci		}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci		snprintf(name, sizeof(name), "i2so%d_hop_ck", i);
6662306a36Sopenharmony_ci		i2s_ck = devm_clk_get(afe->dev, name);
6762306a36Sopenharmony_ci		if (IS_ERR(i2s_ck)) {
6862306a36Sopenharmony_ci			dev_err(afe->dev, "failed to get %s\n", name);
6962306a36Sopenharmony_ci			return PTR_ERR(i2s_ck);
7062306a36Sopenharmony_ci		}
7162306a36Sopenharmony_ci		i2s_path->hop_ck[SNDRV_PCM_STREAM_PLAYBACK] = i2s_ck;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci		snprintf(name, sizeof(name), "i2si%d_hop_ck", i);
7462306a36Sopenharmony_ci		i2s_ck = devm_clk_get(afe->dev, name);
7562306a36Sopenharmony_ci		if (IS_ERR(i2s_ck)) {
7662306a36Sopenharmony_ci			dev_err(afe->dev, "failed to get %s\n", name);
7762306a36Sopenharmony_ci			return PTR_ERR(i2s_ck);
7862306a36Sopenharmony_ci		}
7962306a36Sopenharmony_ci		i2s_path->hop_ck[SNDRV_PCM_STREAM_CAPTURE] = i2s_ck;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci		snprintf(name, sizeof(name), "asrc%d_out_ck", i);
8262306a36Sopenharmony_ci		i2s_path->asrco_ck = devm_clk_get(afe->dev, name);
8362306a36Sopenharmony_ci		if (IS_ERR(i2s_path->asrco_ck)) {
8462306a36Sopenharmony_ci			dev_err(afe->dev, "failed to get %s\n", name);
8562306a36Sopenharmony_ci			return PTR_ERR(i2s_path->asrco_ck);
8662306a36Sopenharmony_ci		}
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	/* Some platforms may support BT path */
9062306a36Sopenharmony_ci	afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd");
9162306a36Sopenharmony_ci	if (IS_ERR(afe_priv->mrgif_ck)) {
9262306a36Sopenharmony_ci		if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER)
9362306a36Sopenharmony_ci			return -EPROBE_DEFER;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci		afe_priv->mrgif_ck = NULL;
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	return 0;
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ciint mt2701_afe_enable_i2s(struct mtk_base_afe *afe,
10262306a36Sopenharmony_ci			  struct mt2701_i2s_path *i2s_path,
10362306a36Sopenharmony_ci			  int dir)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	int ret;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	ret = clk_prepare_enable(i2s_path->asrco_ck);
10862306a36Sopenharmony_ci	if (ret) {
10962306a36Sopenharmony_ci		dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret);
11062306a36Sopenharmony_ci		return ret;
11162306a36Sopenharmony_ci	}
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	ret = clk_prepare_enable(i2s_path->hop_ck[dir]);
11462306a36Sopenharmony_ci	if (ret) {
11562306a36Sopenharmony_ci		dev_err(afe->dev, "failed to enable I2S clock %d\n", ret);
11662306a36Sopenharmony_ci		goto err_hop_ck;
11762306a36Sopenharmony_ci	}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	return 0;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cierr_hop_ck:
12262306a36Sopenharmony_ci	clk_disable_unprepare(i2s_path->asrco_ck);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	return ret;
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_civoid mt2701_afe_disable_i2s(struct mtk_base_afe *afe,
12862306a36Sopenharmony_ci			    struct mt2701_i2s_path *i2s_path,
12962306a36Sopenharmony_ci			    int dir)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	clk_disable_unprepare(i2s_path->hop_ck[dir]);
13262306a36Sopenharmony_ci	clk_disable_unprepare(i2s_path->asrco_ck);
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ciint mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	struct mt2701_afe_private *afe_priv = afe->platform_priv;
13862306a36Sopenharmony_ci	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	return clk_prepare_enable(i2s_path->mclk_ck);
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_civoid mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	struct mt2701_afe_private *afe_priv = afe->platform_priv;
14662306a36Sopenharmony_ci	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	clk_disable_unprepare(i2s_path->mclk_ck);
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ciint mt2701_enable_btmrg_clk(struct mtk_base_afe *afe)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	struct mt2701_afe_private *afe_priv = afe->platform_priv;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	return clk_prepare_enable(afe_priv->mrgif_ck);
15662306a36Sopenharmony_ci}
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_civoid mt2701_disable_btmrg_clk(struct mtk_base_afe *afe)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	struct mt2701_afe_private *afe_priv = afe->platform_priv;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->mrgif_ck);
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic int mt2701_afe_enable_audsys(struct mtk_base_afe *afe)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	struct mt2701_afe_private *afe_priv = afe->platform_priv;
16862306a36Sopenharmony_ci	int ret;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	/* Enable infra clock gate */
17162306a36Sopenharmony_ci	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);
17262306a36Sopenharmony_ci	if (ret)
17362306a36Sopenharmony_ci		return ret;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	/* Enable top a1sys clock gate */
17662306a36Sopenharmony_ci	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);
17762306a36Sopenharmony_ci	if (ret)
17862306a36Sopenharmony_ci		goto err_a1sys;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	/* Enable top a2sys clock gate */
18162306a36Sopenharmony_ci	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);
18262306a36Sopenharmony_ci	if (ret)
18362306a36Sopenharmony_ci		goto err_a2sys;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	/* Internal clock gates */
18662306a36Sopenharmony_ci	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
18762306a36Sopenharmony_ci	if (ret)
18862306a36Sopenharmony_ci		goto err_afe;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
19162306a36Sopenharmony_ci	if (ret)
19262306a36Sopenharmony_ci		goto err_audio_a1sys;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
19562306a36Sopenharmony_ci	if (ret)
19662306a36Sopenharmony_ci		goto err_audio_a2sys;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);
19962306a36Sopenharmony_ci	if (ret)
20062306a36Sopenharmony_ci		goto err_afe_conn;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	return 0;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cierr_afe_conn:
20562306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
20662306a36Sopenharmony_cierr_audio_a2sys:
20762306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
20862306a36Sopenharmony_cierr_audio_a1sys:
20962306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
21062306a36Sopenharmony_cierr_afe:
21162306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);
21262306a36Sopenharmony_cierr_a2sys:
21362306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);
21462306a36Sopenharmony_cierr_a1sys:
21562306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	return ret;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cistatic void mt2701_afe_disable_audsys(struct mtk_base_afe *afe)
22162306a36Sopenharmony_ci{
22262306a36Sopenharmony_ci	struct mt2701_afe_private *afe_priv = afe->platform_priv;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);
22562306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
22662306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
22762306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
22862306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);
22962306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);
23062306a36Sopenharmony_ci	clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);
23162306a36Sopenharmony_ci}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ciint mt2701_afe_enable_clock(struct mtk_base_afe *afe)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	int ret;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	/* Enable audio system */
23862306a36Sopenharmony_ci	ret = mt2701_afe_enable_audsys(afe);
23962306a36Sopenharmony_ci	if (ret) {
24062306a36Sopenharmony_ci		dev_err(afe->dev, "failed to enable audio system %d\n", ret);
24162306a36Sopenharmony_ci		return ret;
24262306a36Sopenharmony_ci	}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
24562306a36Sopenharmony_ci			   ASYS_TOP_CON_ASYS_TIMING_ON,
24662306a36Sopenharmony_ci			   ASYS_TOP_CON_ASYS_TIMING_ON);
24762306a36Sopenharmony_ci	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
24862306a36Sopenharmony_ci			   AFE_DAC_CON0_AFE_ON,
24962306a36Sopenharmony_ci			   AFE_DAC_CON0_AFE_ON);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	/* Configure ASRC */
25262306a36Sopenharmony_ci	regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL);
25362306a36Sopenharmony_ci	regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	return 0;
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ciint mt2701_afe_disable_clock(struct mtk_base_afe *afe)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
26162306a36Sopenharmony_ci			   ASYS_TOP_CON_ASYS_TIMING_ON, 0);
26262306a36Sopenharmony_ci	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
26362306a36Sopenharmony_ci			   AFE_DAC_CON0_AFE_ON, 0);
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	mt2701_afe_disable_audsys(afe);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	return 0;
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ciint mt2701_mclk_configuration(struct mtk_base_afe *afe, int id)
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	struct mt2701_afe_private *priv = afe->platform_priv;
27462306a36Sopenharmony_ci	struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id];
27562306a36Sopenharmony_ci	int ret = -EINVAL;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	/* Set mclk source */
27862306a36Sopenharmony_ci	if (!(MT2701_PLL_DOMAIN_0_RATE % i2s_path->mclk_rate))
27962306a36Sopenharmony_ci		ret = clk_set_parent(i2s_path->sel_ck,
28062306a36Sopenharmony_ci				     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]);
28162306a36Sopenharmony_ci	else if (!(MT2701_PLL_DOMAIN_1_RATE % i2s_path->mclk_rate))
28262306a36Sopenharmony_ci		ret = clk_set_parent(i2s_path->sel_ck,
28362306a36Sopenharmony_ci				     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	if (ret) {
28662306a36Sopenharmony_ci		dev_err(afe->dev, "failed to set mclk source\n");
28762306a36Sopenharmony_ci		return ret;
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	/* Set mclk divider */
29162306a36Sopenharmony_ci	ret = clk_set_rate(i2s_path->div_ck, i2s_path->mclk_rate);
29262306a36Sopenharmony_ci	if (ret) {
29362306a36Sopenharmony_ci		dev_err(afe->dev, "failed to set mclk divider %d\n", ret);
29462306a36Sopenharmony_ci		return ret;
29562306a36Sopenharmony_ci	}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	return 0;
29862306a36Sopenharmony_ci}
299