Path: blob/master/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
26488 views
// SPDX-License-Identifier: GPL-2.01/*2* mt2701-afe-clock-ctrl.c -- Mediatek 2701 afe clock ctrl3*4* Copyright (c) 2016 MediaTek Inc.5* Author: Garlic Tseng <[email protected]>6* Ryder Lee <[email protected]>7*/89#include "mt2701-afe-common.h"10#include "mt2701-afe-clock-ctrl.h"1112static const char *const base_clks[] = {13[MT2701_INFRA_SYS_AUDIO] = "infra_sys_audio_clk",14[MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel",15[MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel",16[MT2701_TOP_AUD_A1SYS] = "top_audio_a1sys_hp",17[MT2701_TOP_AUD_A2SYS] = "top_audio_a2sys_hp",18[MT2701_AUDSYS_AFE] = "audio_afe_pd",19[MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd",20[MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd",21[MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd",22};2324int mt2701_init_clock(struct mtk_base_afe *afe)25{26struct mt2701_afe_private *afe_priv = afe->platform_priv;27int i;2829for (i = 0; i < MT2701_BASE_CLK_NUM; i++) {30afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]);31if (IS_ERR(afe_priv->base_ck[i])) {32dev_err(afe->dev, "failed to get %s\n", base_clks[i]);33return PTR_ERR(afe_priv->base_ck[i]);34}35}3637/* Get I2S related clocks */38for (i = 0; i < afe_priv->soc->i2s_num; i++) {39struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i];40struct clk *i2s_ck;41char name[13];4243snprintf(name, sizeof(name), "i2s%d_src_sel", i);44i2s_path->sel_ck = devm_clk_get(afe->dev, name);45if (IS_ERR(i2s_path->sel_ck)) {46dev_err(afe->dev, "failed to get %s\n", name);47return PTR_ERR(i2s_path->sel_ck);48}4950snprintf(name, sizeof(name), "i2s%d_src_div", i);51i2s_path->div_ck = devm_clk_get(afe->dev, name);52if (IS_ERR(i2s_path->div_ck)) {53dev_err(afe->dev, "failed to get %s\n", name);54return PTR_ERR(i2s_path->div_ck);55}5657snprintf(name, sizeof(name), "i2s%d_mclk_en", i);58i2s_path->mclk_ck = devm_clk_get(afe->dev, name);59if (IS_ERR(i2s_path->mclk_ck)) {60dev_err(afe->dev, "failed to get %s\n", name);61return PTR_ERR(i2s_path->mclk_ck);62}6364snprintf(name, sizeof(name), "i2so%d_hop_ck", i);65i2s_ck = devm_clk_get(afe->dev, name);66if (IS_ERR(i2s_ck)) {67dev_err(afe->dev, "failed to get %s\n", name);68return PTR_ERR(i2s_ck);69}70i2s_path->hop_ck[SNDRV_PCM_STREAM_PLAYBACK] = i2s_ck;7172snprintf(name, sizeof(name), "i2si%d_hop_ck", i);73i2s_ck = devm_clk_get(afe->dev, name);74if (IS_ERR(i2s_ck)) {75dev_err(afe->dev, "failed to get %s\n", name);76return PTR_ERR(i2s_ck);77}78i2s_path->hop_ck[SNDRV_PCM_STREAM_CAPTURE] = i2s_ck;7980snprintf(name, sizeof(name), "asrc%d_out_ck", i);81i2s_path->asrco_ck = devm_clk_get(afe->dev, name);82if (IS_ERR(i2s_path->asrco_ck)) {83dev_err(afe->dev, "failed to get %s\n", name);84return PTR_ERR(i2s_path->asrco_ck);85}86}8788/* Some platforms may support BT path */89afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd");90if (IS_ERR(afe_priv->mrgif_ck)) {91if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER)92return -EPROBE_DEFER;9394afe_priv->mrgif_ck = NULL;95}9697return 0;98}99100int mt2701_afe_enable_i2s(struct mtk_base_afe *afe,101struct mt2701_i2s_path *i2s_path,102int dir)103{104int ret;105106ret = clk_prepare_enable(i2s_path->asrco_ck);107if (ret) {108dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret);109return ret;110}111112ret = clk_prepare_enable(i2s_path->hop_ck[dir]);113if (ret) {114dev_err(afe->dev, "failed to enable I2S clock %d\n", ret);115goto err_hop_ck;116}117118return 0;119120err_hop_ck:121clk_disable_unprepare(i2s_path->asrco_ck);122123return ret;124}125126void mt2701_afe_disable_i2s(struct mtk_base_afe *afe,127struct mt2701_i2s_path *i2s_path,128int dir)129{130clk_disable_unprepare(i2s_path->hop_ck[dir]);131clk_disable_unprepare(i2s_path->asrco_ck);132}133134int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id)135{136struct mt2701_afe_private *afe_priv = afe->platform_priv;137struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];138139return clk_prepare_enable(i2s_path->mclk_ck);140}141142void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id)143{144struct mt2701_afe_private *afe_priv = afe->platform_priv;145struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];146147clk_disable_unprepare(i2s_path->mclk_ck);148}149150int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe)151{152struct mt2701_afe_private *afe_priv = afe->platform_priv;153154return clk_prepare_enable(afe_priv->mrgif_ck);155}156157void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe)158{159struct mt2701_afe_private *afe_priv = afe->platform_priv;160161clk_disable_unprepare(afe_priv->mrgif_ck);162}163164static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe)165{166struct mt2701_afe_private *afe_priv = afe->platform_priv;167int ret;168169/* Enable infra clock gate */170ret = clk_prepare_enable(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);171if (ret)172return ret;173174/* Enable top a1sys clock gate */175ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);176if (ret)177goto err_a1sys;178179/* Enable top a2sys clock gate */180ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);181if (ret)182goto err_a2sys;183184/* Internal clock gates */185ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]);186if (ret)187goto err_afe;188189ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);190if (ret)191goto err_audio_a1sys;192193ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);194if (ret)195goto err_audio_a2sys;196197ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);198if (ret)199goto err_afe_conn;200201return 0;202203err_afe_conn:204clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);205err_audio_a2sys:206clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);207err_audio_a1sys:208clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);209err_afe:210clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);211err_a2sys:212clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);213err_a1sys:214clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);215216return ret;217}218219static void mt2701_afe_disable_audsys(struct mtk_base_afe *afe)220{221struct mt2701_afe_private *afe_priv = afe->platform_priv;222223clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);224clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);225clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);226clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);227clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);228clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);229clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);230}231232int mt2701_afe_enable_clock(struct mtk_base_afe *afe)233{234int ret;235236/* Enable audio system */237ret = mt2701_afe_enable_audsys(afe);238if (ret) {239dev_err(afe->dev, "failed to enable audio system %d\n", ret);240return ret;241}242243regmap_update_bits(afe->regmap, ASYS_TOP_CON,244ASYS_TOP_CON_ASYS_TIMING_ON,245ASYS_TOP_CON_ASYS_TIMING_ON);246regmap_update_bits(afe->regmap, AFE_DAC_CON0,247AFE_DAC_CON0_AFE_ON,248AFE_DAC_CON0_AFE_ON);249250/* Configure ASRC */251regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL);252regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL);253254return 0;255}256257int mt2701_afe_disable_clock(struct mtk_base_afe *afe)258{259regmap_update_bits(afe->regmap, ASYS_TOP_CON,260ASYS_TOP_CON_ASYS_TIMING_ON, 0);261regmap_update_bits(afe->regmap, AFE_DAC_CON0,262AFE_DAC_CON0_AFE_ON, 0);263264mt2701_afe_disable_audsys(afe);265266return 0;267}268269int mt2701_mclk_configuration(struct mtk_base_afe *afe, int id)270271{272struct mt2701_afe_private *priv = afe->platform_priv;273struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id];274int ret = -EINVAL;275276/* Set mclk source */277if (!(MT2701_PLL_DOMAIN_0_RATE % i2s_path->mclk_rate))278ret = clk_set_parent(i2s_path->sel_ck,279priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]);280else if (!(MT2701_PLL_DOMAIN_1_RATE % i2s_path->mclk_rate))281ret = clk_set_parent(i2s_path->sel_ck,282priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]);283284if (ret) {285dev_err(afe->dev, "failed to set mclk source\n");286return ret;287}288289/* Set mclk divider */290ret = clk_set_rate(i2s_path->div_ck, i2s_path->mclk_rate);291if (ret) {292dev_err(afe->dev, "failed to set mclk divider %d\n", ret);293return ret;294}295296return 0;297}298299300