1*3a280ed1SRyder Lee // SPDX-License-Identifier: GPL-2.0 2d6f3710aSGarlic Tseng /* 3d6f3710aSGarlic Tseng * mt2701-afe-clock-ctrl.c -- Mediatek 2701 afe clock ctrl 4d6f3710aSGarlic Tseng * 5d6f3710aSGarlic Tseng * Copyright (c) 2016 MediaTek Inc. 6d6f3710aSGarlic Tseng * Author: Garlic Tseng <garlic.tseng@mediatek.com> 7cf870273SRyder Lee * Ryder Lee <ryder.lee@mediatek.com> 8d6f3710aSGarlic Tseng */ 9d6f3710aSGarlic Tseng 10d6f3710aSGarlic Tseng #include "mt2701-afe-common.h" 11d6f3710aSGarlic Tseng #include "mt2701-afe-clock-ctrl.h" 12d6f3710aSGarlic Tseng 13d8d99d8eSRyder Lee static const char *const base_clks[] = { 1496365d9fSRyder Lee [MT2701_INFRA_SYS_AUDIO] = "infra_sys_audio_clk", 15d8d99d8eSRyder Lee [MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel", 16d8d99d8eSRyder Lee [MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel", 1796365d9fSRyder Lee [MT2701_TOP_AUD_A1SYS] = "top_audio_a1sys_hp", 1896365d9fSRyder Lee [MT2701_TOP_AUD_A2SYS] = "top_audio_a2sys_hp", 19d8d99d8eSRyder Lee [MT2701_AUDSYS_AFE] = "audio_afe_pd", 20d8d99d8eSRyder Lee [MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd", 21d8d99d8eSRyder Lee [MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd", 22d8d99d8eSRyder Lee [MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd", 23d6f3710aSGarlic Tseng }; 24d6f3710aSGarlic Tseng 25d6f3710aSGarlic Tseng int mt2701_init_clock(struct mtk_base_afe *afe) 26d6f3710aSGarlic Tseng { 27d6f3710aSGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 28d8d99d8eSRyder Lee int i; 29d6f3710aSGarlic Tseng 30d8d99d8eSRyder Lee for (i = 0; i < MT2701_BASE_CLK_NUM; i++) { 31d8d99d8eSRyder Lee afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]); 32d8d99d8eSRyder Lee if (IS_ERR(afe_priv->base_ck[i])) { 33d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", base_clks[i]); 34d8d99d8eSRyder Lee return PTR_ERR(afe_priv->base_ck[i]); 35d6f3710aSGarlic Tseng } 36d6f3710aSGarlic Tseng } 37d6f3710aSGarlic Tseng 38d8d99d8eSRyder Lee /* Get I2S related clocks */ 39bfdc56e5SRyder Lee for (i = 0; i < afe_priv->soc->i2s_num; i++) { 40d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i]; 41ab7b4ee9SRyder Lee struct clk *i2s_ck; 42d8d99d8eSRyder Lee char name[13]; 43d8d99d8eSRyder Lee 44d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_src_sel", i); 45d8d99d8eSRyder Lee i2s_path->sel_ck = devm_clk_get(afe->dev, name); 46d8d99d8eSRyder Lee if (IS_ERR(i2s_path->sel_ck)) { 47d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 48d8d99d8eSRyder Lee return PTR_ERR(i2s_path->sel_ck); 49d8d99d8eSRyder Lee } 50d8d99d8eSRyder Lee 51d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_src_div", i); 52d8d99d8eSRyder Lee i2s_path->div_ck = devm_clk_get(afe->dev, name); 53d8d99d8eSRyder Lee if (IS_ERR(i2s_path->div_ck)) { 54d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 55d8d99d8eSRyder Lee return PTR_ERR(i2s_path->div_ck); 56d8d99d8eSRyder Lee } 57d8d99d8eSRyder Lee 58d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_mclk_en", i); 59d8d99d8eSRyder Lee i2s_path->mclk_ck = devm_clk_get(afe->dev, name); 60d8d99d8eSRyder Lee if (IS_ERR(i2s_path->mclk_ck)) { 61d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 62d8d99d8eSRyder Lee return PTR_ERR(i2s_path->mclk_ck); 63d8d99d8eSRyder Lee } 64d8d99d8eSRyder Lee 65d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2so%d_hop_ck", i); 66ab7b4ee9SRyder Lee i2s_ck = devm_clk_get(afe->dev, name); 67ab7b4ee9SRyder Lee if (IS_ERR(i2s_ck)) { 68d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 69ab7b4ee9SRyder Lee return PTR_ERR(i2s_ck); 70d8d99d8eSRyder Lee } 71ab7b4ee9SRyder Lee i2s_path->hop_ck[SNDRV_PCM_STREAM_PLAYBACK] = i2s_ck; 72d8d99d8eSRyder Lee 73d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2si%d_hop_ck", i); 74ab7b4ee9SRyder Lee i2s_ck = devm_clk_get(afe->dev, name); 75ab7b4ee9SRyder Lee if (IS_ERR(i2s_ck)) { 76d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 77ab7b4ee9SRyder Lee return PTR_ERR(i2s_ck); 78d8d99d8eSRyder Lee } 79ab7b4ee9SRyder Lee i2s_path->hop_ck[SNDRV_PCM_STREAM_CAPTURE] = i2s_ck; 80d8d99d8eSRyder Lee 81d8d99d8eSRyder Lee snprintf(name, sizeof(name), "asrc%d_out_ck", i); 82d8d99d8eSRyder Lee i2s_path->asrco_ck = devm_clk_get(afe->dev, name); 83d8d99d8eSRyder Lee if (IS_ERR(i2s_path->asrco_ck)) { 84d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 85d8d99d8eSRyder Lee return PTR_ERR(i2s_path->asrco_ck); 86d8d99d8eSRyder Lee } 87d8d99d8eSRyder Lee } 88d8d99d8eSRyder Lee 89d8d99d8eSRyder Lee /* Some platforms may support BT path */ 90d8d99d8eSRyder Lee afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd"); 91d8d99d8eSRyder Lee if (IS_ERR(afe_priv->mrgif_ck)) { 92d8d99d8eSRyder Lee if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER) 93d8d99d8eSRyder Lee return -EPROBE_DEFER; 94d8d99d8eSRyder Lee 95d8d99d8eSRyder Lee afe_priv->mrgif_ck = NULL; 96d8d99d8eSRyder Lee } 97d8d99d8eSRyder Lee 98d6f3710aSGarlic Tseng return 0; 99d6f3710aSGarlic Tseng } 100d6f3710aSGarlic Tseng 101cf870273SRyder Lee int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, 102cf870273SRyder Lee struct mt2701_i2s_path *i2s_path, 103cf870273SRyder Lee int dir) 104d8d99d8eSRyder Lee { 105d8d99d8eSRyder Lee int ret; 106d8d99d8eSRyder Lee 107d8d99d8eSRyder Lee ret = clk_prepare_enable(i2s_path->asrco_ck); 108d8d99d8eSRyder Lee if (ret) { 109d8d99d8eSRyder Lee dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret); 110d8d99d8eSRyder Lee return ret; 111d8d99d8eSRyder Lee } 112d8d99d8eSRyder Lee 113d8d99d8eSRyder Lee ret = clk_prepare_enable(i2s_path->hop_ck[dir]); 114d8d99d8eSRyder Lee if (ret) { 115d8d99d8eSRyder Lee dev_err(afe->dev, "failed to enable I2S clock %d\n", ret); 116d8d99d8eSRyder Lee goto err_hop_ck; 117d8d99d8eSRyder Lee } 118d8d99d8eSRyder Lee 119d8d99d8eSRyder Lee return 0; 120d8d99d8eSRyder Lee 121d8d99d8eSRyder Lee err_hop_ck: 122d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->asrco_ck); 123d8d99d8eSRyder Lee 124d8d99d8eSRyder Lee return ret; 125d8d99d8eSRyder Lee } 126d8d99d8eSRyder Lee 127cf870273SRyder Lee void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, 128cf870273SRyder Lee struct mt2701_i2s_path *i2s_path, 129cf870273SRyder Lee int dir) 130d8d99d8eSRyder Lee { 131d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->hop_ck[dir]); 132d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->asrco_ck); 133d8d99d8eSRyder Lee } 134d8d99d8eSRyder Lee 135d8d99d8eSRyder Lee int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id) 136d8d99d8eSRyder Lee { 137d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 138d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 139d8d99d8eSRyder Lee 140d8d99d8eSRyder Lee return clk_prepare_enable(i2s_path->mclk_ck); 141d8d99d8eSRyder Lee } 142d8d99d8eSRyder Lee 143d8d99d8eSRyder Lee void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id) 144d8d99d8eSRyder Lee { 145d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 146d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 147d8d99d8eSRyder Lee 148d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->mclk_ck); 149d8d99d8eSRyder Lee } 150d8d99d8eSRyder Lee 151d8d99d8eSRyder Lee int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe) 152d8d99d8eSRyder Lee { 153d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 154d8d99d8eSRyder Lee 155d8d99d8eSRyder Lee return clk_prepare_enable(afe_priv->mrgif_ck); 156d8d99d8eSRyder Lee } 157d8d99d8eSRyder Lee 158d8d99d8eSRyder Lee void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe) 159d8d99d8eSRyder Lee { 160d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 161d8d99d8eSRyder Lee 162d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->mrgif_ck); 163d8d99d8eSRyder Lee } 164d8d99d8eSRyder Lee 165d8d99d8eSRyder Lee static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe) 166d8d99d8eSRyder Lee { 167d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 168d8d99d8eSRyder Lee int ret; 169d8d99d8eSRyder Lee 17096365d9fSRyder Lee /* Enable infra clock gate */ 17196365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); 172d8d99d8eSRyder Lee if (ret) 173d8d99d8eSRyder Lee return ret; 174d8d99d8eSRyder Lee 17596365d9fSRyder Lee /* Enable top a1sys clock gate */ 17696365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 17796365d9fSRyder Lee if (ret) 17896365d9fSRyder Lee goto err_a1sys; 17996365d9fSRyder Lee 18096365d9fSRyder Lee /* Enable top a2sys clock gate */ 18196365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 18296365d9fSRyder Lee if (ret) 18396365d9fSRyder Lee goto err_a2sys; 18496365d9fSRyder Lee 18596365d9fSRyder Lee /* Internal clock gates */ 18696365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 18796365d9fSRyder Lee if (ret) 18896365d9fSRyder Lee goto err_afe; 18996365d9fSRyder Lee 190d8d99d8eSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 191d8d99d8eSRyder Lee if (ret) 192d8d99d8eSRyder Lee goto err_audio_a1sys; 193d8d99d8eSRyder Lee 194d8d99d8eSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 195d8d99d8eSRyder Lee if (ret) 196d8d99d8eSRyder Lee goto err_audio_a2sys; 197d8d99d8eSRyder Lee 198d8d99d8eSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]); 199d8d99d8eSRyder Lee if (ret) 200d8d99d8eSRyder Lee goto err_afe_conn; 201d8d99d8eSRyder Lee 202d8d99d8eSRyder Lee return 0; 203d8d99d8eSRyder Lee 204d8d99d8eSRyder Lee err_afe_conn: 205d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 206d8d99d8eSRyder Lee err_audio_a2sys: 207d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 208d8d99d8eSRyder Lee err_audio_a1sys: 209d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 21096365d9fSRyder Lee err_afe: 21196365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 21296365d9fSRyder Lee err_a2sys: 21396365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 21496365d9fSRyder Lee err_a1sys: 21596365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); 216d8d99d8eSRyder Lee 217d8d99d8eSRyder Lee return ret; 218d8d99d8eSRyder Lee } 219d8d99d8eSRyder Lee 220d8d99d8eSRyder Lee static void mt2701_afe_disable_audsys(struct mtk_base_afe *afe) 221d8d99d8eSRyder Lee { 222d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 223d8d99d8eSRyder Lee 224d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]); 225d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 226d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 227d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 22896365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 22996365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 23096365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); 231d8d99d8eSRyder Lee } 232d8d99d8eSRyder Lee 233d6f3710aSGarlic Tseng int mt2701_afe_enable_clock(struct mtk_base_afe *afe) 234d6f3710aSGarlic Tseng { 235d8d99d8eSRyder Lee int ret; 236d6f3710aSGarlic Tseng 237d8d99d8eSRyder Lee /* Enable audio system */ 238d8d99d8eSRyder Lee ret = mt2701_afe_enable_audsys(afe); 239d6f3710aSGarlic Tseng if (ret) { 240d8d99d8eSRyder Lee dev_err(afe->dev, "failed to enable audio system %d\n", ret); 241d6f3710aSGarlic Tseng return ret; 242d6f3710aSGarlic Tseng } 243d6f3710aSGarlic Tseng 244d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, ASYS_TOP_CON, 245600b2fd4SRyder Lee ASYS_TOP_CON_ASYS_TIMING_ON, 246600b2fd4SRyder Lee ASYS_TOP_CON_ASYS_TIMING_ON); 247d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON0, 248d6f3710aSGarlic Tseng AFE_DAC_CON0_AFE_ON, 249d6f3710aSGarlic Tseng AFE_DAC_CON0_AFE_ON); 250d8d99d8eSRyder Lee 251d8d99d8eSRyder Lee /* Configure ASRC */ 252d8d99d8eSRyder Lee regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL); 253d8d99d8eSRyder Lee regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL); 254d6f3710aSGarlic Tseng 255d6f3710aSGarlic Tseng return 0; 256d6f3710aSGarlic Tseng } 257d6f3710aSGarlic Tseng 258d8d99d8eSRyder Lee int mt2701_afe_disable_clock(struct mtk_base_afe *afe) 259d6f3710aSGarlic Tseng { 260d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, ASYS_TOP_CON, 261600b2fd4SRyder Lee ASYS_TOP_CON_ASYS_TIMING_ON, 0); 262d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON0, 263d6f3710aSGarlic Tseng AFE_DAC_CON0_AFE_ON, 0); 264d6f3710aSGarlic Tseng 265d8d99d8eSRyder Lee mt2701_afe_disable_audsys(afe); 266d6f3710aSGarlic Tseng 267d6f3710aSGarlic Tseng return 0; 268d6f3710aSGarlic Tseng } 269d6f3710aSGarlic Tseng 270cf870273SRyder Lee int mt2701_mclk_configuration(struct mtk_base_afe *afe, int id) 271cf870273SRyder Lee 272d6f3710aSGarlic Tseng { 273d8d99d8eSRyder Lee struct mt2701_afe_private *priv = afe->platform_priv; 274d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id]; 275cf870273SRyder Lee int ret = -EINVAL; 276d6f3710aSGarlic Tseng 277d8d99d8eSRyder Lee /* Set mclk source */ 278cf870273SRyder Lee if (!(MT2701_PLL_DOMAIN_0_RATE % i2s_path->mclk_rate)) 279d8d99d8eSRyder Lee ret = clk_set_parent(i2s_path->sel_ck, 280d8d99d8eSRyder Lee priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]); 281cf870273SRyder Lee else if (!(MT2701_PLL_DOMAIN_1_RATE % i2s_path->mclk_rate)) 282d8d99d8eSRyder Lee ret = clk_set_parent(i2s_path->sel_ck, 283d8d99d8eSRyder Lee priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]); 284d6f3710aSGarlic Tseng 285cf870273SRyder Lee if (ret) { 286cf870273SRyder Lee dev_err(afe->dev, "failed to set mclk source\n"); 287cf870273SRyder Lee return ret; 288cf870273SRyder Lee } 289d6f3710aSGarlic Tseng 290d8d99d8eSRyder Lee /* Set mclk divider */ 291cf870273SRyder Lee ret = clk_set_rate(i2s_path->div_ck, i2s_path->mclk_rate); 292cf870273SRyder Lee if (ret) { 293d8d99d8eSRyder Lee dev_err(afe->dev, "failed to set mclk divider %d\n", ret); 294cf870273SRyder Lee return ret; 295cf870273SRyder Lee } 296cf870273SRyder Lee 297cf870273SRyder Lee return 0; 298d6f3710aSGarlic Tseng } 299