18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * mt2701-afe-clock-ctrl.c -- Mediatek 2701 afe clock ctrl 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2016 MediaTek Inc. 68c2ecf20Sopenharmony_ci * Author: Garlic Tseng <garlic.tseng@mediatek.com> 78c2ecf20Sopenharmony_ci * Ryder Lee <ryder.lee@mediatek.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "mt2701-afe-common.h" 118c2ecf20Sopenharmony_ci#include "mt2701-afe-clock-ctrl.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistatic const char *const base_clks[] = { 148c2ecf20Sopenharmony_ci [MT2701_INFRA_SYS_AUDIO] = "infra_sys_audio_clk", 158c2ecf20Sopenharmony_ci [MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel", 168c2ecf20Sopenharmony_ci [MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel", 178c2ecf20Sopenharmony_ci [MT2701_TOP_AUD_A1SYS] = "top_audio_a1sys_hp", 188c2ecf20Sopenharmony_ci [MT2701_TOP_AUD_A2SYS] = "top_audio_a2sys_hp", 198c2ecf20Sopenharmony_ci [MT2701_AUDSYS_AFE] = "audio_afe_pd", 208c2ecf20Sopenharmony_ci [MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd", 218c2ecf20Sopenharmony_ci [MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd", 228c2ecf20Sopenharmony_ci [MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd", 238c2ecf20Sopenharmony_ci}; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ciint mt2701_init_clock(struct mtk_base_afe *afe) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci struct mt2701_afe_private *afe_priv = afe->platform_priv; 288c2ecf20Sopenharmony_ci int i; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci for (i = 0; i < MT2701_BASE_CLK_NUM; i++) { 318c2ecf20Sopenharmony_ci afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]); 328c2ecf20Sopenharmony_ci if (IS_ERR(afe_priv->base_ck[i])) { 338c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to get %s\n", base_clks[i]); 348c2ecf20Sopenharmony_ci return PTR_ERR(afe_priv->base_ck[i]); 358c2ecf20Sopenharmony_ci } 368c2ecf20Sopenharmony_ci } 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci /* Get I2S related clocks */ 398c2ecf20Sopenharmony_ci for (i = 0; i < afe_priv->soc->i2s_num; i++) { 408c2ecf20Sopenharmony_ci struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i]; 418c2ecf20Sopenharmony_ci struct clk *i2s_ck; 428c2ecf20Sopenharmony_ci char name[13]; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "i2s%d_src_sel", i); 458c2ecf20Sopenharmony_ci i2s_path->sel_ck = devm_clk_get(afe->dev, name); 468c2ecf20Sopenharmony_ci if (IS_ERR(i2s_path->sel_ck)) { 478c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to get %s\n", name); 488c2ecf20Sopenharmony_ci return PTR_ERR(i2s_path->sel_ck); 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "i2s%d_src_div", i); 528c2ecf20Sopenharmony_ci i2s_path->div_ck = devm_clk_get(afe->dev, name); 538c2ecf20Sopenharmony_ci if (IS_ERR(i2s_path->div_ck)) { 548c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to get %s\n", name); 558c2ecf20Sopenharmony_ci return PTR_ERR(i2s_path->div_ck); 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "i2s%d_mclk_en", i); 598c2ecf20Sopenharmony_ci i2s_path->mclk_ck = devm_clk_get(afe->dev, name); 608c2ecf20Sopenharmony_ci if (IS_ERR(i2s_path->mclk_ck)) { 618c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to get %s\n", name); 628c2ecf20Sopenharmony_ci return PTR_ERR(i2s_path->mclk_ck); 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "i2so%d_hop_ck", i); 668c2ecf20Sopenharmony_ci i2s_ck = devm_clk_get(afe->dev, name); 678c2ecf20Sopenharmony_ci if (IS_ERR(i2s_ck)) { 688c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to get %s\n", name); 698c2ecf20Sopenharmony_ci return PTR_ERR(i2s_ck); 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci i2s_path->hop_ck[SNDRV_PCM_STREAM_PLAYBACK] = i2s_ck; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "i2si%d_hop_ck", i); 748c2ecf20Sopenharmony_ci i2s_ck = devm_clk_get(afe->dev, name); 758c2ecf20Sopenharmony_ci if (IS_ERR(i2s_ck)) { 768c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to get %s\n", name); 778c2ecf20Sopenharmony_ci return PTR_ERR(i2s_ck); 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci i2s_path->hop_ck[SNDRV_PCM_STREAM_CAPTURE] = i2s_ck; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "asrc%d_out_ck", i); 828c2ecf20Sopenharmony_ci i2s_path->asrco_ck = devm_clk_get(afe->dev, name); 838c2ecf20Sopenharmony_ci if (IS_ERR(i2s_path->asrco_ck)) { 848c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to get %s\n", name); 858c2ecf20Sopenharmony_ci return PTR_ERR(i2s_path->asrco_ck); 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci /* Some platforms may support BT path */ 908c2ecf20Sopenharmony_ci afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd"); 918c2ecf20Sopenharmony_ci if (IS_ERR(afe_priv->mrgif_ck)) { 928c2ecf20Sopenharmony_ci if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER) 938c2ecf20Sopenharmony_ci return -EPROBE_DEFER; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci afe_priv->mrgif_ck = NULL; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ciint mt2701_afe_enable_i2s(struct mtk_base_afe *afe, 1028c2ecf20Sopenharmony_ci struct mt2701_i2s_path *i2s_path, 1038c2ecf20Sopenharmony_ci int dir) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci int ret; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci ret = clk_prepare_enable(i2s_path->asrco_ck); 1088c2ecf20Sopenharmony_ci if (ret) { 1098c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret); 1108c2ecf20Sopenharmony_ci return ret; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci ret = clk_prepare_enable(i2s_path->hop_ck[dir]); 1148c2ecf20Sopenharmony_ci if (ret) { 1158c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to enable I2S clock %d\n", ret); 1168c2ecf20Sopenharmony_ci goto err_hop_ck; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci return 0; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cierr_hop_ck: 1228c2ecf20Sopenharmony_ci clk_disable_unprepare(i2s_path->asrco_ck); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return ret; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_civoid mt2701_afe_disable_i2s(struct mtk_base_afe *afe, 1288c2ecf20Sopenharmony_ci struct mt2701_i2s_path *i2s_path, 1298c2ecf20Sopenharmony_ci int dir) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci clk_disable_unprepare(i2s_path->hop_ck[dir]); 1328c2ecf20Sopenharmony_ci clk_disable_unprepare(i2s_path->asrco_ck); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ciint mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci struct mt2701_afe_private *afe_priv = afe->platform_priv; 1388c2ecf20Sopenharmony_ci struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci return clk_prepare_enable(i2s_path->mclk_ck); 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_civoid mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci struct mt2701_afe_private *afe_priv = afe->platform_priv; 1468c2ecf20Sopenharmony_ci struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id]; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci clk_disable_unprepare(i2s_path->mclk_ck); 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ciint mt2701_enable_btmrg_clk(struct mtk_base_afe *afe) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci struct mt2701_afe_private *afe_priv = afe->platform_priv; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci return clk_prepare_enable(afe_priv->mrgif_ck); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_civoid mt2701_disable_btmrg_clk(struct mtk_base_afe *afe) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci struct mt2701_afe_private *afe_priv = afe->platform_priv; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->mrgif_ck); 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic int mt2701_afe_enable_audsys(struct mtk_base_afe *afe) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci struct mt2701_afe_private *afe_priv = afe->platform_priv; 1688c2ecf20Sopenharmony_ci int ret; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci /* Enable infra clock gate */ 1718c2ecf20Sopenharmony_ci ret = clk_prepare_enable(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); 1728c2ecf20Sopenharmony_ci if (ret) 1738c2ecf20Sopenharmony_ci return ret; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* Enable top a1sys clock gate */ 1768c2ecf20Sopenharmony_ci ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 1778c2ecf20Sopenharmony_ci if (ret) 1788c2ecf20Sopenharmony_ci goto err_a1sys; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* Enable top a2sys clock gate */ 1818c2ecf20Sopenharmony_ci ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 1828c2ecf20Sopenharmony_ci if (ret) 1838c2ecf20Sopenharmony_ci goto err_a2sys; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci /* Internal clock gates */ 1868c2ecf20Sopenharmony_ci ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 1878c2ecf20Sopenharmony_ci if (ret) 1888c2ecf20Sopenharmony_ci goto err_afe; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 1918c2ecf20Sopenharmony_ci if (ret) 1928c2ecf20Sopenharmony_ci goto err_audio_a1sys; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 1958c2ecf20Sopenharmony_ci if (ret) 1968c2ecf20Sopenharmony_ci goto err_audio_a2sys; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]); 1998c2ecf20Sopenharmony_ci if (ret) 2008c2ecf20Sopenharmony_ci goto err_afe_conn; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci return 0; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cierr_afe_conn: 2058c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 2068c2ecf20Sopenharmony_cierr_audio_a2sys: 2078c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 2088c2ecf20Sopenharmony_cierr_audio_a1sys: 2098c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 2108c2ecf20Sopenharmony_cierr_afe: 2118c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 2128c2ecf20Sopenharmony_cierr_a2sys: 2138c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 2148c2ecf20Sopenharmony_cierr_a1sys: 2158c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci return ret; 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic void mt2701_afe_disable_audsys(struct mtk_base_afe *afe) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci struct mt2701_afe_private *afe_priv = afe->platform_priv; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]); 2258c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]); 2268c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]); 2278c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]); 2288c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]); 2298c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]); 2308c2ecf20Sopenharmony_ci clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]); 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ciint mt2701_afe_enable_clock(struct mtk_base_afe *afe) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci int ret; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci /* Enable audio system */ 2388c2ecf20Sopenharmony_ci ret = mt2701_afe_enable_audsys(afe); 2398c2ecf20Sopenharmony_ci if (ret) { 2408c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to enable audio system %d\n", ret); 2418c2ecf20Sopenharmony_ci return ret; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci regmap_update_bits(afe->regmap, ASYS_TOP_CON, 2458c2ecf20Sopenharmony_ci ASYS_TOP_CON_ASYS_TIMING_ON, 2468c2ecf20Sopenharmony_ci ASYS_TOP_CON_ASYS_TIMING_ON); 2478c2ecf20Sopenharmony_ci regmap_update_bits(afe->regmap, AFE_DAC_CON0, 2488c2ecf20Sopenharmony_ci AFE_DAC_CON0_AFE_ON, 2498c2ecf20Sopenharmony_ci AFE_DAC_CON0_AFE_ON); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci /* Configure ASRC */ 2528c2ecf20Sopenharmony_ci regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL); 2538c2ecf20Sopenharmony_ci regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci return 0; 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ciint mt2701_afe_disable_clock(struct mtk_base_afe *afe) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci regmap_update_bits(afe->regmap, ASYS_TOP_CON, 2618c2ecf20Sopenharmony_ci ASYS_TOP_CON_ASYS_TIMING_ON, 0); 2628c2ecf20Sopenharmony_ci regmap_update_bits(afe->regmap, AFE_DAC_CON0, 2638c2ecf20Sopenharmony_ci AFE_DAC_CON0_AFE_ON, 0); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci mt2701_afe_disable_audsys(afe); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci return 0; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ciint mt2701_mclk_configuration(struct mtk_base_afe *afe, int id) 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci struct mt2701_afe_private *priv = afe->platform_priv; 2748c2ecf20Sopenharmony_ci struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id]; 2758c2ecf20Sopenharmony_ci int ret = -EINVAL; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* Set mclk source */ 2788c2ecf20Sopenharmony_ci if (!(MT2701_PLL_DOMAIN_0_RATE % i2s_path->mclk_rate)) 2798c2ecf20Sopenharmony_ci ret = clk_set_parent(i2s_path->sel_ck, 2808c2ecf20Sopenharmony_ci priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]); 2818c2ecf20Sopenharmony_ci else if (!(MT2701_PLL_DOMAIN_1_RATE % i2s_path->mclk_rate)) 2828c2ecf20Sopenharmony_ci ret = clk_set_parent(i2s_path->sel_ck, 2838c2ecf20Sopenharmony_ci priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (ret) { 2868c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to set mclk source\n"); 2878c2ecf20Sopenharmony_ci return ret; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* Set mclk divider */ 2918c2ecf20Sopenharmony_ci ret = clk_set_rate(i2s_path->div_ck, i2s_path->mclk_rate); 2928c2ecf20Sopenharmony_ci if (ret) { 2938c2ecf20Sopenharmony_ci dev_err(afe->dev, "failed to set mclk divider %d\n", ret); 2948c2ecf20Sopenharmony_ci return ret; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci return 0; 2988c2ecf20Sopenharmony_ci} 299