1d6f3710aSGarlic Tseng /* 2d6f3710aSGarlic Tseng * mt2701-afe-clock-ctrl.c -- Mediatek 2701 afe clock ctrl 3d6f3710aSGarlic Tseng * 4d6f3710aSGarlic Tseng * Copyright (c) 2016 MediaTek Inc. 5d6f3710aSGarlic Tseng * Author: Garlic Tseng <garlic.tseng@mediatek.com> 6*cf870273SRyder Lee * Ryder Lee <ryder.lee@mediatek.com> 7d6f3710aSGarlic Tseng * 8d6f3710aSGarlic Tseng * This program is free software; you can redistribute it and/or modify 9d6f3710aSGarlic Tseng * it under the terms of the GNU General Public License version 2 and 10d6f3710aSGarlic Tseng * only version 2 as published by the Free Software Foundation. 11d6f3710aSGarlic Tseng * 12d6f3710aSGarlic Tseng * This program is distributed in the hope that it will be useful, 13d6f3710aSGarlic Tseng * but WITHOUT ANY WARRANTY; without even the implied warranty of 14d6f3710aSGarlic Tseng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15d6f3710aSGarlic Tseng * GNU General Public License for more details. 16d6f3710aSGarlic Tseng */ 17d6f3710aSGarlic Tseng 18d6f3710aSGarlic Tseng #include "mt2701-afe-common.h" 19d6f3710aSGarlic Tseng #include "mt2701-afe-clock-ctrl.h" 20d6f3710aSGarlic Tseng 21d8d99d8eSRyder Lee static const char *const base_clks[] = { 2296365d9fSRyder Lee [MT2701_INFRA_SYS_AUDIO] = "infra_sys_audio_clk", 23d8d99d8eSRyder Lee [MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel", 24d8d99d8eSRyder Lee [MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel", 2596365d9fSRyder Lee [MT2701_TOP_AUD_A1SYS] = "top_audio_a1sys_hp", 2696365d9fSRyder Lee [MT2701_TOP_AUD_A2SYS] = "top_audio_a2sys_hp", 27d8d99d8eSRyder Lee [MT2701_AUDSYS_AFE] = "audio_afe_pd", 28d8d99d8eSRyder Lee [MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd", 29d8d99d8eSRyder Lee [MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd", 30d8d99d8eSRyder Lee [MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd", 31d6f3710aSGarlic Tseng }; 32d6f3710aSGarlic Tseng 33d6f3710aSGarlic Tseng int mt2701_init_clock(struct mtk_base_afe *afe) 34d6f3710aSGarlic Tseng { 35d6f3710aSGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 36d8d99d8eSRyder Lee int i; 37d6f3710aSGarlic Tseng 38d8d99d8eSRyder Lee for (i = 0; i < MT2701_BASE_CLK_NUM; i++) { 39d8d99d8eSRyder Lee afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]); 40d8d99d8eSRyder Lee if (IS_ERR(afe_priv->base_ck[i])) { 41d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", base_clks[i]); 42d8d99d8eSRyder Lee return PTR_ERR(afe_priv->base_ck[i]); 43d6f3710aSGarlic Tseng } 44d6f3710aSGarlic Tseng } 45d6f3710aSGarlic Tseng 46d8d99d8eSRyder Lee /* Get I2S related clocks */ 47d8d99d8eSRyder Lee for (i = 0; i < MT2701_I2S_NUM; i++) { 48d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i]; 49d8d99d8eSRyder Lee char name[13]; 50d8d99d8eSRyder Lee 51d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_src_sel", i); 52d8d99d8eSRyder Lee i2s_path->sel_ck = devm_clk_get(afe->dev, name); 53d8d99d8eSRyder Lee if (IS_ERR(i2s_path->sel_ck)) { 54d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 55d8d99d8eSRyder Lee return PTR_ERR(i2s_path->sel_ck); 56d8d99d8eSRyder Lee } 57d8d99d8eSRyder Lee 58d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_src_div", i); 59d8d99d8eSRyder Lee i2s_path->div_ck = devm_clk_get(afe->dev, name); 60d8d99d8eSRyder Lee if (IS_ERR(i2s_path->div_ck)) { 61d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 62d8d99d8eSRyder Lee return PTR_ERR(i2s_path->div_ck); 63d8d99d8eSRyder Lee } 64d8d99d8eSRyder Lee 65d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_mclk_en", i); 66d8d99d8eSRyder Lee i2s_path->mclk_ck = devm_clk_get(afe->dev, name); 67d8d99d8eSRyder Lee if (IS_ERR(i2s_path->mclk_ck)) { 68d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 69d8d99d8eSRyder Lee return PTR_ERR(i2s_path->mclk_ck); 70d8d99d8eSRyder Lee } 71d8d99d8eSRyder Lee 72d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2so%d_hop_ck", i); 73d8d99d8eSRyder Lee i2s_path->hop_ck[I2S_OUT] = devm_clk_get(afe->dev, name); 74d8d99d8eSRyder Lee if (IS_ERR(i2s_path->hop_ck[I2S_OUT])) { 75d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 76d8d99d8eSRyder Lee return PTR_ERR(i2s_path->hop_ck[I2S_OUT]); 77d8d99d8eSRyder Lee } 78d8d99d8eSRyder Lee 79d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2si%d_hop_ck", i); 80d8d99d8eSRyder Lee i2s_path->hop_ck[I2S_IN] = devm_clk_get(afe->dev, name); 81d8d99d8eSRyder Lee if (IS_ERR(i2s_path->hop_ck[I2S_IN])) { 82d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 83d8d99d8eSRyder Lee return PTR_ERR(i2s_path->hop_ck[I2S_IN]); 84d8d99d8eSRyder Lee } 85d8d99d8eSRyder Lee 86d8d99d8eSRyder Lee snprintf(name, sizeof(name), "asrc%d_out_ck", i); 87d8d99d8eSRyder Lee i2s_path->asrco_ck = devm_clk_get(afe->dev, name); 88d8d99d8eSRyder Lee if (IS_ERR(i2s_path->asrco_ck)) { 89d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 90d8d99d8eSRyder Lee return PTR_ERR(i2s_path->asrco_ck); 91d8d99d8eSRyder Lee } 92d8d99d8eSRyder Lee } 93d8d99d8eSRyder Lee 94d8d99d8eSRyder Lee /* Some platforms may support BT path */ 95d8d99d8eSRyder Lee afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd"); 96d8d99d8eSRyder Lee if (IS_ERR(afe_priv->mrgif_ck)) { 97d8d99d8eSRyder Lee if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER) 98d8d99d8eSRyder Lee return -EPROBE_DEFER; 99d8d99d8eSRyder Lee 100d8d99d8eSRyder Lee afe_priv->mrgif_ck = NULL; 101d8d99d8eSRyder Lee } 102d8d99d8eSRyder Lee 103d6f3710aSGarlic Tseng return 0; 104d6f3710aSGarlic Tseng } 105d6f3710aSGarlic Tseng 106*cf870273SRyder Lee int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, 107*cf870273SRyder Lee struct mt2701_i2s_path *i2s_path, 108*cf870273SRyder Lee int dir) 109d8d99d8eSRyder Lee { 110d8d99d8eSRyder Lee int ret; 111d8d99d8eSRyder Lee 112d8d99d8eSRyder Lee ret = clk_prepare_enable(i2s_path->asrco_ck); 113d8d99d8eSRyder Lee if (ret) { 114d8d99d8eSRyder Lee dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret); 115d8d99d8eSRyder Lee return ret; 116d8d99d8eSRyder Lee } 117d8d99d8eSRyder Lee 118d8d99d8eSRyder Lee ret = clk_prepare_enable(i2s_path->hop_ck[dir]); 119d8d99d8eSRyder Lee if (ret) { 120d8d99d8eSRyder Lee dev_err(afe->dev, "failed to enable I2S clock %d\n", ret); 121d8d99d8eSRyder Lee goto err_hop_ck; 122d8d99d8eSRyder Lee } 123d8d99d8eSRyder Lee 124d8d99d8eSRyder Lee return 0; 125d8d99d8eSRyder Lee 126d8d99d8eSRyder Lee err_hop_ck: 127d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->asrco_ck); 128d8d99d8eSRyder Lee 129d8d99d8eSRyder Lee return ret; 130d8d99d8eSRyder Lee } 131d8d99d8eSRyder Lee 132*cf870273SRyder Lee void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, 133*cf870273SRyder Lee struct mt2701_i2s_path *i2s_path, 134*cf870273SRyder Lee int dir) 135d8d99d8eSRyder Lee { 136d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->hop_ck[dir]); 137d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->asrco_ck); 138d8d99d8eSRyder Lee } 139d8d99d8eSRyder Lee 140d8d99d8eSRyder Lee int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id) 141d8d99d8eSRyder Lee { 142d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 143d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 144d8d99d8eSRyder Lee 145d8d99d8eSRyder Lee return clk_prepare_enable(i2s_path->mclk_ck); 146d8d99d8eSRyder Lee } 147d8d99d8eSRyder Lee 148d8d99d8eSRyder Lee void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id) 149d8d99d8eSRyder Lee { 150d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 151d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 152d8d99d8eSRyder Lee 153d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->mclk_ck); 154d8d99d8eSRyder Lee } 155d8d99d8eSRyder Lee 156d8d99d8eSRyder Lee int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe) 157d8d99d8eSRyder Lee { 158d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 159d8d99d8eSRyder Lee 160d8d99d8eSRyder Lee return clk_prepare_enable(afe_priv->mrgif_ck); 161d8d99d8eSRyder Lee } 162d8d99d8eSRyder Lee 163d8d99d8eSRyder Lee void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe) 164d8d99d8eSRyder Lee { 165d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 166d8d99d8eSRyder Lee 167d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->mrgif_ck); 168d8d99d8eSRyder Lee } 169d8d99d8eSRyder Lee 170d8d99d8eSRyder Lee static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe) 171d8d99d8eSRyder Lee { 172d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 173d8d99d8eSRyder Lee int ret; 174d8d99d8eSRyder Lee 17596365d9fSRyder Lee /* Enable infra clock gate */ 17696365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); 177d8d99d8eSRyder Lee if (ret) 178d8d99d8eSRyder Lee return ret; 179d8d99d8eSRyder Lee 18096365d9fSRyder Lee /* Enable top a1sys clock gate */ 18196365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 18296365d9fSRyder Lee if (ret) 18396365d9fSRyder Lee goto err_a1sys; 18496365d9fSRyder Lee 18596365d9fSRyder Lee /* Enable top a2sys clock gate */ 18696365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 18796365d9fSRyder Lee if (ret) 18896365d9fSRyder Lee goto err_a2sys; 18996365d9fSRyder Lee 19096365d9fSRyder Lee /* Internal clock gates */ 19196365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 19296365d9fSRyder Lee if (ret) 19396365d9fSRyder Lee goto err_afe; 19496365d9fSRyder Lee 195d8d99d8eSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 196d8d99d8eSRyder Lee if (ret) 197d8d99d8eSRyder Lee goto err_audio_a1sys; 198d8d99d8eSRyder Lee 199d8d99d8eSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 200d8d99d8eSRyder Lee if (ret) 201d8d99d8eSRyder Lee goto err_audio_a2sys; 202d8d99d8eSRyder Lee 203d8d99d8eSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]); 204d8d99d8eSRyder Lee if (ret) 205d8d99d8eSRyder Lee goto err_afe_conn; 206d8d99d8eSRyder Lee 207d8d99d8eSRyder Lee return 0; 208d8d99d8eSRyder Lee 209d8d99d8eSRyder Lee err_afe_conn: 210d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 211d8d99d8eSRyder Lee err_audio_a2sys: 212d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 213d8d99d8eSRyder Lee err_audio_a1sys: 214d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 21596365d9fSRyder Lee err_afe: 21696365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 21796365d9fSRyder Lee err_a2sys: 21896365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 21996365d9fSRyder Lee err_a1sys: 22096365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); 221d8d99d8eSRyder Lee 222d8d99d8eSRyder Lee return ret; 223d8d99d8eSRyder Lee } 224d8d99d8eSRyder Lee 225d8d99d8eSRyder Lee static void mt2701_afe_disable_audsys(struct mtk_base_afe *afe) 226d8d99d8eSRyder Lee { 227d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 228d8d99d8eSRyder Lee 229d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]); 230d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 231d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 232d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 23396365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 23496365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 23596365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); 236d8d99d8eSRyder Lee } 237d8d99d8eSRyder Lee 238d6f3710aSGarlic Tseng int mt2701_afe_enable_clock(struct mtk_base_afe *afe) 239d6f3710aSGarlic Tseng { 240d8d99d8eSRyder Lee int ret; 241d6f3710aSGarlic Tseng 242d8d99d8eSRyder Lee /* Enable audio system */ 243d8d99d8eSRyder Lee ret = mt2701_afe_enable_audsys(afe); 244d6f3710aSGarlic Tseng if (ret) { 245d8d99d8eSRyder Lee dev_err(afe->dev, "failed to enable audio system %d\n", ret); 246d6f3710aSGarlic Tseng return ret; 247d6f3710aSGarlic Tseng } 248d6f3710aSGarlic Tseng 249d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, ASYS_TOP_CON, 250600b2fd4SRyder Lee ASYS_TOP_CON_ASYS_TIMING_ON, 251600b2fd4SRyder Lee ASYS_TOP_CON_ASYS_TIMING_ON); 252d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON0, 253d6f3710aSGarlic Tseng AFE_DAC_CON0_AFE_ON, 254d6f3710aSGarlic Tseng AFE_DAC_CON0_AFE_ON); 255d8d99d8eSRyder Lee 256d8d99d8eSRyder Lee /* Configure ASRC */ 257d8d99d8eSRyder Lee regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL); 258d8d99d8eSRyder Lee regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL); 259d6f3710aSGarlic Tseng 260d6f3710aSGarlic Tseng return 0; 261d6f3710aSGarlic Tseng } 262d6f3710aSGarlic Tseng 263d8d99d8eSRyder Lee int mt2701_afe_disable_clock(struct mtk_base_afe *afe) 264d6f3710aSGarlic Tseng { 265d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, ASYS_TOP_CON, 266600b2fd4SRyder Lee ASYS_TOP_CON_ASYS_TIMING_ON, 0); 267d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON0, 268d6f3710aSGarlic Tseng AFE_DAC_CON0_AFE_ON, 0); 269d6f3710aSGarlic Tseng 270d8d99d8eSRyder Lee mt2701_afe_disable_audsys(afe); 271d6f3710aSGarlic Tseng 272d6f3710aSGarlic Tseng return 0; 273d6f3710aSGarlic Tseng } 274d6f3710aSGarlic Tseng 275*cf870273SRyder Lee int mt2701_mclk_configuration(struct mtk_base_afe *afe, int id) 276*cf870273SRyder Lee 277d6f3710aSGarlic Tseng { 278d8d99d8eSRyder Lee struct mt2701_afe_private *priv = afe->platform_priv; 279d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id]; 280*cf870273SRyder Lee int ret = -EINVAL; 281d6f3710aSGarlic Tseng 282d8d99d8eSRyder Lee /* Set mclk source */ 283*cf870273SRyder Lee if (!(MT2701_PLL_DOMAIN_0_RATE % i2s_path->mclk_rate)) 284d8d99d8eSRyder Lee ret = clk_set_parent(i2s_path->sel_ck, 285d8d99d8eSRyder Lee priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]); 286*cf870273SRyder Lee else if (!(MT2701_PLL_DOMAIN_1_RATE % i2s_path->mclk_rate)) 287d8d99d8eSRyder Lee ret = clk_set_parent(i2s_path->sel_ck, 288d8d99d8eSRyder Lee priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]); 289d6f3710aSGarlic Tseng 290*cf870273SRyder Lee if (ret) { 291*cf870273SRyder Lee dev_err(afe->dev, "failed to set mclk source\n"); 292*cf870273SRyder Lee return ret; 293*cf870273SRyder Lee } 294d6f3710aSGarlic Tseng 295d8d99d8eSRyder Lee /* Set mclk divider */ 296*cf870273SRyder Lee ret = clk_set_rate(i2s_path->div_ck, i2s_path->mclk_rate); 297*cf870273SRyder Lee if (ret) { 298d8d99d8eSRyder Lee dev_err(afe->dev, "failed to set mclk divider %d\n", ret); 299*cf870273SRyder Lee return ret; 300*cf870273SRyder Lee } 301*cf870273SRyder Lee 302*cf870273SRyder Lee return 0; 303d6f3710aSGarlic Tseng } 304