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