299 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * mt2701-afe-clock-ctrl.c -- Mediatek 2701 afe clock ctrl4 *5 * Copyright (c) 2016 MediaTek Inc.6 * Author: Garlic Tseng <garlic.tseng@mediatek.com>7 * Ryder Lee <ryder.lee@mediatek.com>8 */9 10#include "mt2701-afe-common.h"11#include "mt2701-afe-clock-ctrl.h"12 13static 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 25int 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 101int 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 121err_hop_ck:122 clk_disable_unprepare(i2s_path->asrco_ck);123 124 return ret;125}126 127void 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 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 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 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]);210err_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]);216 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]);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 233int 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 258int 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 270int 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