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 <sound/soc.h> 18d6f3710aSGarlic Tseng #include <linux/regmap.h> 19d6f3710aSGarlic Tseng #include <linux/pm_runtime.h> 20d6f3710aSGarlic Tseng 21d6f3710aSGarlic Tseng #include "mt2701-afe-common.h" 22d6f3710aSGarlic Tseng #include "mt2701-afe-clock-ctrl.h" 23d6f3710aSGarlic Tseng 24*d8d99d8eSRyder Lee static const char *const base_clks[] = { 25*d8d99d8eSRyder Lee [MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel", 26*d8d99d8eSRyder Lee [MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel", 27*d8d99d8eSRyder Lee [MT2701_AUDSYS_AFE] = "audio_afe_pd", 28*d8d99d8eSRyder Lee [MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd", 29*d8d99d8eSRyder Lee [MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd", 30*d8d99d8eSRyder 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; 36*d8d99d8eSRyder Lee int i; 37d6f3710aSGarlic Tseng 38*d8d99d8eSRyder Lee for (i = 0; i < MT2701_BASE_CLK_NUM; i++) { 39*d8d99d8eSRyder Lee afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]); 40*d8d99d8eSRyder Lee if (IS_ERR(afe_priv->base_ck[i])) { 41*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", base_clks[i]); 42*d8d99d8eSRyder Lee return PTR_ERR(afe_priv->base_ck[i]); 43d6f3710aSGarlic Tseng } 44d6f3710aSGarlic Tseng } 45d6f3710aSGarlic Tseng 46*d8d99d8eSRyder Lee /* Get I2S related clocks */ 47*d8d99d8eSRyder Lee for (i = 0; i < MT2701_I2S_NUM; i++) { 48*d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i]; 49*d8d99d8eSRyder Lee char name[13]; 50*d8d99d8eSRyder Lee 51*d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_src_sel", i); 52*d8d99d8eSRyder Lee i2s_path->sel_ck = devm_clk_get(afe->dev, name); 53*d8d99d8eSRyder Lee if (IS_ERR(i2s_path->sel_ck)) { 54*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 55*d8d99d8eSRyder Lee return PTR_ERR(i2s_path->sel_ck); 56*d8d99d8eSRyder Lee } 57*d8d99d8eSRyder Lee 58*d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_src_div", i); 59*d8d99d8eSRyder Lee i2s_path->div_ck = devm_clk_get(afe->dev, name); 60*d8d99d8eSRyder Lee if (IS_ERR(i2s_path->div_ck)) { 61*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 62*d8d99d8eSRyder Lee return PTR_ERR(i2s_path->div_ck); 63*d8d99d8eSRyder Lee } 64*d8d99d8eSRyder Lee 65*d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2s%d_mclk_en", i); 66*d8d99d8eSRyder Lee i2s_path->mclk_ck = devm_clk_get(afe->dev, name); 67*d8d99d8eSRyder Lee if (IS_ERR(i2s_path->mclk_ck)) { 68*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 69*d8d99d8eSRyder Lee return PTR_ERR(i2s_path->mclk_ck); 70*d8d99d8eSRyder Lee } 71*d8d99d8eSRyder Lee 72*d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2so%d_hop_ck", i); 73*d8d99d8eSRyder Lee i2s_path->hop_ck[I2S_OUT] = devm_clk_get(afe->dev, name); 74*d8d99d8eSRyder Lee if (IS_ERR(i2s_path->hop_ck[I2S_OUT])) { 75*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 76*d8d99d8eSRyder Lee return PTR_ERR(i2s_path->hop_ck[I2S_OUT]); 77*d8d99d8eSRyder Lee } 78*d8d99d8eSRyder Lee 79*d8d99d8eSRyder Lee snprintf(name, sizeof(name), "i2si%d_hop_ck", i); 80*d8d99d8eSRyder Lee i2s_path->hop_ck[I2S_IN] = devm_clk_get(afe->dev, name); 81*d8d99d8eSRyder Lee if (IS_ERR(i2s_path->hop_ck[I2S_IN])) { 82*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 83*d8d99d8eSRyder Lee return PTR_ERR(i2s_path->hop_ck[I2S_IN]); 84*d8d99d8eSRyder Lee } 85*d8d99d8eSRyder Lee 86*d8d99d8eSRyder Lee snprintf(name, sizeof(name), "asrc%d_out_ck", i); 87*d8d99d8eSRyder Lee i2s_path->asrco_ck = devm_clk_get(afe->dev, name); 88*d8d99d8eSRyder Lee if (IS_ERR(i2s_path->asrco_ck)) { 89*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to get %s\n", name); 90*d8d99d8eSRyder Lee return PTR_ERR(i2s_path->asrco_ck); 91*d8d99d8eSRyder Lee } 92*d8d99d8eSRyder Lee } 93*d8d99d8eSRyder Lee 94*d8d99d8eSRyder Lee /* Some platforms may support BT path */ 95*d8d99d8eSRyder Lee afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd"); 96*d8d99d8eSRyder Lee if (IS_ERR(afe_priv->mrgif_ck)) { 97*d8d99d8eSRyder Lee if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER) 98*d8d99d8eSRyder Lee return -EPROBE_DEFER; 99*d8d99d8eSRyder Lee 100*d8d99d8eSRyder Lee afe_priv->mrgif_ck = NULL; 101*d8d99d8eSRyder Lee } 102*d8d99d8eSRyder Lee 103d6f3710aSGarlic Tseng return 0; 104d6f3710aSGarlic Tseng } 105d6f3710aSGarlic Tseng 106*d8d99d8eSRyder Lee int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, int id, int dir) 107*d8d99d8eSRyder Lee { 108*d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 109*d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 110*d8d99d8eSRyder Lee int ret; 111*d8d99d8eSRyder Lee 112*d8d99d8eSRyder Lee ret = clk_prepare_enable(i2s_path->asrco_ck); 113*d8d99d8eSRyder Lee if (ret) { 114*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret); 115*d8d99d8eSRyder Lee return ret; 116*d8d99d8eSRyder Lee } 117*d8d99d8eSRyder Lee 118*d8d99d8eSRyder Lee ret = clk_prepare_enable(i2s_path->hop_ck[dir]); 119*d8d99d8eSRyder Lee if (ret) { 120*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to enable I2S clock %d\n", ret); 121*d8d99d8eSRyder Lee goto err_hop_ck; 122*d8d99d8eSRyder Lee } 123*d8d99d8eSRyder Lee 124*d8d99d8eSRyder Lee return 0; 125*d8d99d8eSRyder Lee 126*d8d99d8eSRyder Lee err_hop_ck: 127*d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->asrco_ck); 128*d8d99d8eSRyder Lee 129*d8d99d8eSRyder Lee return ret; 130*d8d99d8eSRyder Lee } 131*d8d99d8eSRyder Lee 132*d8d99d8eSRyder Lee void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, int id, int dir) 133*d8d99d8eSRyder Lee { 134*d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 135*d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 136*d8d99d8eSRyder Lee 137*d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->hop_ck[dir]); 138*d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->asrco_ck); 139*d8d99d8eSRyder Lee } 140*d8d99d8eSRyder Lee 141*d8d99d8eSRyder Lee int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id) 142*d8d99d8eSRyder Lee { 143*d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 144*d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 145*d8d99d8eSRyder Lee 146*d8d99d8eSRyder Lee return clk_prepare_enable(i2s_path->mclk_ck); 147*d8d99d8eSRyder Lee } 148*d8d99d8eSRyder Lee 149*d8d99d8eSRyder Lee void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id) 150*d8d99d8eSRyder Lee { 151*d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 152*d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 153*d8d99d8eSRyder Lee 154*d8d99d8eSRyder Lee clk_disable_unprepare(i2s_path->mclk_ck); 155*d8d99d8eSRyder Lee } 156*d8d99d8eSRyder Lee 157*d8d99d8eSRyder Lee int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe) 158*d8d99d8eSRyder Lee { 159*d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 160*d8d99d8eSRyder Lee 161*d8d99d8eSRyder Lee return clk_prepare_enable(afe_priv->mrgif_ck); 162*d8d99d8eSRyder Lee } 163*d8d99d8eSRyder Lee 164*d8d99d8eSRyder Lee void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe) 165*d8d99d8eSRyder Lee { 166*d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 167*d8d99d8eSRyder Lee 168*d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->mrgif_ck); 169*d8d99d8eSRyder Lee } 170*d8d99d8eSRyder Lee 171*d8d99d8eSRyder Lee static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe) 172*d8d99d8eSRyder Lee { 173*d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 174*d8d99d8eSRyder Lee int ret; 175*d8d99d8eSRyder Lee 176*d8d99d8eSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 177*d8d99d8eSRyder Lee if (ret) 178*d8d99d8eSRyder Lee return ret; 179*d8d99d8eSRyder Lee 180*d8d99d8eSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 181*d8d99d8eSRyder Lee if (ret) 182*d8d99d8eSRyder Lee goto err_audio_a1sys; 183*d8d99d8eSRyder Lee 184*d8d99d8eSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 185*d8d99d8eSRyder Lee if (ret) 186*d8d99d8eSRyder Lee goto err_audio_a2sys; 187*d8d99d8eSRyder Lee 188*d8d99d8eSRyder Lee ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]); 189*d8d99d8eSRyder Lee if (ret) 190*d8d99d8eSRyder Lee goto err_afe_conn; 191*d8d99d8eSRyder Lee 192*d8d99d8eSRyder Lee return 0; 193*d8d99d8eSRyder Lee 194*d8d99d8eSRyder Lee err_afe_conn: 195*d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 196*d8d99d8eSRyder Lee err_audio_a2sys: 197*d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 198*d8d99d8eSRyder Lee err_audio_a1sys: 199*d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 200*d8d99d8eSRyder Lee 201*d8d99d8eSRyder Lee return ret; 202*d8d99d8eSRyder Lee } 203*d8d99d8eSRyder Lee 204*d8d99d8eSRyder Lee static void mt2701_afe_disable_audsys(struct mtk_base_afe *afe) 205*d8d99d8eSRyder Lee { 206*d8d99d8eSRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 207*d8d99d8eSRyder Lee 208*d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]); 209*d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 210*d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 211*d8d99d8eSRyder Lee clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 212*d8d99d8eSRyder Lee } 213*d8d99d8eSRyder Lee 214d6f3710aSGarlic Tseng int mt2701_afe_enable_clock(struct mtk_base_afe *afe) 215d6f3710aSGarlic Tseng { 216*d8d99d8eSRyder Lee int ret; 217d6f3710aSGarlic Tseng 218*d8d99d8eSRyder Lee /* Enable audio system */ 219*d8d99d8eSRyder Lee ret = mt2701_afe_enable_audsys(afe); 220d6f3710aSGarlic Tseng if (ret) { 221*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to enable audio system %d\n", ret); 222d6f3710aSGarlic Tseng return ret; 223d6f3710aSGarlic Tseng } 224d6f3710aSGarlic Tseng 225d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, ASYS_TOP_CON, 226d6f3710aSGarlic Tseng AUDIO_TOP_CON0_A1SYS_A2SYS_ON, 227d6f3710aSGarlic Tseng AUDIO_TOP_CON0_A1SYS_A2SYS_ON); 228d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON0, 229d6f3710aSGarlic Tseng AFE_DAC_CON0_AFE_ON, 230d6f3710aSGarlic Tseng AFE_DAC_CON0_AFE_ON); 231*d8d99d8eSRyder Lee 232*d8d99d8eSRyder Lee /* Configure ASRC */ 233*d8d99d8eSRyder Lee regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL); 234*d8d99d8eSRyder Lee regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL); 235d6f3710aSGarlic Tseng 236d6f3710aSGarlic Tseng return 0; 237d6f3710aSGarlic Tseng } 238d6f3710aSGarlic Tseng 239*d8d99d8eSRyder Lee int mt2701_afe_disable_clock(struct mtk_base_afe *afe) 240d6f3710aSGarlic Tseng { 241d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, ASYS_TOP_CON, 242d6f3710aSGarlic Tseng AUDIO_TOP_CON0_A1SYS_A2SYS_ON, 0); 243d6f3710aSGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON0, 244d6f3710aSGarlic Tseng AFE_DAC_CON0_AFE_ON, 0); 245d6f3710aSGarlic Tseng 246*d8d99d8eSRyder Lee mt2701_afe_disable_audsys(afe); 247d6f3710aSGarlic Tseng 248d6f3710aSGarlic Tseng return 0; 249d6f3710aSGarlic Tseng } 250d6f3710aSGarlic Tseng 251d6f3710aSGarlic Tseng void mt2701_mclk_configuration(struct mtk_base_afe *afe, int id, int domain, 252d6f3710aSGarlic Tseng int mclk) 253d6f3710aSGarlic Tseng { 254*d8d99d8eSRyder Lee struct mt2701_afe_private *priv = afe->platform_priv; 255*d8d99d8eSRyder Lee struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id]; 256d6f3710aSGarlic Tseng int ret; 257d6f3710aSGarlic Tseng 258*d8d99d8eSRyder Lee /* Set mclk source */ 259*d8d99d8eSRyder Lee if (domain == 0) 260*d8d99d8eSRyder Lee ret = clk_set_parent(i2s_path->sel_ck, 261*d8d99d8eSRyder Lee priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]); 262*d8d99d8eSRyder Lee else 263*d8d99d8eSRyder Lee ret = clk_set_parent(i2s_path->sel_ck, 264*d8d99d8eSRyder Lee priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]); 265d6f3710aSGarlic Tseng 266d6f3710aSGarlic Tseng if (ret) 267*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to set domain%d mclk source %d\n", 268*d8d99d8eSRyder Lee domain, ret); 269d6f3710aSGarlic Tseng 270*d8d99d8eSRyder Lee /* Set mclk divider */ 271*d8d99d8eSRyder Lee ret = clk_set_rate(i2s_path->div_ck, mclk); 272d6f3710aSGarlic Tseng if (ret) 273*d8d99d8eSRyder Lee dev_err(afe->dev, "failed to set mclk divider %d\n", ret); 274d6f3710aSGarlic Tseng } 275d6f3710aSGarlic Tseng 276d6f3710aSGarlic Tseng MODULE_DESCRIPTION("MT2701 afe clock control"); 277d6f3710aSGarlic Tseng MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>"); 278d6f3710aSGarlic Tseng MODULE_LICENSE("GPL v2"); 279