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> 6d6f3710aSGarlic Tseng * 7d6f3710aSGarlic Tseng * This program is free software; you can redistribute it and/or modify 8d6f3710aSGarlic Tseng * it under the terms of the GNU General Public License version 2 and 9d6f3710aSGarlic Tseng * only version 2 as published by the Free Software Foundation. 10d6f3710aSGarlic Tseng * 11d6f3710aSGarlic Tseng * This program is distributed in the hope that it will be useful, 12d6f3710aSGarlic Tseng * but WITHOUT ANY WARRANTY; without even the implied warranty of 13d6f3710aSGarlic Tseng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14d6f3710aSGarlic Tseng * GNU General Public License for more details. 15d6f3710aSGarlic Tseng */ 16d6f3710aSGarlic Tseng 17d6f3710aSGarlic Tseng #include "mt2701-afe-common.h" 18d6f3710aSGarlic Tseng #include "mt2701-afe-clock-ctrl.h" 19d6f3710aSGarlic Tseng 20d8d99d8eSRyder Lee static const char *const base_clks[] = { 21*96365d9fSRyder Lee [MT2701_INFRA_SYS_AUDIO] = "infra_sys_audio_clk", 22d8d99d8eSRyder Lee [MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel", 23d8d99d8eSRyder Lee [MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel", 24*96365d9fSRyder Lee [MT2701_TOP_AUD_A1SYS] = "top_audio_a1sys_hp", 25*96365d9fSRyder Lee [MT2701_TOP_AUD_A2SYS] = "top_audio_a2sys_hp", 26d8d99d8eSRyder Lee [MT2701_AUDSYS_AFE] = "audio_afe_pd", 27d8d99d8eSRyder Lee [MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd", 28d8d99d8eSRyder Lee [MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd", 29d8d99d8eSRyder Lee [MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd", 30d6f3710aSGarlic Tseng }; 31d6f3710aSGarlic Tseng 32d6f3710aSGarlic Tseng int mt2701_init_clock(struct mtk_base_afe *afe) 33d6f3710aSGarlic Tseng { 34d6f3710aSGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 35d8d99d8eSRyder Lee int i; 36d6f3710aSGarlic Tseng 37d8d99d8eSRyder Lee for (i = 0; i < MT2701_BASE_CLK_NUM; i++) { 38d8d99d8eSRyder Lee afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]); 39d8d99d8eSRyder Lee if (IS_ERR(afe_priv->base_ck[i])) { 40d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", base_clks[i]); 41d8d99d8eSRyder Lee return PTR_ERR(afe_priv->base_ck[i]); 42d6f3710aSGarlic Tseng } 43d6f3710aSGarlic Tseng } 44d6f3710aSGarlic Tseng 45d8d99d8eSRyder Lee /* Get I2S related clocks */ 46d8d99d8eSRyder Lee for (i = 0; i < MT2701_I2S_NUM; i++) { 47d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i]; 48d8d99d8eSRyder Lee char name[13]; 49d8d99d8eSRyder Lee 50d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_src_sel", i); 51d8d99d8eSRyder Lee i2s_path->sel_ck = devm_clk_get(afe->dev, name); 52d8d99d8eSRyder Lee if (IS_ERR(i2s_path->sel_ck)) { 53d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 54d8d99d8eSRyder Lee return PTR_ERR(i2s_path->sel_ck); 55d8d99d8eSRyder Lee } 56d8d99d8eSRyder Lee 57d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_src_div", i); 58d8d99d8eSRyder Lee i2s_path->div_ck = devm_clk_get(afe->dev, name); 59d8d99d8eSRyder Lee if (IS_ERR(i2s_path->div_ck)) { 60d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 61d8d99d8eSRyder Lee return PTR_ERR(i2s_path->div_ck); 62d8d99d8eSRyder Lee } 63d8d99d8eSRyder Lee 64d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_mclk_en", i); 65d8d99d8eSRyder Lee i2s_path->mclk_ck = devm_clk_get(afe->dev, name); 66d8d99d8eSRyder Lee if (IS_ERR(i2s_path->mclk_ck)) { 67d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 68d8d99d8eSRyder Lee return PTR_ERR(i2s_path->mclk_ck); 69d8d99d8eSRyder Lee } 70d8d99d8eSRyder Lee 71d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2so%d_hop_ck", i); 72d8d99d8eSRyder Lee i2s_path->hop_ck[I2S_OUT] = devm_clk_get(afe->dev, name); 73d8d99d8eSRyder Lee if (IS_ERR(i2s_path->hop_ck[I2S_OUT])) { 74d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 75d8d99d8eSRyder Lee return PTR_ERR(i2s_path->hop_ck[I2S_OUT]); 76d8d99d8eSRyder Lee } 77d8d99d8eSRyder Lee 78d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2si%d_hop_ck", i); 79d8d99d8eSRyder Lee i2s_path->hop_ck[I2S_IN] = devm_clk_get(afe->dev, name); 80d8d99d8eSRyder Lee if (IS_ERR(i2s_path->hop_ck[I2S_IN])) { 81d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 82d8d99d8eSRyder Lee return PTR_ERR(i2s_path->hop_ck[I2S_IN]); 83d8d99d8eSRyder Lee } 84d8d99d8eSRyder Lee 85d8d99d8eSRyder Lee snprintf(name, sizeof(name), "asrc%d_out_ck", i); 86d8d99d8eSRyder Lee i2s_path->asrco_ck = devm_clk_get(afe->dev, name); 87d8d99d8eSRyder Lee if (IS_ERR(i2s_path->asrco_ck)) { 88d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 89d8d99d8eSRyder Lee return PTR_ERR(i2s_path->asrco_ck); 90d8d99d8eSRyder Lee } 91d8d99d8eSRyder Lee } 92d8d99d8eSRyder Lee 93d8d99d8eSRyder Lee /* Some platforms may support BT path */ 94d8d99d8eSRyder Lee afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd"); 95d8d99d8eSRyder Lee if (IS_ERR(afe_priv->mrgif_ck)) { 96d8d99d8eSRyder Lee if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER) 97d8d99d8eSRyder Lee return -EPROBE_DEFER; 98d8d99d8eSRyder Lee 99d8d99d8eSRyder Lee afe_priv->mrgif_ck = NULL; 100d8d99d8eSRyder Lee } 101d8d99d8eSRyder Lee 102d6f3710aSGarlic Tseng return 0; 103d6f3710aSGarlic Tseng } 104d6f3710aSGarlic Tseng 105d8d99d8eSRyder Lee int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, int id, int dir) 106d8d99d8eSRyder Lee { 107d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 108d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 109d8d99d8eSRyder Lee int ret; 110d8d99d8eSRyder Lee 111d8d99d8eSRyder Lee ret = clk_prepare_enable(i2s_path->asrco_ck); 112d8d99d8eSRyder Lee if (ret) { 113d8d99d8eSRyder Lee dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret); 114d8d99d8eSRyder Lee return ret; 115d8d99d8eSRyder Lee } 116d8d99d8eSRyder Lee 117d8d99d8eSRyder Lee ret = clk_prepare_enable(i2s_path->hop_ck[dir]); 118d8d99d8eSRyder Lee if (ret) { 119d8d99d8eSRyder Lee dev_err(afe->dev, "failed to enable I2S clock %d\n", ret); 120d8d99d8eSRyder Lee goto err_hop_ck; 121d8d99d8eSRyder Lee } 122d8d99d8eSRyder Lee 123d8d99d8eSRyder Lee return 0; 124d8d99d8eSRyder Lee 125d8d99d8eSRyder Lee err_hop_ck: 126d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->asrco_ck); 127d8d99d8eSRyder Lee 128d8d99d8eSRyder Lee return ret; 129d8d99d8eSRyder Lee } 130d8d99d8eSRyder Lee 131d8d99d8eSRyder Lee void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, int id, int dir) 132d8d99d8eSRyder Lee { 133d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 134d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 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 175*96365d9fSRyder Lee /* Enable infra clock gate */ 176*96365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); 177d8d99d8eSRyder Lee if (ret) 178d8d99d8eSRyder Lee return ret; 179d8d99d8eSRyder Lee 180*96365d9fSRyder Lee /* Enable top a1sys clock gate */ 181*96365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 182*96365d9fSRyder Lee if (ret) 183*96365d9fSRyder Lee goto err_a1sys; 184*96365d9fSRyder Lee 185*96365d9fSRyder Lee /* Enable top a2sys clock gate */ 186*96365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 187*96365d9fSRyder Lee if (ret) 188*96365d9fSRyder Lee goto err_a2sys; 189*96365d9fSRyder Lee 190*96365d9fSRyder Lee /* Internal clock gates */ 191*96365d9fSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 192*96365d9fSRyder Lee if (ret) 193*96365d9fSRyder Lee goto err_afe; 194*96365d9fSRyder 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]); 215*96365d9fSRyder Lee err_afe: 216*96365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 217*96365d9fSRyder Lee err_a2sys: 218*96365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 219*96365d9fSRyder Lee err_a1sys: 220*96365d9fSRyder 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]); 233*96365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 234*96365d9fSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 235*96365d9fSRyder 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 275d6f3710aSGarlic Tseng void mt2701_mclk_configuration(struct mtk_base_afe *afe, int id, int domain, 276d6f3710aSGarlic Tseng int mclk) 277d6f3710aSGarlic Tseng { 278d8d99d8eSRyder Lee struct mt2701_afe_private *priv = afe->platform_priv; 279d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id]; 280d6f3710aSGarlic Tseng int ret; 281d6f3710aSGarlic Tseng 282d8d99d8eSRyder Lee /* Set mclk source */ 283d8d99d8eSRyder Lee if (domain == 0) 284d8d99d8eSRyder Lee ret = clk_set_parent(i2s_path->sel_ck, 285d8d99d8eSRyder Lee priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]); 286d8d99d8eSRyder Lee else 287d8d99d8eSRyder Lee ret = clk_set_parent(i2s_path->sel_ck, 288d8d99d8eSRyder Lee priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]); 289d6f3710aSGarlic Tseng 290d6f3710aSGarlic Tseng if (ret) 291d8d99d8eSRyder Lee dev_err(afe->dev, "failed to set domain%d mclk source %d\n", 292d8d99d8eSRyder Lee domain, ret); 293d6f3710aSGarlic Tseng 294d8d99d8eSRyder Lee /* Set mclk divider */ 295d8d99d8eSRyder Lee ret = clk_set_rate(i2s_path->div_ck, mclk); 296d6f3710aSGarlic Tseng if (ret) 297d8d99d8eSRyder Lee dev_err(afe->dev, "failed to set mclk divider %d\n", ret); 298d6f3710aSGarlic Tseng } 299